diff options
Diffstat (limited to 'gcc/config/m88k')
33 files changed, 0 insertions, 11394 deletions
diff --git a/gcc/config/m88k/dgux.h b/gcc/config/m88k/dgux.h deleted file mode 100755 index 186735b..0000000 --- a/gcc/config/m88k/dgux.h +++ /dev/null @@ -1,305 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola m88100 running DG/UX. - Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@mcc.com) - Currently maintained by (gcc@dg-rtp.dg.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. */ - -/* You're not seeing double! To transition to dwarf debugging, both are - supported. The option -msvr4 specifies elf. With these combinations, - -g means dwarf. */ -/* DWARF_DEBUGGING_INFO defined in svr4.h. */ -#define SDB_DEBUGGING_INFO -#define PREFERRED_DEBUGGING_TYPE \ - (TARGET_SVR4 ? DWARF_DEBUG : SDB_DEBUG) - -#ifndef VERSION_INFO2 -#define VERSION_INFO2 "$Revision: 1.54 $" -#endif -#ifndef NO_BUGS -#define AS_BUG_IMMEDIATE_LABEL -/* The DG/UX 4.30 assembler doesn't accept the symbol `fcr63'. */ -#define AS_BUG_FLDCR -#endif - -#include "svr4.h" -#include "m88k/m88k.h" - -/* Augment TARGET_SWITCHES with the MXDB options. */ -#define MASK_STANDARD 0x40000000 /* Retain standard information */ -#define MASK_NOLEGEND 0x20000000 /* Discard legend information */ -#define MASK_EXTERNAL_LEGEND 0x10000000 /* Make external legends */ - -#define TARGET_STANDARD (target_flags & MASK_STANDARD) -#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND) -#define TARGET_EXTERNAL_LEGEND (target_flags & MASK_EXTERNAL_LEGEND) - -#undef SUBTARGET_SWITCHES -#define SUBTARGET_SWITCHES \ - { "standard", MASK_STANDARD }, \ - { "legend", -MASK_NOLEGEND }, \ - { "no-legend", MASK_NOLEGEND }, \ - { "external-legend", MASK_EXTERNAL_LEGEND }, \ - /* the following is used only in the *_SPEC's */ \ - { "keep-coff", 0 }, - -/* Default switches */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_CHECK_ZERO_DIV | \ - MASK_OCS_DEBUG_INFO | \ - MASK_OCS_FRAME_POSITION | \ - MASK_STANDARD | \ - MASK_SVR4) -#undef CPU_DEFAULT -#define CPU_DEFAULT MASK_88000 - -/* Macros to be automatically defined. __svr4__ is our extension. - __CLASSIFY_TYPE__ is used in the <varargs.h> and <stdarg.h> header - files with DG/UX revision 5.40 and later. This allows GNU CC to - operate without installing the header files. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dm88000 -Dm88k -Dunix -DDGUX -D__CLASSIFY_TYPE__=2\ - -D__svr4__ -Asystem(unix) -Acpu(m88k) -Amachine(m88k)" - -/* If -m88100 is in effect, add -Dm88100; similarly for -m88110. - Here, the CPU_DEFAULT is assumed to be -m88000. If not -ansi, - -traditional, or restricting include files to one specific source - target, specify full DG/UX features. */ -#undef CPP_SPEC -#define CPP_SPEC "%(cpp_cpu) %{msvr3:-D_M88KBCS_TARGET} %{!msvr3:-D_DGUX_TARGET}" - -/* Assembler support (-V, silicon filter, legends for mxdb). */ -#undef ASM_SPEC -#define ASM_SPEC "%{pipe:%{!.s: - }\ - %{!msvr3:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\ - %(asm_cpu)" - -/* Override svr4.h. */ -#undef ASM_FINAL_SPEC -#undef STARTFILE_SPEC - -/* Linker and library spec's. - -msvr4 is the default if -msvr3 is not specified. - -static, -shared, -symbolic, -h* and -z* access AT&T V.4 link options. - -svr4 instructs gcc to place /usr/lib/values-X[cat].o on the link line. - -msvr3 indicates linking done in a COFF environment and the link - script is added to the link line. In all environments, the first - and last objects are crtbegin.o (or bcscrtbegin.o) and crtend.o. - When the -G link option is used (-shared and -symbolic) a final - link is not being done. */ -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s" -#undef LIB_SPEC -#define LIB_SPEC "%{!msvr3:%{!shared:-lstaticdgc}} %{!shared:%{!symbolic:-lc}}" -#undef LINK_SPEC -#define LINK_SPEC "%{z*} %{h*} %{v:-V} \ - %{static:-dn -Bstatic} \ - %{shared:-G -dy} \ - %{symbolic:-Bsymbolic -G -dy} \ - %{pg:-L/usr/lib/libp}%{p:-L/usr/lib/libp}" -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "%(startfile_default)" - - -/* 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", CPP_CPU_SPEC }, \ - { "asm_cpu", ASM_CPU_SPEC }, \ - { "startfile_default", STARTFILE_DEFAULT_SPEC }, \ - { "startfile_crtbegin", STARTFILE_CRTBEGIN_SPEC } - -/* Keep this left justified, no white space is allowed between - the arguments to the -Wc option */ -#define ASM_CPU_SPEC "\ - %{v:-V}\ - %{g:\ -%{mno-legend:-Wc,off}\ -%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\ -%{traditional:,-lc}\ -%{!traditional:,-lansi-c}\ -%{mstandard:,-keep-std}\ -%{mexternal-legend:,-external}\ -%{mocs-frame-position:,-ocs}}}" - -#define CPP_CPU_SPEC "\ - %{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \ - %{!m88000:%{!m88110:%{m88100:-D__m88100__}}} \ - %{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}" - -#define STARTFILE_DEFAULT_SPEC "\ - %{!shared:%{!symbolic:%{pg:gcrt0.o%s} \ - %{!pg:%{p:/lib/mcrt0.o}%{!p:/lib/crt0.o}} \ - %(startfile_crtbegin) \ - %{svr4:%{ansi:/lib/values-Xc.o} \ - %{!ansi:%{traditional:/lib/values-Xt.o} \ - %{!traditional:/usr/lib/values-Xa.o}}}}}" - -#define STARTFILE_CRTBEGIN_SPEC "\ - %{msvr3:m88kdgux.ld%s bcscrtbegin.o%s} \ - %{!msvr3:crtbegin.o%s}" - -#undef GPLUSPLUS_INCLUDE_DIR -#define GPLUSPLUS_INCLUDE_DIR "/usr/opt/g++/lib/g++-include" - -/* Fast DG/UX version of profiler that does not require lots of - registers to be stored. */ -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - output_function_profiler (FILE, LABELNO, "gcc.mcount", 0) - -/* Output the legend info for mxdb when debugging except if standard - debugging information only is explicitly requested. */ -#undef ASM_FIRST_LINE -#define ASM_FIRST_LINE(FILE) \ - do { \ - if (TARGET_SVR4) \ - { \ - if (TARGET_88110) \ - fprintf (FILE, "\t%s\t \"%s\"\n", VERSION_ASM_OP, "04.00"); \ - else \ - fprintf (FILE, "\t%s\t \"%s\"\n", VERSION_ASM_OP, "03.00"); \ - } \ - if (write_symbols != NO_DEBUG && !TARGET_NOLEGEND) \ - { \ - fprintf (FILE, ";legend_info -fix-bb -h\"gcc-%s\" -s\"%s\"", \ - VERSION_STRING, main_input_filename); \ - fputs (flag_traditional ? " -lc" : " -lansi-c", FILE); \ - if (TARGET_STANDARD) \ - fputs (" -keep-std", FILE); \ - if (TARGET_EXTERNAL_LEGEND) \ - fputs (" -external", FILE); \ - if (TARGET_OCS_FRAME_POSITION) \ - fputs (" -ocs", FILE); \ - fputc ('\n', FILE); \ - } \ - } while (0) - -/* Override svr4.h. */ -#undef PTRDIFF_TYPE -#undef WCHAR_TYPE -#undef WCHAR_TYPE_SIZE - -/* Override svr4.h and m88k.h except when compiling crtstuff.c. These must - be constant strings when compiling crtstuff.c. Otherwise, respect the - -mversion-STRING option used. */ -#undef INIT_SECTION_PREAMBLE -#undef INIT_SECTION_ASM_OP -#undef FINI_SECTION_ASM_OP -#undef CTORS_SECTION_ASM_OP -#undef DTORS_SECTION_ASM_OP - -#if defined (CRT_BEGIN) || defined (CRT_END) || defined (L__main) -/* routines to invoke global constructors and destructors are always COFF - to enable linking mixed COFF and ELF objects */ -#define FINI_SECTION_ASM_OP ("section .fini,\"x\"") -#ifndef BCS -#define INIT_SECTION_PREAMBLE asm ("\taddu\tr31,r31,0x20") -#endif -#undef INIT_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP ("section\t .init,\"x\"") -#undef CTORS_SECTION_ASM_OP -#define CTORS_SECTION_ASM_OP ("section\t .ctors,\"d\"") -#undef DTORS_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP ("section\t .dtors,\"d\"") -#undef OBJECT_FORMAT_ELF -#else -#undef INIT_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP (TARGET_SVR4 \ - ? "section\t .init,\"xa\"" \ - : "section\t .init,\"x\"") -#undef CTORS_SECTION_ASM_OP -#define CTORS_SECTION_ASM_OP (TARGET_SVR4 \ - ? "section\t .ctors,\"aw\"" \ - : "section\t .ctors,\"d\"") -#undef DTORS_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP (TARGET_SVR4 \ - ? "section\t .dtors,\"aw\"" \ - : "section\t .dtors,\"d\"") -#endif /* crtstuff.c */ - -/* The lists of global object constructors and global destructors are always - placed in the .ctors/.dtors sections. This requires the use of a link - script if the COFF linker is used, but otherwise COFF and ELF objects - can be intermixed. A COFF object will pad the section to 16 bytes with - zeros; and ELF object will not contain padding. We deal with this by - putting a -1 marker at the begin and end of the list and ignoring zero - entries. */ - -/* Mark the end of the .ctors/.dtors sections with a -1. */ - -#define CTOR_LIST_BEGIN \ -asm (CTORS_SECTION_ASM_OP); \ -func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) } - -#define CTOR_LIST_END \ -asm (CTORS_SECTION_ASM_OP); \ -func_ptr __CTOR_END__[1] = { (func_ptr) (-1) } - -#define DTOR_LIST_BEGIN \ -asm (DTORS_SECTION_ASM_OP); \ -func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) } - -#define DTOR_LIST_END \ -asm (DTORS_SECTION_ASM_OP); \ -func_ptr __DTOR_END__[1] = { (func_ptr) (-1) } - -/* Walk the list ignoring NULL entries till we hit the terminating -1. */ -#define DO_GLOBAL_CTORS_BODY \ - do { \ - int i; \ - for (i=1;(int)(__CTOR_LIST__[i]) != -1; i++) \ - if (((int *)__CTOR_LIST__)[i] != 0) \ - __CTOR_LIST__[i] (); \ - } while (0) - -/* Walk the list looking for the terminating -1 that marks the end. - Go backward and ignore any NULL entries. */ -#define DO_GLOBAL_DTORS_BODY \ - do { \ - int i; \ - for (i=1;(int)(__DTOR_LIST__[i]) != -1; i++); \ - for (i-=1;(int)(__DTOR_LIST__[i]) != -1; i--) \ - if (((int *)__DTOR_LIST__)[i] != 0) \ - __DTOR_LIST__[i] (); \ - } while (0) - -/* The maximum alignment which the object file format can support. - page alignment would seem to be enough */ -#undef MAX_OFILE_ALIGNMENT -#define MAX_OFILE_ALIGNMENT 0x1000 - -/* Must use data section for relocatable constants when pic. */ -#undef SELECT_RTX_SECTION -#define SELECT_RTX_SECTION(MODE,RTX) \ -{ \ - if (flag_pic && symbolic_operand (RTX)) \ - data_section (); \ - else \ - const_section (); \ -} diff --git a/gcc/config/m88k/dgux.ld b/gcc/config/m88k/dgux.ld deleted file mode 100755 index cc5dc0f..0000000 --- a/gcc/config/m88k/dgux.ld +++ /dev/null @@ -1,48 +0,0 @@ -/* m88kdgux.ld - COFF linker directives for G++ on an AViiON - - 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. - - On The AViiON we start the output .text section somewhere after the - first 64kb (0x10000) of logical address space so that the first - 64kb can be mapped out, thus catching references through null - pointers. We actually start at 0x10200 (for efficiency). Ideally, - we want the page offset of a given word of the .text (output) - section to be the same as its page offset in the actual (output) - linked core file so that paging of the .text section is efficient. - In order to do this we allow for up to 0x200 bytes of header stuff - in the output (linked) object file. - - For .data, the OCS says that regions with different "protections" - (i.e. read/write, read-only) should not share any 4 megabyte chunk - of the logical address space, so we start the .data segment at the - first (lowest) 4 MB boundary past the end of the .text segment. - - For some reason, you can't start right at the 4 MB boundary. You - have to start at some distance past that. The distance must be - equal to the distance from the start of the last 64 KB segment in - the (output) .text segment to the actual end of the (output) .text - segment. */ - -SECTIONS { - .text 0x10200 BLOCK(0x200) : - { *(.init) *(.initp) *(.finip) *(.text) *(.tdesc) } - - GROUP BIND (((((ADDR(.text) + SIZEOF(.text) - 1) / 0x400000) + 1) * 0x400000) + ((ADDR(.text) + SIZEOF (.text)) % 0x10000)) : - { .data : { *(.data) *(.ctors) *(.dtors) } - .bss : {} } -} diff --git a/gcc/config/m88k/dguxbcs.h b/gcc/config/m88k/dguxbcs.h deleted file mode 100755 index 00ef9b3..0000000 --- a/gcc/config/m88k/dguxbcs.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola m88100 running DG/UX. - Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@mcc.com) - Currently maintained by (gcc@dg-rtp.dg.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 "m88k/dgux.h" - -/* dgux.h builds an elf gcc which compiles elf objects by default. - dguxbcs.h builds a bcs gcc which compiles bcs objects by default. - The default can be overridden in either case with -msvr3 and -msvr4 */ - -/* Default switches */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_CHECK_ZERO_DIV | \ - MASK_OCS_DEBUG_INFO | \ - MASK_OCS_FRAME_POSITION | \ - MASK_SVR3) - -/* Assembler support (-V, silicon filter, legends for mxdb). */ -#undef ASM_SPEC -#define ASM_SPEC "%{pipe:%{!.s: - }\ - %{msvr4:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\ - %(asm_cpu)" - -/* If -m88100 is in effect, add -Dm88100; similarly for -m88110. - Here, the CPU_DEFAULT is assumed to be -m88000. If not -ansi, - -traditional, or restricting include files to one specific source - target, specify full DG/UX features. */ -#undef CPP_SPEC -#define CPP_SPEC "%(cpp_cpu) - %{!msvr4:-D_M88KBCS_TARGET} %{msvr4:-D_DGUX_TARGET}" - -/* Linker and library spec's. - -msvr3 is the default if -msvr4 is not specified. */ -#undef LIB_SPEC -#define LIB_SPEC "%{msvr4:%{!shared:-lstaticdgc}} %{!shared:%{!symbolic:-lc}}" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "%(startfile_default)" - -#undef STARTFILE_CRTBEGIN_SPEC -#define STARTFILE_CRTBEGIN_SPEC "\ - %{!msvr4:m88kdgux.ld%s bcscrtbegin.o%s} \ - %{msvr4:crtbegin.o%s}" diff --git a/gcc/config/m88k/dolph.h b/gcc/config/m88k/dolph.h deleted file mode 100755 index bd77227..0000000 --- a/gcc/config/m88k/dolph.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola m88100 running the Dolphin UNIX System V/88 Release 3.2, - Version 3.8/7.83 and 3.6/5.86 - Copyright (C) 1992, 1993, 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 "m88k/sysv3.h" - -#define SDB_ALLOW_FORWARD_REFERENCES -#define SDB_ALLOW_UNKNOWN_REFERENCES - -/* Override m88k/sysv3.h */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dm88000 -Dm88k -DOCS88 -DDOLPHIN -Dunix -DsysV88 -D__CLASSIFY_TYPE__=2 -Asystem(unix) -Asystem(svr3) -Acpu(m88k) -Amachine(m88k)" - -/* - If you want to detect dereferencing of NULL pointers, uncomment the - following two lines. Alternatively, edit the appropriate specs file. - - #undef LINK_SPEC - #define LINK_SPEC "gcc.ld%s" - - */ - -#undef CPU_DEFAULT -#define CPU_DEFAULT MASK_88000 diff --git a/gcc/config/m88k/dolphin.ld b/gcc/config/m88k/dolphin.ld deleted file mode 100755 index ce5c8f0..0000000 --- a/gcc/config/m88k/dolphin.ld +++ /dev/null @@ -1,40 +0,0 @@ -/* COFF linker directives for the Dolphin Triton88 for GNU compiler. - Copyright (C) 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. */ - - -/* This file does the following: - - - Sets VIRTUAL addr of .text to 0x400200 - Sets FILE addr of .text to 0x200 (BLOCK directive) - - Depending on size of .text section rounds up to next - 4 MG boundary, adds (size of .text and vaddr of .text) mod 64K - This is to handle sections larger than 4 MG. */ - -SECTIONS { - .text 0x400200 BLOCK (0x200): - { *(.init) *(.text) *(.rodata) *(.tdesc) *(.fini)} - - GROUP BIND( (((SIZEOF(.text)+ADDR(.text)) / 0x400000 * 0x400000) + 0x400000) + - ((SIZEOF(.text) + ADDR(.text)) % 0x10000) ) : - { - .data : { } - .bss : { } - } -} diff --git a/gcc/config/m88k/luna.h b/gcc/config/m88k/luna.h deleted file mode 100755 index ab6dbde..0000000 --- a/gcc/config/m88k/luna.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola m88100 running Omron Luna/88k. - Copyright (C) 1991, 1997 Free Software Foundation, Inc. - Contributed by Jeffrey Friedl (jfriedl@omron.co.jp) - -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. */ - -/* The Omron Luna/88k is MACH and uses BSD a.out, not COFF or ELF. */ -#ifndef MACH -#define MACH -#endif -#define DBX_DEBUGGING_INFO -#define DEFAULT_GDB_EXTENSIONS 0 - -#include "aoutos.h" -#include "m88k/m88k.h" - -/* Identify the compiler. */ -#undef VERSION_INFO1 -#define VERSION_INFO1 "Omron Luna/88k, " - -/* Macros to be automatically defined. */ -#undef CPP_PREDEFINES -#define CPP_PREDEFINES \ - "-DMACH -Dm88k -Dunix -Dluna -Dluna88k -D__CLASSIFY_TYPE__=2 -Asystem(unix) -Asystem(mach) -Acpu(m88k) -Amachine(m88k)" - -/* If -m88000 is in effect, add -Dmc88000; similarly for -m88100 and -m88110. - However, reproduce the effect of -Dmc88100 previously in CPP_PREDEFINES. - Here, the CPU_DEFAULT is assumed to be -m88100. */ -#undef CPP_SPEC -#define CPP_SPEC "%{m88000:-D__mc88000__} \ - %{!m88000:%{m88100:%{m88110:-D__mc88000__}}} \ - %{!m88000:%{!m88100:%{m88110:-D__mc88110__}}} \ - %{!m88000:%{!m88110:%{!ansi:%{traditional:-Dmc88100}} \ - -D__mc88100__ -D__mc88100}}" - -/* Specify extra dir to search for include files. */ -#undef SYSTEM_INCLUDE_DIR -#define SYSTEM_INCLUDE_DIR "/usr/mach/include" - -/* For the Omron Luna/88k, a float function returns a double in traditional - mode (and a float in ansi mode). */ -#undef TRADITIONAL_RETURN_FLOAT diff --git a/gcc/config/m88k/m88k-aout.h b/gcc/config/m88k/m88k-aout.h deleted file mode 100755 index 90f3fe7..0000000 --- a/gcc/config/m88k/m88k-aout.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Definitions for "naked" Motorola 88k using a.out object format files - and stabs debugging info. - - 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. */ - -#undef SDB_DEBUGGING_INFO -#define DBX_DEBUGGING_INFO - -#include "m88k/m88k.h" -#include "aoutos.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dm88000 -Dm88k -Acpu(m88k) -Amachine(m88k)" - -/* end of m88k-aout.h */ diff --git a/gcc/config/m88k/m88k-coff.h b/gcc/config/m88k/m88k-coff.h deleted file mode 100755 index d32e1d9..0000000 --- a/gcc/config/m88k/m88k-coff.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Definitions for "naked" Motorola 88k using coff object format files - and coff debugging info. - - 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 "m88k/m88k.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dm88000 -Dm88k -Acpu(m88k) -Amachine(m88k)" - -#define SDB_DEBUGGING_INFO - -/* Output DBX (stabs) debugging information if using -gstabs. */ - -#include "dbxcoff.h" - -/* end of m88k-coff.h */ diff --git a/gcc/config/m88k/m88k-move.sh b/gcc/config/m88k/m88k-move.sh deleted file mode 100755 index 5e757bd..0000000 --- a/gcc/config/m88k/m88k-move.sh +++ /dev/null @@ -1,306 +0,0 @@ -#!/bin/sh -# -# If your shell doesn't support functions (true for some BSD users), -# you might try using GNU's bash. -# -#ident "@(#) m88k-move.sh 1-Sep-92" -# -# This file provided by Data General, February 1990. -# -# This script generates the necessary movstr library functions -# for the m88100. These functions are called from the expansion -# of movstrsi. There are eight modules created by this script, -# each with multiple entry points. One module, moveSI64n -# implements a word aligned loop; the other modules, moveXINx -# implement a straight line copy of N bytes in mode XI. -# -# By analysis of the best memcpy function, it can be determined -# what appear to be certain magic numbers. For example, a -# memcpy of 13 bytes, where the pointers are determined at run -# time to be word aligned takes 28 cycles. A call to -# __movstrQI13x13 also takes 28 cycles. The break even point -# for a HImode copy is 38 bytes. Just to be on the safe side, -# these are bumped to 16 and 48 respectively. -# -# The smaller, odd-remainder modules are provided to help -# mitigate the overhead of copying the last bytes. -# -# Changes to these functions should not be taken lightly if you -# want to be able to link programs built with older movstr -# parameters. -# -#.Revision History -# -# 1-Sep-92 Stan Cox Added moveDI96x, moveDI41x through moveDI47x. -# 2-Jan-92 Tom Wood Renamed files to comply with SVR3 14 char limit. -# 26-Oct-90 Tom Wood Delete movstr.h; moved to out-m88k.c. -# 17-Oct-90 Tom Wood Files are named *.asm rather than *.s. -# 11-Sep-90 Jeffrey Friedl -# On my BSD 4.3 awk and my GNU-awk, only the -# first character of an argument to -F is passed -# through, so I can't get this to work. -# 5-Sep-90 Ray Essick/Tom Wood -# Added a -no-tdesc option. -# 27-Aug-90 Vince Guarna/Tom Wood -# Version 3 assembler syntax (-abi). -# 16-Aug-90 Ron Guilmette -# Avoid problems on a Sparc. The common -# denominator among shells seems to be '...\' -# rather than '...\\'. -# 15-Aug-90 Ron Guilmette -# Avoid awk syntax errors on a Sun by not using -# the `!' operator. -# 22-Feb-90 Tom Wood Created. -# 20-Jun-90 Tom Wood Emit file directives. -# -#.End]=--------------------------------------------------------------*/ - -usage() { - echo "usage: $0 [ -abi ] [ -no-tdesc ]" 1>&2 - exit 1 -} - -awk_flag="-F:"; -awk_begin="BEGIN { " -ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt=""; -do_file() { - echo " file $1"; -} - -while [ $# -gt 0 ] ; do - case $1 in - -no-tdesc) awk_begin="$awk_begin no_tdesc=1;" - nt=";";; - -abi) awk_begin="$awk_begin abi=1;" - ps="#"; us=""; tf="a"; la=".L"; fb="16"; - do_file() { - echo ' version "03.00"'; - echo " file $1"; - };; - *) usage;; - esac - shift -done - -rm -f move?I*[xn].s move?I*[xn].asm - -#.Implementation_continued[=----------------------------------------------- -# -# This generates the word aligned loop. The loop is entered -# from the callable entry points ___movstrSI64nN, where at -# least N bytes will be copied. r2 is the destination pointer -# offset by 4, r3 is the source pointer offset by 4, r6 is the -# loop count. Thus, the total bytes moved is 64 * r6 + N. The -# first value is preloaded into r4 or r5 (r4 if N/4 is odd; -# r5 if N/4 is even). Upon returning, r2 and r3 have been -# updated and may be used for the remainder bytes to move. -# -# The code for this loop is generated by the awk program -# following. Edit *it*, not what it generates! -# -#.End]=------------------------------------------------------------------*/ - -gen_movstrN() { - awk $awk_flag "$awk_begin"' - if (abi) { - ps="#"; us=""; tf="a"; la=".L"; fb=16; - } else { - ps=""; us="_"; tf="x"; la="@L"; fb=8; - } - } - NR == 1 && NF == 4 { - mode = $1; suffix = $2; align = $3; count = $4; - ld = align; st = 0; - - printf "; The following was calculated using awk.\n"; - printf "\ttext\n"; - printf "\talign\t%d\n", fb; - printf "%sloop%s%d:\n", la, mode, count * align; - printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; - printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; - printf "\tsubu\t%sr6,%sr6,1\n", ps, ps; - for (r = count + 1; r >= 1; r--) { - evenp = r % 2; - name = sprintf("__%smovstr%s%dn%d", us, mode, count * align, r * align); - if (r > 1) { - printf "\tglobal\t%s\n", name; - printf "%s:\n", name; - } - if (r > 2) { - printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; - printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; - } else if (r == 2) { - printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; - printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align; - printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; - printf "\tjmp.n\t%sr1\n", ps; - } else { - printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; - } - ld += align; st += align; - } - if (!no_tdesc) { - printf "%send%s%d:\n", la, mode, count * align; - printf "\tsection\t.tdesc,\"%s\"\n", tf; - printf "\tword\t0x42,1,%sloop%s%d", la, mode, count * align; - printf ",%send%s%d\n", la, mode, count * align; - printf "\tword\t0x0100001f,0,1,0\n"; - printf "\ttext\n"; - } - printf "; End of awk generated code.\n"; - exit; - }' -} - -(do_file '"movstrSI64n.s"'; - echo 'SI::4:16' | gen_movstrN) > moveSI64n.asm - -#.Implementation_continued[=----------------------------------------------- -# -# This generates the even-remainder, straight-line modules. -# The code is entered from the callable entry points -# ___movstrXINxM, where exactly M bytes will be copied in XI -# mode. r2 is the destination pointer, r3 is the source -# pointer, neither being offset. The first value is preloaded -# into r4 or r5 (r4 if M-N/B is even; r5 if M-N/B is odd, where -# B is the mode size of XI). Upon returning, r2 and r3 have not -# been changed. -# -# The code for these cases is generated by the awk program -# following. Edit *it*, not what it generates! -# -#.End]=------------------------------------------------------------------*/ - -gen_movstrX0() { - awk $awk_flag "$awk_begin"' - if (abi) { - ps="#"; us=""; tf="a"; la=".L"; fb=16; - } else { - ps=""; us="_"; tf="x"; la="@L"; fb=8; - } - } - NR == 1 && NF == 4 { - mode = $1; suffix = $2; align = $3; bytes = $4; - ld = align; st = 0; count = bytes / align; - reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; - printf "; The following was calculated using awk.\n"; - printf "\ttext\n"; - printf "\talign\t%d\n", fb; - for (r = count; r >= 1; r--) { - evenp = r % 2; - name = sprintf("__%smovstr%s%dx%d", us, mode, count * align, r * align); - if (r > 1) { - printf "\tglobal\t%s\n", name; - printf "%s:\n", name; - } - if (r == 1) - printf "\tjmp.n\t%sr1\n", ps; - else - printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, reg[evenp], ps, ld; - printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, reg[1-evenp], ps, st; - ld += align; st += align; - } - if (!no_tdesc) { - printf "%send%s%dx:\n", la, mode, count * align; - printf "\tsection\t.tdesc,\"%s\"\n", tf; - printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, count * align, count * align; - printf ",%send%s%dx\n", la, mode, count * align; - printf "\tword\t0x0100001f,0,1,0\n"; - printf "\ttext\n"; - } - printf "; End of awk generated code.\n" - exit; - }' -} - -(do_file '"movstrQI16x.s"'; - echo 'QI:.b:1:16' | gen_movstrX0) > moveQI16x.asm -(do_file '"movstrHI48x.s"'; - echo 'HI:.h:2:48' | gen_movstrX0) > moveHI48x.asm -(do_file '"movstrSI96x.s"'; - echo 'SI::4:96' | gen_movstrX0) > moveSI96x.asm -(do_file '"movstrDI96x.s"'; - echo 'DI:.d:8:96' | gen_movstrX0) > moveDI96x.asm - -#.Implementation_continued[=----------------------------------------------- -# -# This generates the odd-remainder, straight-line modules. The -# interface is the same as that for the even-remainder modules. -# -#.End]=------------------------------------------------------------------*/ - -gen_movstrXr() { - awk $awk_flag "$awk_begin"' - if (abi) { - ps="#"; us=""; tf="a"; la=".L"; fb=16; - } else { - ps=""; us="_"; tf="x"; la="@L"; fb=8; - } - } - NR == 1 && NF == 4 { - mode = $1; rem = $2; most = $3; count = $4; - suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d"; - - prev = align = most; - ld = align; st = 0; total = count - rem - most; - evenp = int(total/align) % 2; - reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; - printf "; The following was calculated using awk.\n"; - printf "\ttext\n"; - printf "\talign\t%d\n", fb; - for (bytes = total; bytes >= 0; bytes -= align) { - if (bytes < align) { - if (bytes >= 4) align = 4; - else if (bytes >= 2) align = 2; - else align = 1; - } - name = sprintf("__%smovstr%s%dx%d", us, mode, total + most, bytes + most); - if (bytes > most) { - printf "\tglobal\t%s\n", name; - printf "%s:\n", name; - } - if (bytes == 0) - printf "\tjmp.n\t%sr1\n", ps; - else - printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, reg[evenp], ps, ld; - printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, reg[1-evenp], ps, st; - ld += align; st += prev; prev = align; - evenp = 1 - evenp; - } - if (!no_tdesc) { - printf "%send%s%dx:\n", la, mode, total + most; - printf "\tsection\t.tdesc,\"%s\"\n", tf; - printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, total + most, total + most; - printf ",%send%s%dx\n", la, mode, total + most; - printf "\tword\t0x0100001f,0,1,0\n"; - printf "\ttext\n"; - } - printf "; End of awk generated code.\n" - exit; - }' -} - -(do_file '"movstrDI47x.s"'; - echo 'DI:1:8:48' | gen_movstrXr) > moveDI47x.asm -(do_file '"movstrDI46x.s"'; - echo 'DI:2:8:48' | gen_movstrXr) > moveDI46x.asm -(do_file '"movstrDI45x.s"'; - echo 'DI:3:8:48' | gen_movstrXr) > moveDI45x.asm -(do_file '"movstrDI44x.s"'; - echo 'DI:4:8:48' | gen_movstrXr) > moveDI44x.asm -(do_file '"movstrDI43x.s"'; - echo 'DI:5:8:48' | gen_movstrXr) > moveDI43x.asm -(do_file '"movstrDI42x.s"'; - echo 'DI:6:8:48' | gen_movstrXr) > moveDI42x.asm -(do_file '"movstrDI41x.s"'; - echo 'DI:7:8:48' | gen_movstrXr) > moveDI41x.asm - -(do_file '"movstrSI47x.s"'; - echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm -(do_file '"movstrSI46x.s"'; - echo 'SI:2:4:48' | gen_movstrXr) > moveSI46x.asm -(do_file '"movstrSI45x.s"'; - echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm - -(do_file '"movstrHI15x.s"'; - echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c deleted file mode 100755 index ef743cb..0000000 --- a/gcc/config/m88k/m88k.c +++ /dev/null @@ -1,3162 +0,0 @@ -/* Subroutines for insn-output.c for Motorola 88000. - Copyright (C) 1988, 92, 93, 94, 95, 16, 1997 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@mcc.com) - Currently maintained by (gcc@dg-rtp.dg.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 "config.h" - -#include <stdio.h> -#include <sys/types.h> -#include <time.h> -#include <ctype.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 "tree.h" -#include "c-tree.h" -#include "expr.h" -#include "flags.h" - -extern char *version_string; -extern time_t time (); -extern char *ctime (); -extern int flag_traditional; -extern FILE *asm_out_file; - -static char out_rcs_id[] = "$What: <@(#) m88k.c,v 1.8> $"; -static char tm_rcs_id [] = TM_RCS_ID; - -char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ -char *m88k_short_data; -char *m88k_version; -char m88k_volatile_code; - -unsigned m88k_gp_threshold = 0; -int m88k_prologue_done = 0; /* Ln directives can now be emitted */ -int m88k_function_number = 0; /* Counter unique to each function */ -int m88k_fp_offset = 0; /* offset of frame pointer if used */ -int m88k_stack_size = 0; /* size of allocated stack (including frame) */ -int m88k_case_index; - -rtx m88k_compare_reg; /* cmp output pseudo register */ -rtx m88k_compare_op0; /* cmpsi operand 0 */ -rtx m88k_compare_op1; /* cmpsi operand 1 */ - -enum processor_type m88k_cpu; /* target cpu */ - -/* Determine what instructions are needed to manufacture the integer VALUE - in the given MODE. */ - -enum m88k_instruction -classify_integer (mode, value) - enum machine_mode mode; - register int value; -{ - register int mask; - - if (value == 0) - return m88k_zero; - else if (SMALL_INTVAL (value)) - return m88k_or; - else if (SMALL_INTVAL (-value)) - return m88k_subu; - else if (mode == HImode) - return m88k_or_lo16; - else if (mode == QImode) - return m88k_or_lo8; - else if ((value & 0xffff) == 0) - return m88k_oru_hi16; - else if (integer_ok_for_set (value)) - return m88k_set; - else - return m88k_oru_or; -} - -/* Return the bit number in a compare word corresponding to CONDITION. */ - -int -condition_value (condition) - rtx condition; -{ - switch (GET_CODE (condition)) - { - case EQ: return 2; - case NE: return 3; - case GT: return 4; - case LE: return 5; - case LT: return 6; - case GE: return 7; - case GTU: return 8; - case LEU: return 9; - case LTU: return 10; - case GEU: return 11; - default: abort (); - } -} - -int -integer_ok_for_set (value) - register unsigned value; -{ - /* All the "one" bits must be contiguous. If so, MASK + 1 will be - a power of two or zero. */ - register unsigned mask = (value | (value - 1)); - return (value && POWER_OF_2_or_0 (mask + 1)); -} - -char * -output_load_const_int (mode, operands) - enum machine_mode mode; - rtx *operands; -{ - static char *patterns[] = - { "or %0,%#r0,0", - "or %0,%#r0,%1", - "subu %0,%#r0,%n1", - "or %0,%#r0,%h1", - "or %0,%#r0,%q1", - "set %0,%#r0,%s1", - "or.u %0,%#r0,%X1", - "or.u %0,%#r0,%X1\n\tor %0,%0,%x1", - }; - - if (! REG_P (operands[0]) - || GET_CODE (operands[1]) != CONST_INT) - abort (); - return patterns[classify_integer (mode, INTVAL (operands[1]))]; -} - -/* These next two routines assume that floating point numbers are represented - in a manner which is consistent between host and target machines. */ - -char * -output_load_const_float (operands) - rtx *operands; -{ - /* These can return 0 under some circumstances when cross-compiling. */ - operands[0] = operand_subword (operands[0], 0, 0, SFmode); - operands[1] = operand_subword (operands[1], 0, 0, SFmode); - - return output_load_const_int (SImode, operands); -} - -char * -output_load_const_double (operands) - rtx *operands; -{ - rtx latehalf[2]; - - /* These can return zero on some cross-compilers, but there's nothing - we can do about it. */ - latehalf[0] = operand_subword (operands[0], 1, 0, DFmode); - latehalf[1] = operand_subword (operands[1], 1, 0, DFmode); - - operands[0] = operand_subword (operands[0], 0, 0, DFmode); - operands[1] = operand_subword (operands[1], 0, 0, DFmode); - - output_asm_insn (output_load_const_int (SImode, operands), operands); - - operands[0] = latehalf[0]; - operands[1] = latehalf[1]; - - return output_load_const_int (SImode, operands); -} - -char * -output_load_const_dimode (operands) - rtx *operands; -{ - rtx latehalf[2]; - - latehalf[0] = operand_subword (operands[0], 1, 0, DImode); - latehalf[1] = operand_subword (operands[1], 1, 0, DImode); - - operands[0] = operand_subword (operands[0], 0, 0, DImode); - operands[1] = operand_subword (operands[1], 0, 0, DImode); - - output_asm_insn (output_load_const_int (SImode, operands), operands); - - operands[0] = latehalf[0]; - operands[1] = latehalf[1]; - - return output_load_const_int (SImode, operands); -} - -/* Emit insns to move operands[1] into operands[0]. - - Return 1 if we have written out everything that needs to be done to - do the move. Otherwise, return 0 and the caller will emit the move - normally. - - SCRATCH if non zero can be used as a scratch register for the move - operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */ - -int -emit_move_sequence (operands, mode, scratch) - rtx *operands; - enum machine_mode mode; - rtx scratch; -{ - register rtx operand0 = operands[0]; - register rtx operand1 = operands[1]; - - if (CONSTANT_P (operand1) && flag_pic - && pic_address_needs_scratch (operand1)) - operands[1] = operand1 = legitimize_address (1, operand1, 0, 0); - - /* Handle most common case first: storing into a register. */ - if (register_operand (operand0, mode)) - { - if (register_operand (operand1, mode) - || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1)) - || GET_CODE (operand1) == HIGH - /* Only `general_operands' can come here, so MEM is ok. */ - || GET_CODE (operand1) == MEM) - { - /* Run this case quickly. */ - emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); - return 1; - } - } - else if (GET_CODE (operand0) == MEM) - { - if (register_operand (operand1, mode) - || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)) - { - /* Run this case quickly. */ - emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1)); - return 1; - } - if (! reload_in_progress && ! reload_completed) - { - operands[0] = validize_mem (operand0); - operands[1] = operand1 = force_reg (mode, operand1); - } - } - - /* Simplify the source if we need to. */ - if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) - { - if (GET_CODE (operand1) != CONST_INT - && GET_CODE (operand1) != CONST_DOUBLE) - { - rtx temp = ((reload_in_progress || reload_completed) - ? operand0 : 0); - operands[1] = legitimize_address (flag_pic - && symbolic_address_p (operand1), - operand1, temp, scratch); - if (mode != SImode) - operands[1] = gen_rtx (SUBREG, mode, operands[1], 0); - } - } - - /* Now have insn-emit do whatever it normally does. */ - return 0; -} - -/* Return a legitimate reference for ORIG (either an address or a MEM) - using the register REG. If PIC and the address is already - position-independent, use ORIG. Newly generated position-independent - addresses go into a reg. This is REG if non zero, otherwise we - allocate register(s) as necessary. If this is called during reload, - and we need a second temp register, then we use SCRATCH, which is - provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */ - -struct rtx_def * -legitimize_address (pic, orig, reg, scratch) - int pic; - rtx orig; - rtx reg; - rtx scratch; -{ - rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig); - rtx new = orig; - rtx temp, insn; - - if (pic) - { - if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) - { - if (reg == 0) - { - if (reload_in_progress || reload_completed) - abort (); - else - reg = gen_reg_rtx (Pmode); - } - - if (flag_pic == 2) - { - /* If not during reload, allocate another temp reg here for - loading in the address, so that these instructions can be - optimized properly. */ - temp = ((reload_in_progress || reload_completed) - ? reg : gen_reg_rtx (Pmode)); - - emit_insn (gen_rtx (SET, VOIDmode, temp, - gen_rtx (HIGH, SImode, - gen_rtx (UNSPEC, SImode, - gen_rtvec (1, addr), - 0)))); - emit_insn (gen_rtx (SET, VOIDmode, temp, - gen_rtx (LO_SUM, SImode, temp, - gen_rtx (UNSPEC, SImode, - gen_rtvec (1, addr), - 0)))); - addr = temp; - } - new = gen_rtx (MEM, Pmode, - gen_rtx (PLUS, SImode, - pic_offset_table_rtx, addr)); - current_function_uses_pic_offset_table = 1; - RTX_UNCHANGING_P (new) = 1; - insn = emit_move_insn (reg, new); - /* Put a REG_EQUAL note on this insn, so that it can be optimized - by loop. */ - REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig, - REG_NOTES (insn)); - new = reg; - } - else if (GET_CODE (addr) == CONST) - { - rtx base, offset; - - if (GET_CODE (XEXP (addr, 0)) == PLUS - && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx) - return orig; - - if (reg == 0) - { - if (reload_in_progress || reload_completed) - abort (); - else - reg = gen_reg_rtx (Pmode); - } - - if (GET_CODE (XEXP (addr, 0)) != PLUS) abort (); - - base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0); - addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1), - base == reg ? 0 : reg, 0); - - if (GET_CODE (addr) == CONST_INT) - { - if (ADD_INT (addr)) - return plus_constant_for_output (base, INTVAL (addr)); - else if (! reload_in_progress && ! reload_completed) - addr = force_reg (Pmode, addr); - /* We can't create any new registers during reload, so use the - SCRATCH reg provided by the reload_insi pattern. */ - else if (scratch) - { - emit_move_insn (scratch, addr); - addr = scratch; - } - else - /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS - macro needs to be adjusted so that a scratch reg is provided - for this address. */ - abort (); - } - new = gen_rtx (PLUS, SImode, base, addr); - /* Should we set special REG_NOTEs here? */ - } - } - else if (! SHORT_ADDRESS_P (addr, temp)) - { - if (reg == 0) - { - if (reload_in_progress || reload_completed) - abort (); - else - reg = gen_reg_rtx (Pmode); - } - - emit_insn (gen_rtx (SET, VOIDmode, - reg, gen_rtx (HIGH, SImode, addr))); - new = gen_rtx (LO_SUM, SImode, reg, addr); - } - - if (new != orig - && GET_CODE (orig) == MEM) - { - new = gen_rtx (MEM, GET_MODE (orig), new); - RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig); - MEM_COPY_ATTRIBUTES (new, orig); - } - return new; -} - -/* Support functions for code to emit a block move. There are four methods - used to perform the block move: - + call memcpy - + call the looping library function, e.g. __movstrSI64n8 - + call a non-looping library function, e.g. __movstrHI15x11 - + produce an inline sequence of ld/st instructions - - The parameters below describe the library functions produced by - movstr-m88k.sh. */ - -#define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */ -#define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */ -#define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ -#define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */ -#define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */ -#define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ -#define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11, - __movstrSI46x46 .. __movstrSI46x10, - __movstrSI45x45 .. __movstrSI45x9 */ -#define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23, - __movstrDI46x46 .. __movstrDI46x22, - __movstrDI45x45 .. __movstrDI45x21, - __movstrDI44x44 .. __movstrDI44x20, - __movstrDI43x43 .. __movstrDI43x19, - __movstrDI42x42 .. __movstrDI42x18, - __movstrDI41x41 .. __movstrDI41x17 */ - -/* Limits for using the non-looping movstr functions. For the m88100 - processor, we assume the source and destination are word aligned. - The QImode and HImode limits are the break even points where memcpy - does just as well and beyond which memcpy does better. For the - m88110, we tend to assume double word alignment, but also analyze - the word aligned cases. The analysis is complicated because memcpy - may use the cache control instructions for better performance. */ - -#define MOVSTR_QI_LIMIT_88100 13 -#define MOVSTR_HI_LIMIT_88100 38 -#define MOVSTR_SI_LIMIT_88100 MOVSTR_SI -#define MOVSTR_DI_LIMIT_88100 MOVSTR_SI - -#define MOVSTR_QI_LIMIT_88000 16 -#define MOVSTR_HI_LIMIT_88000 38 -#define MOVSTR_SI_LIMIT_88000 72 -#define MOVSTR_DI_LIMIT_88000 72 - -#define MOVSTR_QI_LIMIT_88110 16 -#define MOVSTR_HI_LIMIT_88110 38 -#define MOVSTR_SI_LIMIT_88110 72 -#define MOVSTR_DI_LIMIT_88110 72 - -static enum machine_mode mode_from_align[] = - {VOIDmode, QImode, HImode, VOIDmode, SImode, - VOIDmode, VOIDmode, VOIDmode, DImode}; -static int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI, - 0, 0, 0, MOVSTR_DI}; -static int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI, - 0, 0, 0, MOVSTR_ODD_DI}; - -static int best_from_align[3][9] = - {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100, - 0, 0, 0, MOVSTR_DI_LIMIT_88100, - 0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110, - 0, 0, 0, MOVSTR_DI_LIMIT_88110, - 0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000, - 0, 0, 0, MOVSTR_DI_LIMIT_88000}; - -static void block_move_loop (); -static void block_move_no_loop (); -static void block_move_sequence (); - -/* Emit code to perform a block move. Choose the best method. - - OPERANDS[0] is the destination. - OPERANDS[1] is the source. - OPERANDS[2] is the size. - OPERANDS[3] is the alignment safe to use. */ - -void -expand_block_move (dest_mem, src_mem, operands) - rtx dest_mem; - rtx src_mem; - rtx *operands; -{ - int align = INTVAL (operands[3]); - int constp = (GET_CODE (operands[2]) == CONST_INT); - int bytes = (constp ? INTVAL (operands[2]) : 0); - int target = (int) m88k_cpu; - - if (! (PROCESSOR_M88100 == 0 - && PROCESSOR_M88110 == 1 - && PROCESSOR_M88000 == 2)) - abort (); - - if (constp && bytes <= 0) - return; - - /* Determine machine mode to do move with. */ - if (align > 4 && !TARGET_88110) - align = 4; - else if (align <= 0 || align == 3) - abort (); /* block move invalid alignment. */ - - if (constp && bytes <= 3 * align) - block_move_sequence (operands[0], dest_mem, operands[1], src_mem, - bytes, align, 0); - - else if (constp && bytes <= best_from_align[target][align]) - block_move_no_loop (operands[0], dest_mem, operands[1], src_mem, - bytes, align); - - else if (constp && align == 4 && TARGET_88100) - block_move_loop (operands[0], dest_mem, operands[1], src_mem, - bytes, align); - - else - { -#ifdef TARGET_MEM_FUNCTIONS - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0, - VOIDmode, 3, - operands[0], Pmode, - operands[1], Pmode, - convert_to_mode (TYPE_MODE (sizetype), operands[2], - TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); -#else - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0, - VOIDmode, 3, - operands[1], Pmode, - operands[0], Pmode, - convert_to_mode (TYPE_MODE (integer_type_node), - operands[2], - TREE_UNSIGNED (integer_type_node)), - TYPE_MODE (integer_type_node)); -#endif - } -} - -/* Emit code to perform a block move by calling a looping movstr library - function. SIZE and ALIGN are known constants. DEST and SRC are - registers. */ - -static void -block_move_loop (dest, dest_mem, src, src_mem, size, align) - rtx dest, dest_mem; - rtx src, src_mem; - int size; - int align; -{ - enum machine_mode mode; - int count; - int units; - int remainder; - rtx offset_rtx; - rtx value_rtx; - char entry[30]; - tree entry_name; - - /* Determine machine mode to do move with. */ - if (align != 4) - abort (); - - /* Determine the structure of the loop. */ - count = size / MOVSTR_LOOP; - units = (size - count * MOVSTR_LOOP) / align; - - if (units < 2) - { - count--; - units += MOVSTR_LOOP / align; - } - - if (count <= 0) - { - block_move_no_loop (dest, dest_mem, src, src_mem, size, align); - return; - } - - remainder = size - count * MOVSTR_LOOP - units * align; - - mode = mode_from_align[align]; - sprintf (entry, "__movstr%s%dn%d", - GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); - entry_name = get_identifier (entry); - - offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align); - - value_rtx = gen_rtx (MEM, MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode, - gen_rtx (PLUS, Pmode, - gen_rtx (REG, Pmode, 3), - offset_rtx)); - RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem); - MEM_COPY_ATTRIBUTES (value_rtx, src_mem); - - emit_insn (gen_call_movstrsi_loop - (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), - dest, src, offset_rtx, value_rtx, - gen_rtx (REG, mode, ((units & 1) ? 4 : 5)), - GEN_INT (count))); - - if (remainder) - block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem, - gen_rtx (REG, Pmode, 3), src_mem, - remainder, align, MOVSTR_LOOP + align); -} - -/* Emit code to perform a block move by calling a non-looping library - function. SIZE and ALIGN are known constants. DEST and SRC are - registers. OFFSET is the known starting point for the output pattern. */ - -static void -block_move_no_loop (dest, dest_mem, src, src_mem, size, align) - rtx dest, dest_mem; - rtx src, src_mem; - int size; - int align; -{ - enum machine_mode mode = mode_from_align[align]; - int units = size / align; - int remainder = size - units * align; - int most; - int value_reg; - rtx offset_rtx; - rtx value_rtx; - char entry[30]; - tree entry_name; - - if (remainder && size <= all_from_align[align]) - { - most = all_from_align[align] - (align - remainder); - remainder = 0; - } - else - { - most = max_from_align[align]; - } - - sprintf (entry, "__movstr%s%dx%d", - GET_MODE_NAME (mode), most, size - remainder); - entry_name = get_identifier (entry); - - offset_rtx = GEN_INT (most - (size - remainder)); - - value_rtx = gen_rtx (MEM, MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode, - gen_rtx (PLUS, Pmode, - gen_rtx (REG, Pmode, 3), - offset_rtx)); - RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem); - MEM_COPY_ATTRIBUTES (value_rtx, src_mem); - - value_reg = ((((most - (size - remainder)) / align) & 1) == 0 - ? (align == 8 ? 6 : 5) : 4); - - emit_insn (gen_call_block_move - (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), - dest, src, offset_rtx, value_rtx, - gen_rtx (REG, mode, value_reg))); - - if (remainder) - block_move_sequence (gen_rtx (REG, Pmode, 2), dest_mem, - gen_rtx (REG, Pmode, 3), src_mem, - remainder, align, most); -} - -/* Emit code to perform a block move with an offset sequence of ld/st - instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are - known constants. DEST and SRC are registers. OFFSET is the known - starting point for the output pattern. */ - -static void -block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset) - rtx dest, dest_mem; - rtx src, src_mem; - int size; - int align; - int offset; -{ - rtx temp[2]; - enum machine_mode mode[2]; - int amount[2]; - int active[2]; - int phase = 0; - int next; - int offset_ld = offset; - int offset_st = offset; - - active[0] = active[1] = FALSE; - - /* Establish parameters for the first load and for the second load if - it is known to be the same mode as the first. */ - amount[0] = amount[1] = align; - mode[0] = mode_from_align[align]; - temp[0] = gen_reg_rtx (mode[0]); - if (size >= 2 * align) - { - mode[1] = mode[0]; - temp[1] = gen_reg_rtx (mode[1]); - } - - do - { - rtx srcp, dstp; - next = phase; - phase = !phase; - - if (size > 0) - { - /* Change modes as the sequence tails off. */ - if (size < amount[next]) - { - amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1)); - mode[next] = mode_from_align[amount[next]]; - temp[next] = gen_reg_rtx (mode[next]); - } - size -= amount[next]; - srcp = gen_rtx (MEM, - MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode, - gen_rtx (PLUS, Pmode, src, - GEN_INT (offset_ld))); - RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem); - MEM_COPY_ATTRIBUTES (srcp, src_mem); - emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp)); - offset_ld += amount[next]; - active[next] = TRUE; - } - - if (active[phase]) - { - active[phase] = FALSE; - dstp = gen_rtx (MEM, - MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode, - gen_rtx (PLUS, Pmode, dest, - GEN_INT (offset_st))); - RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem); - MEM_COPY_ATTRIBUTES (dstp, dest_mem); - emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase])); - offset_st += amount[phase]; - } - } - while (active[next]); -} - -/* Emit the code to do an AND operation. */ - -char * -output_and (operands) - rtx operands[]; -{ - unsigned int value; - - if (REG_P (operands[2])) - return "and %0,%1,%2"; - - value = INTVAL (operands[2]); - if (SMALL_INTVAL (value)) - return "mask %0,%1,%2"; - else if ((value & 0xffff0000) == 0xffff0000) - return "and %0,%1,%x2"; - else if ((value & 0xffff) == 0xffff) - return "and.u %0,%1,%X2"; - else if ((value & 0xffff) == 0) - return "mask.u %0,%1,%X2"; - else if (integer_ok_for_set (~value)) - return "clr %0,%1,%S2"; - else - return "and.u %0,%1,%X2\n\tand %0,%0,%x2"; -} - -/* Emit the code to do an inclusive OR operation. */ - -char * -output_ior (operands) - rtx operands[]; -{ - unsigned int value; - - if (REG_P (operands[2])) - return "or %0,%1,%2"; - - value = INTVAL (operands[2]); - if (SMALL_INTVAL (value)) - return "or %0,%1,%2"; - else if ((value & 0xffff) == 0) - return "or.u %0,%1,%X2"; - else if (integer_ok_for_set (value)) - return "set %0,%1,%s2"; - else - return "or.u %0,%1,%X2\n\tor %0,%0,%x2"; -} - -/* Emit the instructions for doing an XOR. */ - -char * -output_xor (operands) - rtx operands[]; -{ - unsigned int value; - - if (REG_P (operands[2])) - return "xor %0,%1,%2"; - - value = INTVAL (operands[2]); - if (SMALL_INTVAL (value)) - return "xor %0,%1,%2"; - else if ((value & 0xffff) == 0) - return "xor.u %0,%1,%X2"; - else - return "xor.u %0,%1,%X2\n\txor %0,%0,%x2"; -} - -/* Output a call. Normally this is just bsr or jsr, but this also deals with - accomplishing a branch after the call by incrementing r1. This requires - that various assembler bugs be accommodated. The 4.30 DG/UX assembler - requires that forward references not occur when computing the difference of - two labels. The [version?] Motorola assembler computes a word difference. - No doubt there's more to come! - - It would seem the same idea could be used to tail call, but in this case, - the epilogue will be non-null. */ - -static rtx sb_name = 0; -static rtx sb_high = 0; -static rtx sb_low = 0; - -char * -output_call (operands, addr) - rtx operands[]; - rtx addr; -{ - operands[0] = addr; - if (final_sequence) - { - rtx jump; - rtx seq_insn; - - /* This can be generalized, but there is currently no need. */ - if (XVECLEN (final_sequence, 0) != 2) - abort (); - - /* The address of interior insns is not computed, so use the sequence. */ - seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); - jump = XVECEXP (final_sequence, 0, 1); - if (GET_CODE (jump) == JUMP_INSN) - { - rtx low, high; - char *last; - rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0); - int delta = 4 * (insn_addresses[INSN_UID (dest)] - - insn_addresses[INSN_UID (seq_insn)] - - 2); -#if (MONITOR_GCC & 0x2) /* How often do long branches happen? */ - if ((unsigned) (delta + 0x8000) >= 0x10000) - warning ("Internal gcc monitor: short-branch(%x)", delta); -#endif - - /* Delete the jump. */ - PUT_CODE (jump, NOTE); - NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (jump) = 0; - - /* We only do this optimization if -O2, modifying the value of - r1 in the delay slot confuses debuggers and profilers on some - systems. - - If we loose, we must use the non-delay form. This is unlikely - to ever happen. If it becomes a problem, claim that a call - has two delay slots and only the second can be filled with - a jump. - - The 88110 can lose when a jsr.n r1 is issued and a page fault - occurs accessing the delay slot. So don't use jsr.n form when - jumping thru r1. - */ -#ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */ - if (optimize < 2 - || ! ADD_INTVAL (delta * 2) -#else - if (optimize < 2 - || ! ADD_INTVAL (delta) -#endif - || (REG_P (addr) && REGNO (addr) == 1)) - { - operands[1] = dest; - return (REG_P (addr) - ? "jsr %0\n\tbr %l1" - : (flag_pic - ? "bsr %0#plt\n\tbr %l1" - : "bsr %0\n\tbr %l1")); - } - - /* Output the short branch form. */ - output_asm_insn ((REG_P (addr) - ? "jsr.n %0" - : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")), - operands); - -#ifdef USE_GAS - last = (delta < 0 - ? "subu %#r1,%#r1,.-%l0+4" - : "addu %#r1,%#r1,%l0-.-4"); - operands[0] = dest; -#else - operands[0] = gen_label_rtx (); - operands[1] = gen_label_rtx (); - if (delta < 0) - { - low = dest; - high = operands[1]; - last = "subu %#r1,%#r1,%l0\n%l1:"; - } - else - { - low = operands[1]; - high = dest; - last = "addu %#r1,%#r1,%l0\n%l1:"; - } - - /* Record the values to be computed later as "def name,high-low". */ - sb_name = gen_rtx (EXPR_LIST, VOIDmode, operands[0], sb_name); - sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high); - sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low); -#endif /* Don't USE_GAS */ - - return last; - } - } - return (REG_P (addr) - ? "jsr%. %0" - : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0")); -} - -static void -output_short_branch_defs (stream) - FILE *stream; -{ - char name[256], high[256], low[256]; - - for (; sb_name && sb_high && sb_low; - sb_name = XEXP (sb_name, 1), - sb_high = XEXP (sb_high, 1), - sb_low = XEXP (sb_low, 1)) - { - ASM_GENERATE_INTERNAL_LABEL - (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0))); - ASM_GENERATE_INTERNAL_LABEL - (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0))); - ASM_GENERATE_INTERNAL_LABEL - (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0))); - /* This will change as the assembler requirements become known. */ - fprintf (stream, "\t%s\t %s,%s-%s\n", - SET_ASM_OP, &name[1], &high[1], &low[1]); - } - if (sb_name || sb_high || sb_low) - abort (); -} - -/* Return truth value of the statement that this conditional branch is likely - to fall through. CONDITION, is the condition that JUMP_INSN is testing. */ - -int -mostly_false_jump (jump_insn, condition) - rtx jump_insn, condition; -{ - rtx target_label = JUMP_LABEL (jump_insn); - rtx insnt, insnj; - - /* Much of this isn't computed unless we're optimizing. */ - if (optimize == 0) - return 0; - - /* Determine if one path or the other leads to a return. */ - for (insnt = NEXT_INSN (target_label); - insnt; - insnt = NEXT_INSN (insnt)) - { - if (GET_CODE (insnt) == JUMP_INSN) - break; - else if (GET_CODE (insnt) == INSN - && GET_CODE (PATTERN (insnt)) == SEQUENCE - && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN) - { - insnt = XVECEXP (PATTERN (insnt), 0, 0); - break; - } - } - if (insnt - && (GET_CODE (PATTERN (insnt)) == RETURN - || (GET_CODE (PATTERN (insnt)) == SET - && GET_CODE (SET_SRC (PATTERN (insnt))) == REG - && REGNO (SET_SRC (PATTERN (insnt))) == 1))) - insnt = 0; - - for (insnj = NEXT_INSN (jump_insn); - insnj; - insnj = NEXT_INSN (insnj)) - { - if (GET_CODE (insnj) == JUMP_INSN) - break; - else if (GET_CODE (insnj) == INSN - && GET_CODE (PATTERN (insnj)) == SEQUENCE - && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN) - { - insnj = XVECEXP (PATTERN (insnj), 0, 0); - break; - } - } - if (insnj - && (GET_CODE (PATTERN (insnj)) == RETURN - || (GET_CODE (PATTERN (insnj)) == SET - && GET_CODE (SET_SRC (PATTERN (insnj))) == REG - && REGNO (SET_SRC (PATTERN (insnj))) == 1))) - insnj = 0; - - /* Predict to not return. */ - if ((insnt == 0) != (insnj == 0)) - return (insnt == 0); - - /* Predict loops to loop. */ - for (insnt = PREV_INSN (target_label); - insnt && GET_CODE (insnt) == NOTE; - insnt = PREV_INSN (insnt)) - if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END) - return 1; - else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG) - return 0; - else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT) - return 0; - - /* Predict backward branches usually take. */ - if (final_sequence) - insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); - else - insnj = jump_insn; - if (insn_addresses[INSN_UID (insnj)] - > insn_addresses[INSN_UID (target_label)]) - return 0; - - /* EQ tests are usually false and NE tests are usually true. Also, - most quantities are positive, so we can make the appropriate guesses - about signed comparisons against zero. Consider unsigned comparisons - to be a range check and assume quantities to be in range. */ - switch (GET_CODE (condition)) - { - case CONST_INT: - /* Unconditional branch. */ - return 0; - case EQ: - return 1; - case NE: - return 0; - case LE: - case LT: - case GEU: - case GTU: /* Must get casesi right at least. */ - if (XEXP (condition, 1) == const0_rtx) - return 1; - break; - case GE: - case GT: - case LEU: - case LTU: - if (XEXP (condition, 1) == const0_rtx) - return 0; - break; - } - - return 0; -} - -/* Return true if the operand is a power of two and is a floating - point type (to optimize division by power of two into multiplication). */ - -int -real_power_of_2_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - union { - REAL_VALUE_TYPE d; - int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)]; - struct { /* IEEE double precision format */ - unsigned sign : 1; - unsigned exponent : 11; - unsigned mantissa1 : 20; - unsigned mantissa2; - } s; - struct { /* IEEE double format to quick check */ - unsigned sign : 1; /* if it fits in a float */ - unsigned exponent1 : 4; - unsigned exponent2 : 7; - unsigned mantissa1 : 20; - unsigned mantissa2; - } s2; - } u; - - if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode) - return 0; - - if (GET_CODE (op) != CONST_DOUBLE) - return 0; - - u.i[0] = CONST_DOUBLE_LOW (op); - u.i[1] = CONST_DOUBLE_HIGH (op); - - if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */ - || u.s.exponent == 0 /* constant 0.0 */ - || u.s.exponent == 0x7ff /* NAN */ - || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7)) - return 0; /* const won't fit in float */ - - return 1; -} - -/* Make OP legitimate for mode MODE. Currently this only deals with DFmode - operands, putting them in registers and making CONST_DOUBLE values - SFmode where possible. */ - -struct rtx_def * -legitimize_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx temp; - union { - union real_extract r; - struct { /* IEEE double precision format */ - unsigned sign : 1; - unsigned exponent : 11; - unsigned mantissa1 : 20; - unsigned mantissa2; - } d; - struct { /* IEEE double format to quick check */ - unsigned sign : 1; /* if it fits in a float */ - unsigned exponent1 : 4; - unsigned exponent2 : 7; - unsigned mantissa1 : 20; - unsigned mantissa2; - } s; - } u; - - if (GET_CODE (op) == REG || mode != DFmode) - return op; - - if (GET_CODE (op) == CONST_DOUBLE) - { - bcopy (&CONST_DOUBLE_LOW (op), &u.r, sizeof u); - if (u.d.exponent != 0x7ff /* NaN */ - && u.d.mantissa2 == 0 /* Mantissa fits */ - && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */ - && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode, - op, mode)) != 0) - return gen_rtx (FLOAT_EXTEND, mode, force_reg (SFmode, temp)); - } - else if (register_operand (op, mode)) - return op; - - return force_reg (mode, op); -} - -/* Return true if OP is a suitable input for a move insn. */ - -int -move_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - if (GET_CODE (op) == CONST_INT) - return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16); - if (GET_MODE (op) != mode) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - if (GET_CODE (op) == LO_SUM) - return (REG_P (XEXP (op, 0)) - && symbolic_address_p (XEXP (op, 1))); - return memory_address_p (mode, op); -} - -/* Return true if OP is suitable for a call insn. */ - -int -call_address_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (REG_P (op) || symbolic_address_p (op)); -} - -/* Returns true if OP is either a symbol reference or a sum of a symbol - reference and a constant. */ - -int -symbolic_address_p (op) - register rtx op; -{ - 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); - - default: - return 0; - } -} - -/* Return true if OP is a register or const0_rtx. */ - -int -reg_or_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (op == const0_rtx || register_operand (op, mode)); -} - -/* Nonzero if OP is a valid second operand for an arithmetic insn. */ - -int -arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); -} - -/* Return true if OP is a register or 5 bit integer. */ - -int -arith5_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32)); -} - -int -arith32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) || GET_CODE (op) == CONST_INT); -} - -int -arith64_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || GET_CODE (op) == CONST_INT - || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)); -} - -int -int5_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32); -} - -int -int32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == CONST_INT); -} - -/* Return true if OP is a register or a valid immediate operand for - addu or subu. */ - -int -add_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && ADD_INT (op))); -} - -/* Nonzero if this is a bitmask filling the bottom bits, for optimizing and + - shift left combinations into a single mak instruction. */ - -int -mak_mask_p (value) - int value; -{ - return (value && POWER_OF_2_or_0 (value + 1)); -} - -int -reg_or_bbx_mask_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int value; - if (register_operand (op, mode)) - return 1; - if (GET_CODE (op) != CONST_INT) - return 0; - - value = INTVAL (op); - if (POWER_OF_2 (value)) - return 1; - - return 0; -} - -/* Return true if OP is valid to use in the context of a floating - point operation. Special case 0.0, since we can use r0. */ - -int -real_or_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != SFmode && mode != DFmode) - return 0; - - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_DOUBLE - && op == CONST0_RTX (mode))); -} - -/* Return true if OP is valid to use in the context of logic arithmetic - on condition codes. */ - -int -partial_ccmode_register_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, CCmode) || register_operand (op, CCEVENmode); -} - -/* Return true if OP is a relational operator. */ - -int -relop (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case EQ: - case NE: - case LT: - case LE: - case GE: - case GT: - case LTU: - case LEU: - case GEU: - case GTU: - return 1; - default: - return 0; - } -} - -int -even_relop (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case EQ: - case LT: - case GT: - case LTU: - case GTU: - return 1; - default: - return 0; - } -} - -int -odd_relop (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case NE: - case LE: - case GE: - case LEU: - case GEU: - return 1; - default: - return 0; - } -} - -/* Return true if OP is a relational operator, and is not an unsigned - relational operator. */ - -int -relop_no_unsigned (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case EQ: - case NE: - case LT: - case LE: - case GE: - case GT: - /* @@ What is this test doing? Why not use `mode'? */ - if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT - || GET_MODE (op) == DImode - || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT - || GET_MODE (XEXP (op, 0)) == DImode - || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT - || GET_MODE (XEXP (op, 1)) == DImode) - return 0; - return 1; - default: - return 0; - } -} - -/* Return true if the code of this rtx pattern is EQ or NE. */ - -int -equality_op (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == EQ || GET_CODE (op) == NE); -} - -/* Return true if the code of this rtx pattern is pc or label_ref. */ - -int -pc_or_label_ref (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); -} - -/* Output to FILE the start of the assembler file. */ - -struct options -{ - char *string; - int *variable; - int on_value; - char *description; -}; - -static int -output_option (file, sep, type, name, indent, pos, max) - FILE *file; - char *sep; - char *type; - char *name; - char *indent; - int pos; - int max; -{ - if (strlen (sep) + strlen (type) + strlen (name) + pos > max) - { - fprintf (file, indent); - return fprintf (file, "%s%s", type, name); - } - return pos + fprintf (file, "%s%s%s", sep, type, name); -} - -static struct { char *name; int value; } m_options[] = TARGET_SWITCHES; - -static void -output_options (file, f_options, f_len, W_options, W_len, - pos, max, sep, indent, term) - FILE *file; - struct options *f_options; - struct options *W_options; - int f_len, W_len; - int pos; - int max; - char *indent; - char *term; -{ - register int j; - - if (optimize) - pos = output_option (file, sep, "-O", "", indent, pos, max); - if (write_symbols != NO_DEBUG) - pos = output_option (file, sep, "-g", "", indent, pos, max); - if (flag_traditional) - pos = output_option (file, sep, "-traditional", "", indent, pos, max); - if (profile_flag) - pos = output_option (file, sep, "-p", "", indent, pos, max); - if (profile_block_flag) - pos = output_option (file, sep, "-a", "", indent, pos, max); - - for (j = 0; j < f_len; j++) - if (*f_options[j].variable == f_options[j].on_value) - pos = output_option (file, sep, "-f", f_options[j].string, - indent, pos, max); - - for (j = 0; j < W_len; j++) - if (*W_options[j].variable == W_options[j].on_value) - pos = output_option (file, sep, "-W", W_options[j].string, - indent, pos, max); - - for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) - if (m_options[j].name[0] != '\0' - && m_options[j].value > 0 - && ((m_options[j].value & target_flags) - == m_options[j].value)) - pos = output_option (file, sep, "-m", m_options[j].name, - indent, pos, max); - - if (m88k_short_data) - pos = output_option (file, sep, "-mshort-data-", m88k_short_data, - indent, pos, max); - - fprintf (file, term); -} - -void -output_file_start (file, f_options, f_len, W_options, W_len) - FILE *file; - struct options *f_options; - struct options *W_options; - int f_len, W_len; -{ - register int pos; - - ASM_FIRST_LINE (file); - if (TARGET_88110 - && TARGET_SVR4) - fprintf (file, "\t%s\n", REQUIRES_88110_ASM_OP); - output_file_directive (file, main_input_filename); - /* Switch to the data section so that the coffsem symbol and the - gcc2_compiled. symbol aren't in the text section. */ - data_section (); - ASM_COFFSEM (file); - - if (TARGET_IDENTIFY_REVISION) - { - char indent[256]; - - time_t now = time ((time_t *)0); - sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename); - fprintf (file, indent+3); - pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now)); -#if 1 - /* ??? It would be nice to call print_switch_values here (and thereby - let us delete output_options) but this is kept in until it is known - whether the change in content format matters. */ - output_options (file, f_options, f_len, W_options, W_len, - pos, 150 - strlen (indent), " ", indent, "]\"\n\n"); -#else - fprintf (file, "]\"\n"); - print_switch_values (file, 0, 150 - strlen (indent), - indent + 3, " ", "]\"\n"); -#endif - } -} - -/* Output an ascii string. */ - -void -output_ascii (file, opcode, max, p, size) - FILE *file; - char *opcode; - int max; - unsigned char *p; - int size; -{ - int i; - int in_escape = 0; - - register int num = 0; - - fprintf (file, "\t%s\t \"", opcode); - for (i = 0; i < size; i++) - { - register int c = p[i]; - - if (num > max) - { - fprintf (file, "\"\n\t%s\t \"", opcode); - num = 0; - } - - if (c == '\"' || c == '\\') - { - escape: - putc ('\\', file); - putc (c, file); - num += 2; - in_escape = 0; - } - else if (in_escape && c >= '0' && c <= '9') - { - /* If a digit follows an octal-escape, the Vax assembler fails - to stop reading the escape after three digits. Continue to - output the values as an octal-escape until a non-digit is - found. */ - fprintf (file, "\\%03o", c); - num += 4; - } - else if ((c >= ' ' && c < 0177) || (c == '\t')) - { - putc (c, file); - num++; - in_escape = 0; - } - else - { - switch (c) - { - /* Some assemblers can't handle \a, \v, or \?. */ - case '\f': c = 'f'; goto escape; - case '\b': c = 'b'; goto escape; - case '\r': c = 'r'; goto escape; - case '\n': c = 'n'; goto escape; - } - - fprintf (file, "\\%03o", c); - num += 4; - in_escape = 1; - } - } - fprintf (file, "\"\n"); -} - -/* Output a label (allows insn-output.c to be compiled without including - m88k.c or needing to include stdio.h). */ - -void -output_label (label_number) - int label_number; -{ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number); -} - -/* Generate the assembly code for function entry. - - The prologue is responsible for setting up the stack frame, - initializing the frame pointer register, saving registers that must be - saved, and allocating SIZE additional bytes of storage for the - local variables. SIZE is an integer. FILE is a stdio - stream to which the assembler code should be output. - - The label for the beginning of the function need not be output by this - macro. That has already been done when the macro is run. - - To determine which registers to save, the macro can refer to the array - `regs_ever_live': element R is nonzero if hard register - R is used anywhere within the function. This implies the - function prologue should save register R, but not if it is one - of the call-used registers. - - On machines where functions may or may not have frame-pointers, the - function entry code must vary accordingly; it must set up the frame - pointer if one is wanted, and not otherwise. To determine whether a - frame pointer is in wanted, the macro can refer to the variable - `frame_pointer_needed'. The variable's value will be 1 at run - time in a function that needs a frame pointer. - - On machines where an argument may be passed partly in registers and - partly in memory, this macro must examine the variable - `current_function_pretend_args_size', and allocate that many bytes - of uninitialized space on the stack just underneath the first argument - arriving on the stack. (This may not be at the very end of the stack, - if the calling sequence has pushed anything else since pushing the stack - arguments. But usually, on such machines, nothing else has been pushed - yet, because the function prologue itself does all the pushing.) - - If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable - `current_function_outgoing_args_size' contains the size in bytes - required for the outgoing arguments. This macro must add that - amount of uninitialized space to very bottom of the stack. - - The stack frame we use looks like this: - - caller callee - |==============================================| - | caller's frame | - |==============================================| - | [caller's outgoing memory arguments] | - |==============================================| - | caller's outgoing argument area (32 bytes) | - sp -> |==============================================| <- ap - | [local variable space] | - |----------------------------------------------| - | [return address (r1)] | - |----------------------------------------------| - | [previous frame pointer (r30)] | - |==============================================| <- fp - | [preserved registers (r25..r14)] | - |----------------------------------------------| - | [preserved registers (x29..x22)] | - |==============================================| - | [dynamically allocated space (alloca)] | - |==============================================| - | [callee's outgoing memory arguments] | - |==============================================| - | [callee's outgoing argument area (32 bytes)] | - |==============================================| <- sp - - Notes: - - r1 and r30 must be saved if debugging. - - fp (if present) is located two words down from the local - variable space. - */ - -static void emit_add (); -static void preserve_registers (); -static void emit_ldst (); -static void output_tdesc (); - -static int nregs; -static int nxregs; -static char save_regs[FIRST_PSEUDO_REGISTER]; -static int frame_laid_out; -static int frame_size; -static int variable_args_p; -static int epilogue_marked; -static int prologue_marked; - -extern char call_used_regs[]; -extern int current_function_pretend_args_size; -extern int current_function_outgoing_args_size; -extern int frame_pointer_needed; - -#define FIRST_OCS_PRESERVE_REGISTER 14 -#define LAST_OCS_PRESERVE_REGISTER 30 - -#define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22) -#define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31) - -#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT) -#define ROUND_CALL_BLOCK_SIZE(BYTES) \ - (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1)) - -/* Establish the position of the FP relative to the SP. This is done - either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */ - -void -m88k_layout_frame () -{ - int regno, sp_size; - - frame_laid_out++; - - bzero ((char *) &save_regs[0], sizeof (save_regs)); - sp_size = nregs = nxregs = 0; - frame_size = get_frame_size (); - - /* Since profiling requires a call, make sure r1 is saved. */ - if (profile_flag || profile_block_flag) - save_regs[1] = 1; - - /* If we are producing debug information, store r1 and r30 where the - debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has - already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */ - if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION) - save_regs[1] = 1; - - /* If there is a call, alloca is used, __builtin_alloca is used, or - a dynamic-sized object is defined, add the 8 additional words - for the callee's argument area. The common denominator is that the - FP is required. may_call_alloca only gets calls to alloca; - current_function_calls_alloca gets alloca and __builtin_alloca. */ - if (regs_ever_live[1] || frame_pointer_needed) - { - save_regs[1] = 1; - sp_size += REG_PARM_STACK_SPACE (0); - } - - /* If we are producing PIC, save the addressing base register and r1. */ - if (flag_pic && current_function_uses_pic_offset_table) - { - save_regs[PIC_OFFSET_TABLE_REGNUM] = 1; - nregs++; - } - - /* If a frame is requested, save the previous FP, and the return - address (r1), so that a traceback can be done without using tdesc - information. Otherwise, simply save the FP if it is used as - a preserve register. */ - if (frame_pointer_needed) - save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1; - else if (regs_ever_live[FRAME_POINTER_REGNUM]) - save_regs[FRAME_POINTER_REGNUM] = 1; - - /* Figure out which extended register(s) needs to be saved. */ - for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER; - regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) - { - save_regs[regno] = 1; - nxregs++; - } - - /* Figure out which normal register(s) needs to be saved. */ - for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) - { - save_regs[regno] = 1; - nregs++; - } - - /* Achieve greatest use of double memory ops. Either we end up saving - r30 or we use that slot to align the registers we do save. */ - if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM]) - sp_size += 4; - - nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM]; - /* if we need to align extended registers, add a word */ - if (nxregs > 0 && (nregs & 1) != 0) - sp_size +=4; - sp_size += 4 * nregs; - sp_size += 8 * nxregs; - sp_size += current_function_outgoing_args_size; - - /* The first two saved registers are placed above the new frame pointer - if any. In the only case this matters, they are r1 and r30. */ - if (frame_pointer_needed || sp_size) - m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET); - else - m88k_fp_offset = -STARTING_FRAME_OFFSET; - m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET; - - /* First, combine m88k_stack_size and size. If m88k_stack_size is - non-zero, align the frame size to 8 mod 16; otherwise align the - frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends - up as a NOP. */ - { - int need - = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0) - - (frame_size % STACK_UNIT_BOUNDARY)); - if (need) - { - if (need < 0) - need += STACK_UNIT_BOUNDARY; - (void) assign_stack_local (BLKmode, need, BITS_PER_UNIT); - frame_size = get_frame_size (); - } - m88k_stack_size - = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size - + current_function_pretend_args_size); - } -} - -/* Return true if this function is known to have a null prologue. */ - -int -null_prologue () -{ - if (! reload_completed) - return 0; - if (! frame_laid_out) - m88k_layout_frame (); - return (! frame_pointer_needed - && nregs == 0 - && nxregs == 0 - && m88k_stack_size == 0); -} - -/* Determine if the current function has any references to the arg pointer. - This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL. - It is OK to return TRUE if there are no references, but FALSE must be - correct. */ - -static int -uses_arg_area_p () -{ - register tree parm; - - if (current_function_decl == 0 - || current_function_varargs - || variable_args_p) - return 1; - - for (parm = DECL_ARGUMENTS (current_function_decl); - parm; - parm = TREE_CHAIN (parm)) - { - if (DECL_RTL (parm) == 0 - || GET_CODE (DECL_RTL (parm)) == MEM) - return 1; - - if (DECL_INCOMING_RTL (parm) == 0 - || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM) - return 1; - } - return 0; -} - -void -m88k_begin_prologue (stream, size) - FILE *stream; - int size; -{ - if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ()) - fprintf (stderr, "$"); - - m88k_prologue_done = 1; /* it's ok now to put out ln directives */ -} - -void -m88k_end_prologue (stream) - FILE *stream; -{ - if (TARGET_OCS_DEBUG_INFO && !prologue_marked) - { - PUT_OCS_FUNCTION_START (stream); - prologue_marked = 1; - - /* If we've already passed the start of the epilogue, say that - it starts here. This marks the function as having a null body, - but at a point where the return address is in a known location. - - Originally, I thought this couldn't happen, but the pic prologue - for leaf functions ends with the instruction that restores the - return address from the temporary register. If the temporary - register is never used, that instruction can float all the way - to the end of the function. */ - if (epilogue_marked) - PUT_OCS_FUNCTION_END (stream); - } -} - -void -m88k_expand_prologue () -{ - m88k_layout_frame (); - - if (TARGET_OPTIMIZE_ARG_AREA - && m88k_stack_size - && ! uses_arg_area_p ()) - { - /* The incoming argument area is used for stack space if it is not - used (or if -mno-optimize-arg-area is given). */ - if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0) - m88k_stack_size = 0; - } - - if (m88k_stack_size) - emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size); - - if (nregs || nxregs) - preserve_registers (m88k_fp_offset + 4, 1); - - if (frame_pointer_needed) - emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset); - - if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]) - { - rtx return_reg = gen_rtx (REG, SImode, 1); - rtx label = gen_label_rtx (); - rtx temp_reg; - - if (! save_regs[1]) - { - temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM); - emit_move_insn (temp_reg, return_reg); - } - emit_insn (gen_locate1 (pic_offset_table_rtx, label)); - emit_insn (gen_locate2 (pic_offset_table_rtx, label)); - emit_insn (gen_addsi3 (pic_offset_table_rtx, - pic_offset_table_rtx, return_reg)); - if (! save_regs[1]) - emit_move_insn (return_reg, temp_reg); - } - if (profile_flag || profile_block_flag) - emit_insn (gen_blockage ()); -} - -/* 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 -m88k_begin_epilogue (stream) - FILE *stream; -{ - if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked) - { - PUT_OCS_FUNCTION_END (stream); - } - epilogue_marked = 1; -} - -void -m88k_end_epilogue (stream, size) - FILE *stream; - int size; -{ - rtx insn = get_last_insn (); - - if (TARGET_OCS_DEBUG_INFO && !epilogue_marked) - PUT_OCS_FUNCTION_END (stream); - - /* If the last insn isn't a BARRIER, we must write a return insn. This - should only happen if the function has no prologue and no body. */ - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - if (insn == 0 || GET_CODE (insn) != BARRIER) - fprintf (stream, "\tjmp\t %s\n", reg_names[1]); - - /* If the last insn is a barrier, and the insn before that is a call, - then add a nop instruction so that tdesc can walk the stack correctly - even though there is no epilogue. (Otherwise, the label for the - end of the tdesc region ends up at the start of the next function. */ - if (insn && GET_CODE (insn) == BARRIER) - { - insn = prev_nonnote_insn (insn); - if (insn && GET_CODE (insn) == CALL_INSN) - fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]); - } - - output_short_branch_defs (stream); - - fprintf (stream, "\n"); - - if (TARGET_OCS_DEBUG_INFO) - output_tdesc (stream, m88k_fp_offset + 4); - - m88k_function_number++; - m88k_prologue_done = 0; /* don't put out ln directives */ - variable_args_p = 0; /* has variable args */ - frame_laid_out = 0; - epilogue_marked = 0; - prologue_marked = 0; -} - -void -m88k_expand_epilogue () -{ -#if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */ - fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n", - size, m88k_fp_offset, m88k_stack_size); -#endif - - if (frame_pointer_needed) - emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset); - - if (nregs || nxregs) - preserve_registers (m88k_fp_offset + 4, 0); - - if (m88k_stack_size) - emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size); -} - -/* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or - epilogue. */ - -static void -emit_add (dstreg, srcreg, amount) - rtx dstreg; - rtx srcreg; - int amount; -{ - rtx incr = GEN_INT (abs (amount)); - if (! ADD_INTVAL (amount)) - { - rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM); - emit_move_insn (temp, incr); - incr = temp; - } - emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr)); -} - -/* Save/restore the preserve registers. base is the highest offset from - r31 at which a register is stored. store_p is true if stores are to - be done; otherwise loads. */ - -static void -preserve_registers (base, store_p) - int base; - int store_p; -{ - int regno, offset; - struct mem_op { - int regno; - int nregs; - int offset; - } mem_op[FIRST_PSEUDO_REGISTER]; - struct mem_op *mo_ptr = mem_op; - - /* The 88open OCS mandates that preserved registers be stored in - increasing order. For compatibility with current practice, - the order is r1, r30, then the preserve registers. */ - - offset = base; - if (save_regs[1]) - { - /* An extra word is given in this case to make best use of double - memory ops. */ - if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM]) - offset -= 4; - emit_ldst (store_p, 1, SImode, offset); - offset -= 4; - base = offset; - } - - /* Walk the registers to save recording all single memory operations. */ - for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--) - if (save_regs[regno]) - { - if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1]) - { - mo_ptr->nregs = 1; - mo_ptr->regno = regno; - mo_ptr->offset = offset; - mo_ptr++; - offset -= 4; - } - else - { - regno--; - offset -= 2*4; - } - } - - /* Walk the registers to save recording all double memory operations. - This avoids a delay in the epilogue (ld.d/ld). */ - offset = base; - for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--) - if (save_regs[regno]) - { - if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1]) - { - offset -= 4; - } - else - { - mo_ptr->nregs = 2; - mo_ptr->regno = regno-1; - mo_ptr->offset = offset-4; - mo_ptr++; - regno--; - offset -= 2*4; - } - } - - /* Walk the extended registers to record all memory operations. */ - /* Be sure the offset is double word aligned. */ - offset = (offset - 1) & ~7; - for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER; - regno--) - if (save_regs[regno]) - { - mo_ptr->nregs = 2; - mo_ptr->regno = regno; - mo_ptr->offset = offset; - mo_ptr++; - offset -= 2*4; - } - - mo_ptr->regno = 0; - - /* Output the memory operations. */ - for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++) - { - if (mo_ptr->nregs) - emit_ldst (store_p, mo_ptr->regno, - (mo_ptr->nregs > 1 ? DImode : SImode), - mo_ptr->offset); - } -} - -static void -emit_ldst (store_p, regno, mode, offset) - int store_p; - int regno; - enum machine_mode mode; - int offset; -{ - rtx reg = gen_rtx (REG, mode, regno); - rtx mem; - - if (SMALL_INTVAL (offset)) - { - mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset)); - } - else - { - /* offset is too large for immediate index must use register */ - - rtx disp = GEN_INT (offset); - rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM); - rtx regi = gen_rtx (PLUS, SImode, stack_pointer_rtx, temp); - emit_move_insn (temp, disp); - mem = gen_rtx (MEM, mode, regi); - } - - if (store_p) - emit_move_insn (mem, reg); - else - emit_move_insn (reg, mem); -} - -/* Convert the address expression REG to a CFA offset. */ - -int -m88k_debugger_offset (reg, offset) - register rtx reg; - register int offset; -{ - if (GET_CODE (reg) == PLUS) - { - offset = INTVAL (XEXP (reg, 1)); - reg = XEXP (reg, 0); - } - - /* Put the offset in terms of the CFA (arg pointer). */ - if (reg == frame_pointer_rtx) - offset += m88k_fp_offset - m88k_stack_size; - else if (reg == stack_pointer_rtx) - offset -= m88k_stack_size; - else if (reg != arg_pointer_rtx) - { -#if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */ - if (! (GET_CODE (reg) == REG - && REGNO (reg) >= FIRST_PSEUDO_REGISTER)) - warning ("Internal gcc error: Can't express symbolic location"); -#endif - return 0; - } - - return offset; -} - -/* Output the 88open OCS proscribed text description information. - The information is: - 0 8: zero - 0 22: info-byte-length (16 or 20 bytes) - 0 2: info-alignment (word 2) - 1 32: info-protocol (version 1 or 2(pic)) - 2 32: starting-address (inclusive, not counting prologue) - 3 32: ending-address (exclusive, not counting epilog) - 4 8: info-variant (version 1 or 3(extended registers)) - 4 17: register-save-mask (from register 14 to 30) - 4 1: zero - 4 1: return-address-info-discriminant - 4 5: frame-address-register - 5 32: frame-address-offset - 6 32: return-address-info - 7 32: register-save-offset - 8 16: extended-register-save-mask (x16 - x31) - 8 16: extended-register-save-offset (WORDS from register-save-offset) */ - -static void -output_tdesc (file, offset) - FILE *file; - int offset; -{ - int regno, i, j; - long mask, return_address_info, register_save_offset; - long xmask, xregister_save_offset; - char buf[256]; - - for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER; - regno <= LAST_OCS_PRESERVE_REGISTER; - regno++) - { - mask <<= 1; - if (save_regs[regno]) - { - mask |= 1; - i++; - } - } - - for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER; - regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER; - regno++) - { - xmask <<= 1; - if (save_regs[regno]) - { - xmask |= 1; - j++; - } - } - - if (save_regs[1]) - { - if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM]) - offset -= 4; - return_address_info = - m88k_stack_size + offset; - register_save_offset = return_address_info - i*4; - } - else - { - return_address_info = 1; - register_save_offset = - m88k_stack_size + offset + 4 - i*4; - } - - xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1)); - - tdesc_section (); - - fprintf (file, "\t%s\t %d,%d", INT_ASM_OP, /* 8:0,22:(20 or 16),2:2 */ - (((xmask != 0) ? 20 : 16) << 2) | 2, - flag_pic ? 2 : 1); - - ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number); - fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : ""); - ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number); - fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : ""); - - fprintf (file, ",0x%x,0x%x,0x%x,0x%x", - /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */ - (((xmask ? 3 : 1) << (17+1+1+5)) - | (mask << (1+1+5)) - | ((!!save_regs[1]) << 5) - | (frame_pointer_needed - ? FRAME_POINTER_REGNUM - : STACK_POINTER_REGNUM)), - (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)), - return_address_info, - register_save_offset); - if (xmask) - fprintf (file, ",0x%x%04x", xmask, (0xffff & xregister_save_offset)); - fputc ('\n', file); - - text_section (); -} - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. NAME is the mcount function name - (varies), SAVEP indicates whether the parameter registers need to - be saved and restored. */ - -void -output_function_profiler (file, labelno, name, savep) - FILE *file; - int labelno; - char *name; - int savep; -{ - char label[256]; - char dbi[256]; - char *temp = (savep ? reg_names[2] : reg_names[10]); - - /* Remember to update FUNCTION_PROFILER_LENGTH. */ - - if (savep) - { - fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]); - } - - ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno); - if (flag_pic == 2) - { - fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n", - temp, reg_names[0], m88k_pound_sign, &label[1]); - fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n", - temp, temp, m88k_pound_sign, &label[1]); - sprintf (dbi, "\tld\t %s,%s,%s\n", temp, - reg_names[PIC_OFFSET_TABLE_REGNUM], temp); - } - else if (flag_pic) - { - sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp, - reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]); - } - else - { - fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", - temp, reg_names[0], m88k_pound_sign, &label[1]); - sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n", - temp, temp, m88k_pound_sign, &label[1]); - } - - if (flag_pic) - fprintf (file, "\tbsr.n\t %s#plt\n", name); - else - fprintf (file, "\tbsr.n\t %s\n", name); - fputs (dbi, file); - - if (savep) - { - fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]); - fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]); - } -} - -/* Output assembler code to FILE to initialize basic-block profiling for - the current module. LABELNO is unique to each instance. */ - -void -output_function_block_profiler (file, labelno) - FILE *file; - int labelno; -{ - char block[256]; - char label[256]; - - /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */ - - ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0); - ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno); - - /* @@ Need to deal with PIC. I'm not sure what the requirements are on - register usage, so I used r26/r27 to be safe. */ - fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names[27], reg_names[0], - m88k_pound_sign, &block[1]); - fprintf (file, "\tld\t %s,%s,%slo16(%s)\n", reg_names[26], reg_names[27], - m88k_pound_sign, &block[1]); - fprintf (file, "\tbcnd\t %sne0,%s,%s\n", - m88k_pound_sign, reg_names[26], &label[1]); - fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]); - fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]); - fputs ("\tbsr.n\t ", file); - ASM_OUTPUT_LABELREF (file, "__bb_init_func"); - putc ('\n', file); - fprintf (file, "\tor\t %s,%s,%slo16(%s)\n", reg_names[2], reg_names[27], - m88k_pound_sign, &block[1]); - fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]); - fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]); - fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]); - ASM_OUTPUT_INTERNAL_LABEL (file, "LPY", labelno); -} - -/* Output assembler code to FILE to increment the count associated with - the basic block number BLOCKNO. */ - -void -output_block_profiler (file, blockno) - FILE *file; - int blockno; -{ - char block[256]; - - /* Remember to update BLOCK_PROFILER_LENGTH. */ - - ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2); - - /* @@ Need to deal with PIC. I'm not sure what the requirements are on - register usage, so I used r26/r27 to be safe. */ - fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0], - m88k_pound_sign, &block[1], 4 * blockno); - fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27], - m88k_pound_sign, &block[1], 4 * blockno); - fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]); - fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27], - m88k_pound_sign, &block[1], 4 * blockno); -} - -/* Determine whether a function argument is passed in a register, and - which register. - - The arguments are CUM, which summarizes all the previous - arguments; MODE, the machine mode of the argument; TYPE, - the data type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, - which is 1 for an ordinary argument and 0 for nameless arguments that - correspond to `...' in the called function's prototype. - - The value of the expression should either be a `reg' RTX for the - hard register in which to pass the argument, or zero to pass the - argument on the stack. - - On the m88000 the first eight words of args are normally in registers - and the rest are pushed. Double precision floating point must be - double word aligned (and if in a register, starting on an even - register). Structures and unions which are not 4 byte, and word - aligned are passed in memory rather than registers, even if they - would fit completely in the registers under OCS rules. - - Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different. - For structures that are passed in memory, but could have been - passed in registers, we first load the structure into the - register, and then when the last argument is passed, we store - the registers into the stack locations. This fixes some bugs - where GCC did not expect to have register arguments, followed - by stack arguments, followed by register arguments. */ - -struct rtx_def * -m88k_function_arg (args_so_far, mode, type, named) - CUMULATIVE_ARGS args_so_far; - enum machine_mode mode; - tree type; - int named; -{ - int bytes, words; - - if (type != 0 /* undo putting struct in register */ - && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)) - mode = BLKmode; - - if (mode == BLKmode && TARGET_WARN_PASS_STRUCT) - warning ("argument #%d is a structure", args_so_far + 1); - - if ((args_so_far & 1) != 0 - && (mode == DImode || mode == DFmode - || (type != 0 && TYPE_ALIGN (type) > 32))) - args_so_far++; - -#ifdef ESKIT - if (no_reg_params) - return (rtx) 0; /* don't put args in registers */ -#endif - - if (type == 0 && mode == BLKmode) - abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */ - - bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type); - words = (bytes + 3) / 4; - - if (args_so_far + words > 8) - return (rtx) 0; /* args have exhausted registers */ - - else if (mode == BLKmode - && (TYPE_ALIGN (type) != BITS_PER_WORD - || bytes != UNITS_PER_WORD)) - return (rtx) 0; - - return gen_rtx (REG, - ((mode == BLKmode) ? TYPE_MODE (type) : mode), - 2 + args_so_far); -} - -/* Do what is necessary for `va_start'. The argument is ignored; - We look at the current function to determine if stdargs or varargs - is used and fill in an initial va_list. A pointer to this constructor - is returned. */ - -struct rtx_def * -m88k_builtin_saveregs (arglist) - tree arglist; -{ - rtx block, addr, argsize, dest; - tree fntype = TREE_TYPE (current_function_decl); - int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node))) - ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1; - int fixed; - variable_args_p = 1; - - if (CONSTANT_P (current_function_arg_offset_rtx)) - { - fixed = (XINT (current_function_arg_offset_rtx, 0) - + argadj) / UNITS_PER_WORD; - argsize = GEN_INT (fixed); - } - else - { - fixed = 0; - argsize = plus_constant (current_function_arg_offset_rtx, argadj); - argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize, - build_int_2 (2, 0), argsize, 0); - } - - /* Allocate the va_list constructor */ - block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD); - MEM_SET_IN_STRUCT_P (block, 1); - RTX_UNCHANGING_P (block) = 1; - RTX_UNCHANGING_P (XEXP (block, 0)) = 1; - - /* Store the argsize as the __va_arg member. */ - emit_move_insn (change_address (block, SImode, XEXP (block, 0)), - argsize); - - /* Store the arg pointer in the __va_stk member. */ - emit_move_insn (change_address (block, Pmode, - plus_constant (XEXP (block, 0), - UNITS_PER_WORD)), - copy_to_reg (virtual_incoming_args_rtx)); - - /* Allocate the register space, and store it as the __va_reg member. */ - addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1); - MEM_SET_IN_STRUCT_P (addr, 1); - RTX_UNCHANGING_P (addr) = 1; - RTX_UNCHANGING_P (XEXP (addr, 0)) = 1; - emit_move_insn (change_address (block, Pmode, - plus_constant (XEXP (block, 0), - 2 * UNITS_PER_WORD)), - copy_to_reg (XEXP (addr, 0))); - - /* Now store the incoming registers. */ - if (fixed < 8) - { - dest = change_address (addr, Pmode, - plus_constant (XEXP (addr, 0), - fixed * UNITS_PER_WORD)); - move_block_from_reg (2 + fixed, dest, 8 - fixed, - UNITS_PER_WORD * (8 - fixed)); - } - - if (current_function_check_memory_usage) - { - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - block, ptr_mode, - GEN_INT (3 * UNITS_PER_WORD), TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - if (fixed < 8) - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - dest, ptr_mode, - GEN_INT (UNITS_PER_WORD * (8 - fixed)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - } - - /* Return the address of the va_list constructor, but don't put it in a - register. This fails when not optimizing and produces worse code when - optimizing. */ - return XEXP (block, 0); -} - -/* If cmpsi has not been generated, emit code to do the test. Return the - expression describing the test of operator OP. */ - -rtx -emit_test (op, mode) - enum rtx_code op; - enum machine_mode mode; -{ - if (m88k_compare_reg == 0) - emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1)); - return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx)); -} - -/* Determine how to best perform cmpsi/bxx, where cmpsi has a constant - operand. All tests with zero (albeit swapped) and all equality tests - with a constant are done with bcnd. The remaining cases are swapped - as needed. */ - -void -emit_bcnd (op, label) - enum rtx_code op; - rtx label; -{ - if (m88k_compare_op1 == const0_rtx) - emit_jump_insn( gen_bcnd ( - gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx), - label)); - else if (m88k_compare_op0 == const0_rtx) - emit_jump_insn( gen_bcnd( - gen_rtx( - swap_condition (op), - VOIDmode, m88k_compare_op1, const0_rtx), - label)); - else if (op != EQ && op != NE) - emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label)); - else - { - rtx zero = gen_reg_rtx (SImode); - rtx reg, constant; - int value; - - if (GET_CODE (m88k_compare_op1) == CONST_INT) - { - reg = force_reg (SImode, m88k_compare_op0); - constant = m88k_compare_op1; - } - else - { - reg = force_reg (SImode, m88k_compare_op1); - constant = m88k_compare_op0; - } - value = INTVAL (constant); - - /* Perform an arithmetic computation to make the compared-to value - zero, but avoid loosing if the bcnd is later changed into sxx. */ - if (SMALL_INTVAL (value)) - emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label)); - else - { - if (SMALL_INTVAL (-value)) - emit_insn (gen_addsi3 (zero, reg, - GEN_INT (-value))); - else - emit_insn (gen_xorsi3 (zero, reg, constant)); - - emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode, - zero, const0_rtx), - label)); - } - } -} - -/* Print an operand. Recognize special options, documented below. */ - -void -print_operand (file, x, code) - FILE *file; - rtx x; - char code; -{ - enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN); - register int value = (xc == CONST_INT ? INTVAL (x) : 0); - static int sequencep; - static int reversep; - - if (sequencep) - { - if (code < 'B' || code > 'E') - output_operand_lossage ("%R not followed by %B/C/D/E"); - if (reversep) - xc = reverse_condition (xc); - sequencep = 0; - } - - switch (code) - { - case '*': /* addressing base register for PIC */ - fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return; - - case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */ - fputs (m88k_pound_sign, file); return; - - case 'V': /* Output a serializing instruction as needed if the operand - (assumed to be a MEM) is a volatile load. */ - case 'v': /* ditto for a volatile store. */ - if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE) - { - /* The m88110 implements two FIFO queues, one for loads and - one for stores. These queues mean that loads complete in - their issue order as do stores. An interaction between the - history buffer and the store reservation station ensures - that a store will not bypass load. Finally, a load will not - bypass store, but only when they reference the same address. - - To avoid this reordering (a load bypassing a store) for - volatile references, a serializing instruction is output. - We choose the fldcr instruction as it does not serialize on - the m88100 so that -m88000 code will not be degraded. - - The mechanism below is completed by having CC_STATUS_INIT set - the code to the unknown value. */ - - /* - hassey 6/30/93 - A problem with 88110 4.1 & 4.2 makes the use of fldcr for - this purpose undesirable. Instead we will use tb1, this will - cause serialization on the 88100 but such is life. - */ - - static rtx last_addr = 0; - if (code == 'V' /* Only need to serialize before a load. */ - && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */ - && !(m88k_volatile_code == 'v' - && GET_CODE (XEXP (x, 0)) == LO_SUM - && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr))) - fprintf (file, -#if 0 -#ifdef AS_BUG_FLDCR - "fldcr\t %s,%scr63\n\t", -#else - "fldcr\t %s,%sfcr63\n\t", -#endif - reg_names[0], m88k_pound_sign); -#else /* 0 */ - "tb1\t 1,%s,0xff\n\t", reg_names[0]); -#endif /* 0 */ - m88k_volatile_code = code; - last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM - ? XEXP (XEXP (x, 0), 1) : 0); - } - return; - - case 'X': /* print the upper 16 bits... */ - value >>= 16; - case 'x': /* print the lower 16 bits of the integer constant in hex */ - if (xc != CONST_INT) - output_operand_lossage ("invalid %x/X value"); - fprintf (file, "0x%x", value & 0xffff); return; - - case 'H': /* print the low 16 bits of the negated integer constant */ - if (xc != CONST_INT) - output_operand_lossage ("invalid %H value"); - value = -value; - case 'h': /* print the register or low 16 bits of the integer constant */ - if (xc == REG) - goto reg; - if (xc != CONST_INT) - output_operand_lossage ("invalid %h value"); - fprintf (file, "%d", value & 0xffff); - return; - - case 'Q': /* print the low 8 bits of the negated integer constant */ - if (xc != CONST_INT) - output_operand_lossage ("invalid %Q value"); - value = -value; - case 'q': /* print the register or low 8 bits of the integer constant */ - if (xc == REG) - goto reg; - if (xc != CONST_INT) - output_operand_lossage ("invalid %q value"); - fprintf (file, "%d", value & 0xff); - return; - - case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */ - if (xc != CONST_INT) - output_operand_lossage ("invalid %o value"); - fprintf (file, "%d", value == 32 ? 0 : 32 - value); - return; - - case 'p': /* print the logarithm of the integer constant */ - if (xc != CONST_INT - || (value = exact_log2 (value)) < 0) - output_operand_lossage ("invalid %p value"); - fprintf (file, "%d", value); - return; - - case 'S': /* compliment the value and then... */ - value = ~value; - case 's': /* print the width and offset values forming the integer - constant with a SET instruction. See integer_ok_for_set. */ - { - register unsigned mask, uval = value; - register int top, bottom; - - if (xc != CONST_INT) - output_operand_lossage ("invalid %s/S value"); - /* All the "one" bits must be contiguous. If so, MASK will be - a power of two or zero. */ - mask = (uval | (uval - 1)) + 1; - if (!(uval && POWER_OF_2_or_0 (mask))) - output_operand_lossage ("invalid %s/S value"); - top = mask ? exact_log2 (mask) : 32; - bottom = exact_log2 (uval & ~(uval - 1)); - fprintf (file,"%d<%d>", top - bottom, bottom); - return; - } - - case 'P': /* print nothing if pc_rtx; output label_ref */ - if (xc == LABEL_REF) - output_addr_const (file, x); - else if (xc != PC) - output_operand_lossage ("invalid %P operand"); - return; - - case 'L': /* print 0 or 1 if operand is label_ref and then... */ - fputc (xc == LABEL_REF ? '1' : '0', file); - case '.': /* print .n if delay slot is used */ - fputs ((final_sequence - && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) - ? ".n\t" : "\t", file); - return; - - case '!': /* Reverse the following condition. */ - sequencep++; - reversep = 1; - return; - case 'R': /* reverse the condition of the next print_operand - if operand is a label_ref. */ - sequencep++; - reversep = (xc == LABEL_REF); - return; - - case 'B': /* bcnd branch values */ - fputs (m88k_pound_sign, file); - switch (xc) - { - case EQ: fputs ("eq0", file); return; - case NE: fputs ("ne0", file); return; - case GT: fputs ("gt0", file); return; - case LE: fputs ("le0", file); return; - case LT: fputs ("lt0", file); return; - case GE: fputs ("ge0", file); return; - default: output_operand_lossage ("invalid %B value"); - } - - case 'C': /* bb0/bb1 branch values for comparisons */ - fputs (m88k_pound_sign, file); - switch (xc) - { - case EQ: fputs ("eq", file); return; - case NE: fputs ("ne", file); return; - case GT: fputs ("gt", file); return; - case LE: fputs ("le", file); return; - case LT: fputs ("lt", file); return; - case GE: fputs ("ge", file); return; - case GTU: fputs ("hi", file); return; - case LEU: fputs ("ls", file); return; - case LTU: fputs ("lo", file); return; - case GEU: fputs ("hs", file); return; - default: output_operand_lossage ("invalid %C value"); - } - - case 'D': /* bcnd branch values for float comparisons */ - switch (xc) - { - case EQ: fputs ("0xa", file); return; - case NE: fputs ("0x5", file); return; - case GT: fputs (m88k_pound_sign, file); - fputs ("gt0", file); return; - case LE: fputs ("0xe", file); return; - case LT: fputs ("0x4", file); return; - case GE: fputs ("0xb", file); return; - default: output_operand_lossage ("invalid %D value"); - } - - case 'E': /* bcnd branch values for special integers */ - switch (xc) - { - case EQ: fputs ("0x8", file); return; - case NE: fputs ("0x7", file); return; - default: output_operand_lossage ("invalid %E value"); - } - - case 'd': /* second register of a two register pair */ - if (xc != REG) - output_operand_lossage ("`%d' operand isn't a register"); - fputs (reg_names[REGNO (x) + 1], file); - return; - - case 'r': /* an immediate 0 should be represented as `r0' */ - if (x == const0_rtx) - { - fputs (reg_names[0], file); - return; - } - else if (xc != REG) - output_operand_lossage ("invalid %r value"); - case 0: - name: - if (xc == REG) - { - reg: - if (REGNO (x) == ARG_POINTER_REGNUM) - output_operand_lossage ("operand is r0"); - else - fputs (reg_names[REGNO (x)], file); - } - else if (xc == PLUS) - output_address (x); - else if (xc == MEM) - output_address (XEXP (x, 0)); - else if (flag_pic && xc == UNSPEC) - { - output_addr_const (file, XVECEXP (x, 0, 0)); - fputs ("#got_rel", file); - } - else if (xc == CONST_DOUBLE) - output_operand_lossage ("operand is const_double"); - else - output_addr_const (file, x); - return; - - case 'g': /* append #got_rel as needed */ - if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF)) - { - output_addr_const (file, x); - fputs ("#got_rel", file); - return; - } - goto name; - - case 'a': /* (standard), assume operand is an address */ - case 'c': /* (standard), assume operand is an immediate value */ - case 'l': /* (standard), assume operand is a label_ref */ - case 'n': /* (standard), like %c, except negate first */ - default: - output_operand_lossage ("invalid code"); - } -} - -void -print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - register rtx reg0, reg1, temp; - - switch (GET_CODE (addr)) - { - case REG: - if (REGNO (addr) == ARG_POINTER_REGNUM) - abort (); - else - fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]); - break; - - case LO_SUM: - fprintf (file, "%s,%slo16(", - reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign); - output_addr_const (file, XEXP (addr, 1)); - fputc (')', file); - break; - - case PLUS: - reg0 = XEXP (addr, 0); - reg1 = XEXP (addr, 1); - if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT) - { - rtx tmp = reg0; - reg0 = reg1; - reg1 = tmp; - } - - if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM) - || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM)) - abort (); - - else if (REG_P (reg0)) - { - if (REG_P (reg1)) - fprintf (file, "%s,%s", - reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]); - - else if (GET_CODE (reg1) == CONST_INT) - fprintf (file, "%s,%d", - reg_names [REGNO (reg0)], INTVAL (reg1)); - - else if (GET_CODE (reg1) == MULT) - { - rtx mreg = XEXP (reg1, 0); - if (REGNO (mreg) == ARG_POINTER_REGNUM) - abort (); - - fprintf (file, "%s[%s]", reg_names[REGNO (reg0)], - reg_names[REGNO (mreg)]); - } - - else if (GET_CODE (reg1) == ZERO_EXTRACT) - { - fprintf (file, "%s,%slo16(", - reg_names[REGNO (reg0)], m88k_pound_sign); - output_addr_const (file, XEXP (reg1, 0)); - fputc (')', file); - } - - else if (flag_pic) - { - fprintf (file, "%s,", reg_names[REGNO (reg0)]); - output_addr_const (file, reg1); - fputs ("#got_rel", file); - } - else abort (); - } - - else - abort (); - break; - - case MULT: - if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM) - abort (); - - fprintf (file, "%s[%s]", - reg_names[0], reg_names[REGNO (XEXP (addr, 0))]); - break; - - case CONST_INT: - fprintf (file, "%s,%d", reg_names[0], INTVAL (addr)); - break; - - default: - fprintf (file, "%s,", reg_names[0]); - if (SHORT_ADDRESS_P (addr, temp)) - { - fprintf (file, "%siw16(", m88k_pound_sign); - output_addr_const (file, addr); - fputc (')', file); - } - else - output_addr_const (file, addr); - } -} - -/* Return true if X is an address which needs a temporary register when - reloaded while generating PIC code. */ - -int -pic_address_needs_scratch (x) - rtx x; -{ - /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ - if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && ! ADD_INT (XEXP (XEXP (x, 0), 1))) - return 1; - - return 0; -} - -/* 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; -{ - 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); - - /* ??? This clause seems to be irrelevant. */ - case CONST_DOUBLE: - return GET_MODE (op) == mode; - - default: - return 0; - } -} diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h deleted file mode 100755 index 5735560..0000000 --- a/gcc/config/m88k/m88k.h +++ /dev/null @@ -1,2646 +0,0 @@ -/* Definitions of target machine for GNU compiler for - Motorola m88100 in an 88open OCS/BCS environment. - Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@cygnus.com). - Currently maintained by (gcc@dg-rtp.dg.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. */ - -/* The m88100 port of GNU CC adheres to the various standards from 88open. - These documents are available by writing: - - 88open Consortium Ltd. - 100 Homeland Court, Suite 800 - San Jose, CA 95112 - (408) 436-6600 - - In brief, the current standards are: - - Binary Compatibility Standard, Release 1.1A, May 1991 - This provides for portability of application-level software at the - executable level for AT&T System V Release 3.2. - - Object Compatibility Standard, Release 1.1A, May 1991 - This provides for portability of application-level software at the - object file and library level for C, Fortran, and Cobol, and again, - largely for SVR3. - - Under development are standards for AT&T System V Release 4, based on the - [generic] System V Application Binary Interface from AT&T. These include: - - System V Application Binary Interface, Motorola 88000 Processor Supplement - Another document from AT&T for SVR4 specific to the m88100. - Available from Prentice Hall. - - System V Application Binary Interface, Motorola 88000 Processor Supplement, - Release 1.1, Draft H, May 6, 1991 - A proposed update to the AT&T document from 88open. - - System V ABI Implementation Guide for the M88000 Processor, - Release 1.0, January 1991 - A companion ABI document from 88open. */ - -/* Other *.h files in config/m88k include this one and override certain items. - Currently these are sysv3.h, sysv4.h, dgux.h, dolph.h, tekXD88.h, and luna.h. - Additionally, sysv4.h and dgux.h include svr4.h first. All other - m88k targets except luna.h are based on svr3.h. */ - -/* Choose SVR3 as the default. */ -#if !defined(DBX_DEBUGGING_INFO) && !defined(DWARF_DEBUGGING_INFO) -#include "svr3.h" -#endif - -/* External types used. */ - -/* What instructions are needed to manufacture an integer constant. */ -enum m88k_instruction { - m88k_zero, - m88k_or, - m88k_subu, - m88k_or_lo16, - m88k_or_lo8, - m88k_set, - m88k_oru_hi16, - m88k_oru_or -}; - -/* Which processor to schedule for. The elements of the enumeration - must match exactly the cpu attribute in the m88k.md machine description. */ - -enum processor_type { - PROCESSOR_M88100, - PROCESSOR_M88110, - PROCESSOR_M88000, -}; - -/* Recast the cpu class to be the cpu attribute. */ -#define m88k_cpu_attr ((enum attr_cpu)m88k_cpu) - -/* External variables/functions defined in m88k.c. */ - -extern char *m88k_pound_sign; -extern char *m88k_short_data; -extern char *m88k_version; -extern char m88k_volatile_code; - -extern unsigned m88k_gp_threshold; -extern int m88k_prologue_done; -extern int m88k_function_number; -extern int m88k_fp_offset; -extern int m88k_stack_size; -extern int m88k_case_index; - -extern struct rtx_def *m88k_compare_reg; -extern struct rtx_def *m88k_compare_op0; -extern struct rtx_def *m88k_compare_op1; - -extern enum processor_type m88k_cpu; - -extern int null_prologue (); -extern int integer_ok_for_set (); -extern int m88k_debugger_offset (); - - -extern void emit_bcnd (); -extern void expand_block_move (); -extern void m88k_layout_frame (); -extern void m88k_expand_prologue (); -extern void m88k_begin_prologue (); -extern void m88k_end_prologue (); -extern void m88k_expand_epilogue (); -extern void m88k_begin_epilogue (); -extern void m88k_end_epilogue (); -extern void output_function_profiler (); -extern void output_function_block_profiler (); -extern void output_block_profiler (); -extern void output_file_start (); -extern void output_ascii (); -extern void output_label (); -extern void print_operand (); -extern void print_operand_address (); - -extern char *output_load_const_int (); -extern char *output_load_const_float (); -extern char *output_load_const_double (); -extern char *output_load_const_dimode (); -extern char *output_and (); -extern char *output_ior (); -extern char *output_xor (); -extern char *output_call (); - -extern struct rtx_def *emit_test (); -extern struct rtx_def *legitimize_address (); -extern struct rtx_def *legitimize_operand (); -extern struct rtx_def *m88k_function_arg (); -extern struct rtx_def *m88k_builtin_saveregs (); - -extern enum m88k_instruction classify_integer (); - -/* external variables defined elsewhere in the compiler */ - -extern int target_flags; /* -m compiler switches */ -extern int frame_pointer_needed; /* current function has a FP */ -extern int current_function_pretend_args_size; /* args size without ... */ -extern int flag_delayed_branch; /* -fdelayed-branch */ -extern int flag_pic; /* -fpic */ -extern char * reg_names[]; - -/* Specify the default monitors. The meaning of these values can - be obtained by doing "grep MONITOR_GCC *m88k*". Generally, the - values downward from 0x8000 are tests that will soon go away. - values upward from 0x1 are generally useful tests that will remain. */ - -#ifndef MONITOR_GCC -#define MONITOR_GCC 0 -#endif - -/*** Controlling the Compilation Driver, `gcc' ***/ -/* Show we can debug even without a frame pointer. */ -#define CAN_DEBUG_WITHOUT_FP - -/* If -m88100 is in effect, add -D__m88100__; similarly for -m88110. - Here, the CPU_DEFAULT is assumed to be -m88100. */ -#undef CPP_SPEC -#define CPP_SPEC "%{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \ - %{!m88000:%{!m88110:-D__m88100__}}" - -/* LIB_SPEC, LINK_SPEC, and STARTFILE_SPEC defined in svr3.h. - ASM_SPEC, ASM_FINAL_SPEC, LIB_SPEC, LINK_SPEC, and STARTFILE_SPEC redefined - in svr4.h. - CPP_SPEC, ASM_SPEC, ASM_FINAL_SPEC, LIB_SPEC, LINK_SPEC, and - STARTFILE_SPEC redefined in dgux.h. */ - -/*** Run-time Target Specification ***/ - -/* Names to predefine in the preprocessor for this target machine. - Redefined in sysv3.h, sysv4.h, dgux.h, and luna.h. */ -#define CPP_PREDEFINES "-Dm88000 -Dm88k -Dunix -D__CLASSIFY_TYPE__=2" - -#define TARGET_VERSION fprintf (stderr, " (%s%s)", \ - VERSION_INFO1, VERSION_INFO2) - -/* Print subsidiary information on the compiler version in use. - Redefined in sysv4.h, and luna.h. */ -#define VERSION_INFO1 "m88k, " -#ifndef VERSION_INFO2 -#define VERSION_INFO2 "$Revision: 1.70 $" -#endif - -#ifndef VERSION_STRING -#define VERSION_STRING version_string -#ifdef __STDC__ -#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.70 $ " __DATE__ -#else -#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $" -#endif /* __STDC__ */ -#else -#define TM_RCS_ID "@(#)" __FILE__ " " VERSION_INFO2 " " __DATE__ -#endif /* VERSION_STRING */ - -/* Run-time compilation parameters selecting different hardware subsets. */ - -/* 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 MASK_88100 0x00000001 /* Target m88100 */ -#define MASK_88110 0x00000002 /* Target m88110 */ -#define MASK_88000 (MASK_88100 | MASK_88110) - -#define MASK_OCS_DEBUG_INFO 0x00000004 /* Emit .tdesc info */ -#define MASK_OCS_FRAME_POSITION 0x00000008 /* Debug frame = CFA, not r30 */ -#define MASK_SVR4 0x00000010 /* Target is AT&T System V.4 */ -#define MASK_SVR3 0x00000020 /* Target is AT&T System V.3 */ -#define MASK_NO_UNDERSCORES 0x00000040 /* Don't emit a leading `_' */ -#define MASK_BIG_PIC 0x00000080 /* PIC with large got-rel's -fPIC */ -#define MASK_TRAP_LARGE_SHIFT 0x00000100 /* Trap if shift not <= 31 */ -#define MASK_HANDLE_LARGE_SHIFT 0x00000200 /* Handle shift count >= 32 */ -#define MASK_CHECK_ZERO_DIV 0x00000400 /* Check for int div. by 0 */ -#define MASK_USE_DIV 0x00000800 /* No signed div. checks */ -#define MASK_IDENTIFY_REVISION 0x00001000 /* Emit ident, with GCC rev */ -#define MASK_WARN_PASS_STRUCT 0x00002000 /* Warn about passed structs */ -#define MASK_OPTIMIZE_ARG_AREA 0x00004000 /* Save stack space */ -#define MASK_NO_SERIALIZE_VOLATILE 0x00008000 /* Serialize volatile refs */ -#define MASK_EITHER_LARGE_SHIFT (MASK_TRAP_LARGE_SHIFT | \ - MASK_HANDLE_LARGE_SHIFT) -#define MASK_OMIT_LEAF_FRAME_POINTER 0x00020000 /* omit leaf frame pointers */ - - -#define TARGET_88100 ((target_flags & MASK_88000) == MASK_88100) -#define TARGET_88110 ((target_flags & MASK_88000) == MASK_88110) -#define TARGET_88000 ((target_flags & MASK_88000) == MASK_88000) - -#define TARGET_OCS_DEBUG_INFO (target_flags & MASK_OCS_DEBUG_INFO) -#define TARGET_OCS_FRAME_POSITION (target_flags & MASK_OCS_FRAME_POSITION) -#define TARGET_SVR4 (target_flags & MASK_SVR4) -#define TARGET_SVR3 (target_flags & MASK_SVR3) -#define TARGET_NO_UNDERSCORES (target_flags & MASK_NO_UNDERSCORES) -#define TARGET_BIG_PIC (target_flags & MASK_BIG_PIC) -#define TARGET_TRAP_LARGE_SHIFT (target_flags & MASK_TRAP_LARGE_SHIFT) -#define TARGET_HANDLE_LARGE_SHIFT (target_flags & MASK_HANDLE_LARGE_SHIFT) -#define TARGET_CHECK_ZERO_DIV (target_flags & MASK_CHECK_ZERO_DIV) -#define TARGET_USE_DIV (target_flags & MASK_USE_DIV) -#define TARGET_IDENTIFY_REVISION (target_flags & MASK_IDENTIFY_REVISION) -#define TARGET_WARN_PASS_STRUCT (target_flags & MASK_WARN_PASS_STRUCT) -#define TARGET_OPTIMIZE_ARG_AREA (target_flags & MASK_OPTIMIZE_ARG_AREA) -#define TARGET_SERIALIZE_VOLATILE (!(target_flags & MASK_NO_SERIALIZE_VOLATILE)) - -#define TARGET_EITHER_LARGE_SHIFT (target_flags & MASK_EITHER_LARGE_SHIFT) -#define TARGET_OMIT_LEAF_FRAME_POINTER (target_flags & MASK_OMIT_LEAF_FRAME_POINTER) - -/* Redefined in sysv3.h, sysv4.h, and dgux.h. */ -#define TARGET_DEFAULT (MASK_CHECK_ZERO_DIV) -#define CPU_DEFAULT MASK_88100 - -#define TARGET_SWITCHES \ - { \ - { "88110", MASK_88110 }, \ - { "88100", MASK_88100 }, \ - { "88000", MASK_88000 }, \ - { "ocs-debug-info", MASK_OCS_DEBUG_INFO }, \ - { "no-ocs-debug-info", -MASK_OCS_DEBUG_INFO }, \ - { "ocs-frame-position", MASK_OCS_FRAME_POSITION }, \ - { "no-ocs-frame-position", -MASK_OCS_FRAME_POSITION }, \ - { "svr4", MASK_SVR4 }, \ - { "svr3", -MASK_SVR4 }, \ - { "no-underscores", MASK_NO_UNDERSCORES }, \ - { "big-pic", MASK_BIG_PIC }, \ - { "trap-large-shift", MASK_TRAP_LARGE_SHIFT }, \ - { "handle-large-shift", MASK_HANDLE_LARGE_SHIFT }, \ - { "check-zero-division", MASK_CHECK_ZERO_DIV }, \ - { "no-check-zero-division", -MASK_CHECK_ZERO_DIV }, \ - { "use-div-instruction", MASK_USE_DIV }, \ - { "identify-revision", MASK_IDENTIFY_REVISION }, \ - { "warn-passed-structs", MASK_WARN_PASS_STRUCT }, \ - { "optimize-arg-area", MASK_OPTIMIZE_ARG_AREA }, \ - { "no-optimize-arg-area", -MASK_OPTIMIZE_ARG_AREA }, \ - { "no-serialize-volatile", MASK_NO_SERIALIZE_VOLATILE }, \ - { "serialize-volatile", -MASK_NO_SERIALIZE_VOLATILE }, \ - { "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER }, \ - { "no-omit-leaf-frame-pointer", -MASK_OMIT_LEAF_FRAME_POINTER }, \ - SUBTARGET_SWITCHES \ - /* Default switches */ \ - { "", TARGET_DEFAULT }, \ - } - -/* Redefined in dgux.h. */ -#define SUBTARGET_SWITCHES - -/* Macro to define table for command options with values. */ - -#define TARGET_OPTIONS { { "short-data-", &m88k_short_data }, \ - { "version-", &m88k_version } } - -/* Do any checking or such that is needed after processing the -m switches. */ - -#define OVERRIDE_OPTIONS \ - do { \ - register int i; \ - \ - if ((target_flags & MASK_88000) == 0) \ - target_flags |= CPU_DEFAULT; \ - \ - if (TARGET_88110) \ - { \ - target_flags |= MASK_USE_DIV; \ - target_flags &= ~MASK_CHECK_ZERO_DIV; \ - } \ - \ - m88k_cpu = (TARGET_88000 ? PROCESSOR_M88000 \ - : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88110)); \ - \ - if (TARGET_BIG_PIC) \ - flag_pic = 2; \ - \ - if ((target_flags & MASK_EITHER_LARGE_SHIFT) == MASK_EITHER_LARGE_SHIFT) \ - error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");\ - \ - if (TARGET_SVR4) \ - { \ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) \ - reg_names[i]--; \ - m88k_pound_sign = "#"; \ - } \ - else \ - { \ - target_flags |= MASK_SVR3; \ - target_flags &= ~MASK_SVR4; \ - } \ - \ - if (m88k_short_data) \ - { \ - char *p = m88k_short_data; \ - while (*p) \ - if (*p >= '0' && *p <= '9') \ - p++; \ - else \ - { \ - error ("Invalid option `-mshort-data-%s'", m88k_short_data); \ - break; \ - } \ - m88k_gp_threshold = atoi (m88k_short_data); \ - if (m88k_gp_threshold > 0x7fffffff) \ - error ("-mshort-data-%s is too large ", m88k_short_data); \ - if (flag_pic) \ - error ("-mshort-data-%s and PIC are incompatible", m88k_short_data); \ - } \ - if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */ \ - flag_omit_frame_pointer = 1; \ - } while (0) - -/*** Storage Layout ***/ - -/* Sizes in bits of the various types. */ -#define CHAR_TYPE_SIZE 8 -#define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE 32 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - Somewhat arbitrary. It matches the bit field patterns. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. - That is true on the m88000. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is the lowest - numbered. - For the m88000 we can decide arbitrarily since there are no machine - instructions for them. */ -#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 32 - -/* Largest alignment for stack parameters (if greater than PARM_BOUNDARY). */ -#define MAX_PARM_BOUNDARY 64 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 128 - -/* Allocation boundary (in *bits*) for the code of a function. On the - m88100, it is desirable to align to a cache line. However, SVR3 targets - only provided 8 byte alignment. The m88110 cache is small, so align - to an 8 byte boundary. Pack code tightly when compiling crtstuff.c. */ -#define FUNCTION_BOUNDARY (flag_inhibit_size_directive ? 32 : \ - (TARGET_88100 && TARGET_SVR4 ? 128 : 64)) - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 64 - -/* The best alignment to use in cases where we have a choice. */ -#define FASTEST_ALIGNMENT (TARGET_88100 ? 32 : 64) - -/* Make strings 4/8 byte aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - ((TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < FASTEST_ALIGNMENT) \ - ? FASTEST_ALIGNMENT : (ALIGN)) - -/* Make arrays of chars 4/8 byte aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN)) - -/* Alignment of field after `int : 0' in a structure. - Ignored with PCC_BITFIELD_TYPE_MATTERS. */ -/* #define EMPTY_FIELD_BOUNDARY 8 */ - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Maximum size (in bits) to use for the largest integral type that - replaces a BLKmode type. */ -/* #define MAX_FIXED_MODE_SIZE 0 */ - -/* Check a `double' value for validity for a particular machine mode. - This is defined to avoid crashes outputting certain constants. - Since we output the number in hex, the assembler won't choke on it. */ -/* #define CHECK_FLOAT_VALUE(MODE,VALUE) */ - -/* A code distinguishing the floating point format of the target machine. */ -/* #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT */ - -/*** 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. - - The m88100 has a General Register File (GRF) of 32 32-bit registers. - The m88110 adds an Extended Register File (XRF) of 32 80-bit registers. */ -#define FIRST_PSEUDO_REGISTER 64 -#define FIRST_EXTENDED_REGISTER 32 - -/* General notes on extended registers, their use and misuse. - - Possible good uses: - - spill area instead of memory. - -waste if only used once - - floating point calculations - -probably a waste unless we have run out of general purpose registers - - freeing up general purpose registers - -e.g. may be able to have more loop invariants if floating - point is moved into extended registers. - - - I've noticed wasteful moves into and out of extended registers; e.g. a load - into x21, then inside a loop a move into r24, then r24 used as input to - an fadd. Why not just load into r24 to begin with? Maybe the new cse.c - will address this. This wastes a move, but the load,store and move could - have been saved had extended registers been used throughout. - E.g. in the code following code, if z and xz are placed in extended - registers, there is no need to save preserve registers. - - long c=1,d=1,e=1,f=1,g=1,h=1,i=1,j=1,k; - - double z=0,xz=4.5; - - foo(a,b) - long a,b; - { - while (a < b) - { - k = b + c + d + e + f + g + h + a + i + j++; - z += xz; - a++; - } - printf("k= %d; z=%f;\n", k, z); - } - - I've found that it is possible to change the constraints (putting * before - the 'r' constraints int the fadd.ddd instruction) and get the entire - addition and store to go into extended registers. However, this also - forces simple addition and return of floating point arguments to a - function into extended registers. Not the correct solution. - - Found the following note in local-alloc.c which may explain why I can't - get both registers to be in extended registers since two are allocated in - local-alloc and one in global-alloc. Doesn't explain (I don't believe) - why an extended register is used instead of just using the preserve - register. - - from local-alloc.c: - We have provision to exempt registers, even when they are contained - within the block, that can be tied to others that are not contained in it. - This is so that global_alloc could process them both and tie them then. - But this is currently disabled since tying in global_alloc is not - yet implemented. - - The explanation of why the preserved register is not used is as follows, - I believe. The registers are being allocated in order. Tying is not - done so efficiently, so when it comes time to do the first allocation, - there are no registers left to use without spilling except extended - registers. Then when the next pseudo register needs a hard reg, there - are still no registers to be had for free, but this one must be a GRF - reg instead of an extended reg, so a preserve register is spilled. Thus - the move from extended to GRF is necessitated. I do not believe this can - be 'fixed' through the files in config/m88k. - - gcc seems to sometimes make worse use of register allocation -- not counting - moves -- whenever extended registers are present. For example in the - whetstone, the simple for loop (slightly modified) - for(i = 1; i <= n1; i++) - { - x1 = (x1 + x2 + x3 - x4) * t; - x2 = (x1 + x2 - x3 + x4) * t; - x3 = (x1 - x2 + x3 + x4) * t; - x4 = (x1 + x2 + x3 + x4) * t; - } - in general loads the high bits of the addresses of x2-x4 and i into registers - outside the loop. Whenever extended registers are used, it loads all of - these inside the loop. My conjecture is that since the 88110 has so many - registers, and gcc makes no distinction at this point -- just that they are - not fixed, that in loop.c it believes it can expect a number of registers - to be available. Then it allocates 'too many' in local-alloc which causes - problems later. 'Too many' are allocated because a large portion of the - registers are extended registers and cannot be used for certain purposes - ( e.g. hold the address of a variable). When this loop is compiled on its - own, the problem does not occur. I don't know the solution yet, though it - is probably in the base sources. Possibly a different way to calculate - "threshold". */ - -/* 1 for registers that have pervasive standard uses and are not available - for the register allocator. Registers r14-r25 and x22-x29 are expected - to be preserved across function calls. - - On the 88000, the standard uses of the General Register File (GRF) are: - Reg 0 = Pseudo argument pointer (hardware fixed to 0). - Reg 1 = Subroutine return pointer (hardware). - Reg 2-9 = Parameter registers (OCS). - Reg 10 = OCS reserved temporary. - Reg 11 = Static link if needed [OCS reserved temporary]. - Reg 12 = Address of structure return (OCS). - Reg 13 = OCS reserved temporary. - Reg 14-25 = Preserved register set. - Reg 26-29 = Reserved by OCS and ABI. - Reg 30 = Frame pointer (Common use). - Reg 31 = Stack pointer. - - The following follows the current 88open UCS specification for the - Extended Register File (XRF): - Reg 32 = x0 Always equal to zero - Reg 33-53 = x1-x21 Temporary registers (Caller Save) - Reg 54-61 = x22-x29 Preserver registers (Callee Save) - Reg 62-63 = x30-x31 Reserved for future ABI use. - - Note: The current 88110 extended register mapping is subject to change. - The bias towards caller-save registers is based on the - presumption that memory traffic can potentially be reduced by - allowing the "caller" to save only that part of the register - which is actually being used. (i.e. don't do a st.x if a st.d - is sufficient). Also, in scientific code (a.k.a. Fortran), the - large number of variables defined in common blocks may require - that almost all registers be saved across calls anyway. */ - -#define FIXED_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, 1, 1, 1, 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, 0, 1, 1} - -/* 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1} - -/* Macro to conditionally modify fixed_regs/call_used_regs. */ -#define CONDITIONAL_REGISTER_USAGE \ - { \ - if (! TARGET_88110) \ - { \ - register int i; \ - for (i = FIRST_EXTENDED_REGISTER; i < FIRST_PSEUDO_REGISTER; i++) \ - { \ - fixed_regs[i] = 1; \ - call_used_regs[i] = 1; \ - } \ - } \ - if (flag_pic) \ - { \ - /* Current hack to deal with -fpic -O2 problems. */ \ - fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ - call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ - global_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ - } \ - } - -/* These interfaces that don't apply to the m88000. */ -/* OVERLAPPING_REGNO_P(REGNO) 0 */ -/* INSN_CLOBBERS_REGNO_P(INSN, REGNO) 0 */ - -/* True if register is an extended register. */ -#define XRF_REGNO_P(N) ((N) < FIRST_PSEUDO_REGISTER && (N) >= FIRST_EXTENDED_REGISTER) - -/* 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 m88000, GRF registers hold 32-bits and XRF registers hold 80-bits. - An XRF register can hold any mode, but two GRF registers are required - for larger modes. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (XRF_REGNO_P (REGNO) \ - ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - - For double integers, we never put the value into an odd register so that - the operators don't run into the situation where the high part of one of - the inputs is the low part of the result register. (It's ok if the output - registers are the same as the input registers.) The XRF registers can - hold all modes, but only DF and SF modes can be manipulated in these - registers. The compiler should be allowed to use these as a fast spill - area. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - (XRF_REGNO_P(REGNO) \ - ? (TARGET_88110 && GET_MODE_CLASS (MODE) == MODE_FLOAT) \ - : (((MODE) != DImode && (MODE) != DFmode && (MODE) != DCmode) \ - || ((REGNO) & 1) == 0)) - -/* 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) \ - (((MODE1) == DFmode || (MODE1) == DCmode || (MODE1) == DImode \ - || (TARGET_88110 && GET_MODE_CLASS (MODE1) == MODE_FLOAT)) \ - == ((MODE2) == DFmode || (MODE2) == DCmode || (MODE2) == DImode \ - || (TARGET_88110 && GET_MODE_CLASS (MODE2) == MODE_FLOAT))) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* the m88000 pc isn't overloaded on a register that the compiler knows about. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 31 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 30 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 0 - -/* Register used in cases where a temporary is known to be safe to use. */ -#define TEMP_REGNUM 10 - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 11 - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM 12 - -/* Register to hold the addressing base for position independent - code access to data items. */ -#define PIC_OFFSET_TABLE_REGNUM 25 - -/* Order in which registers are preferred (most to least). Use temp - registers, then param registers top down. Preserve registers are - top down to maximize use of double memory ops for register save. - The 88open reserved registers (r26-r29 and x30-x31) may commonly be used - in most environments with the -fcall-used- or -fcall-saved- options. */ -#define REG_ALLOC_ORDER \ - { \ - 13, 12, 11, 10, 29, 28, 27, 26, \ - 62, 63, 9, 8, 7, 6, 5, 4, \ - 3, 2, 1, 53, 52, 51, 50, 49, \ - 48, 47, 46, 45, 44, 43, 42, 41, \ - 40, 39, 38, 37, 36, 35, 34, 33, \ - 25, 24, 23, 22, 21, 20, 19, 18, \ - 17, 16, 15, 14, 61, 60, 59, 58, \ - 57, 56, 55, 54, 30, 31, 0, 32} - -/* Order for leaf functions. */ -#define REG_LEAF_ALLOC_ORDER \ - { \ - 9, 8, 7, 6, 13, 12, 11, 10, \ - 29, 28, 27, 26, 62, 63, 5, 4, \ - 3, 2, 0, 53, 52, 51, 50, 49, \ - 48, 47, 46, 45, 44, 43, 42, 41, \ - 40, 39, 38, 37, 36, 35, 34, 33, \ - 25, 24, 23, 22, 21, 20, 19, 18, \ - 17, 16, 15, 14, 61, 60, 59, 58, \ - 57, 56, 55, 54, 30, 31, 1, 32} - -/* Switch between the leaf and non-leaf orderings. The purpose is to avoid - write-over scoreboard delays between caller and callee. */ -#define ORDER_REGS_FOR_LOCAL_ALLOC \ -{ \ - static int leaf[] = REG_LEAF_ALLOC_ORDER; \ - static int nonleaf[] = REG_ALLOC_ORDER; \ - \ - bcopy (regs_ever_live[1] ? nonleaf : leaf, reg_alloc_order, \ - FIRST_PSEUDO_REGISTER * sizeof (int)); \ -} - -/*** Register Classes ***/ - -/* 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 m88000 hardware has two kinds of registers. In addition, we denote - the arg pointer as a separate class. */ - -enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS, - XGRF_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", "AP_REG", "XRF_REGS", "GENERAL_REGS", \ - "AGRF_REGS", "XGRF_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, 0x00000000}, \ - {0x00000001, 0x00000000}, \ - {0x00000000, 0xffffffff}, \ - {0xfffffffe, 0x00000000}, \ - {0xffffffff, 0x00000000}, \ - {0xfffffffe, 0xffffffff}, \ - {0xffffffff, 0xffffffff}} - -/* 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) ? ((REGNO < 32) ? GENERAL_REGS : XRF_REGS) : AP_REG) - -/* The class value for index registers, and the one for base regs. */ -#define BASE_REG_CLASS AGRF_REGS -#define INDEX_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. - For the 88000, the following class/letter is defined for the XRF: - x - Extended register file */ -#define REG_CLASS_FROM_LETTER(C) \ - (((C) == 'x') ? XRF_REGS : NO_REGS) - -/* 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_BASE_P(REGNO) \ - ((REGNO) < FIRST_EXTENDED_REGISTER \ - || (unsigned) reg_renumber[REGNO] < FIRST_EXTENDED_REGISTER) -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - (((REGNO) && (REGNO) < FIRST_EXTENDED_REGISTER) \ - || (unsigned) reg_renumber[REGNO] < FIRST_EXTENDED_REGISTER) - -/* 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. - Double constants should be in a register iff they can be made cheaply. */ -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - (CONSTANT_P(X) && (CLASS == XRF_REGS) ? NO_REGS : (CLASS)) - -/* Return the register class of a scratch register needed to load IN - into a register of class CLASS in MODE. On the m88k, when PIC, we - need a temporary when loading some addresses into a register. */ -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ - ((flag_pic \ - && GET_CODE (IN) == CONST \ - && GET_CODE (XEXP (IN, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (IN, 0), 0)) == CONST_INT \ - && ! SMALL_INT (XEXP (XEXP (IN, 0), 1))) ? GENERAL_REGS : NO_REGS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((((CLASS) == XRF_REGS) ? 1 \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) - -/* Letters in the range `I' through `P' in a register constraint string can - be used to stand for particular ranges of immediate operands. The C - expression is true iff C is a known letter and VALUE is appropriate for - that letter. - - For the m88000, the following constants are used: - `I' requires a non-negative 16-bit value. - `J' requires a non-positive 16-bit value. - `K' requires a non-negative value < 32. - `L' requires a constant with only the upper 16-bits set. - `M' requires constant values that can be formed with `set'. - `N' requires a negative value. - `O' requires zero. - `P' requires a non-negative value. */ - -/* Quick tests for certain values. */ -#define SMALL_INT(X) (SMALL_INTVAL (INTVAL (X))) -#define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000) -#define ADD_INT(X) (ADD_INTVAL (INTVAL (X))) -#define ADD_INTVAL(I) ((unsigned) (I) + 0xffff < 0x1ffff) -#define POWER_OF_2(I) ((I) && POWER_OF_2_or_0(I)) -#define POWER_OF_2_or_0(I) (((I) & ((unsigned)(I) - 1)) == 0) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? SMALL_INTVAL (VALUE) \ - : (C) == 'J' ? SMALL_INTVAL (-(VALUE)) \ - : (C) == 'K' ? (unsigned)(VALUE) < 32 \ - : (C) == 'L' ? ((VALUE) & 0xffff) == 0 \ - : (C) == 'M' ? integer_ok_for_set (VALUE) \ - : (C) == 'N' ? (VALUE) < 0 \ - : (C) == 'O' ? (VALUE) == 0 \ - : (C) == 'P' ? (VALUE) >= 0 \ - : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. For the m88000, the - constraints are: `G' requires zero, and `H' requires one or two. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? (CONST_DOUBLE_HIGH (VALUE) == 0 \ - && CONST_DOUBLE_LOW (VALUE) == 0) \ - : 0) - -/* Letters in the range `Q' through `U' in a register constraint string - may be defined in a machine-dependent fashion to stand for arbitrary - operand types. - - For the m88k, `Q' handles addresses in a call context. */ - -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? symbolic_address_p (OP) : 0) - -/*** Describing Stack Layout ***/ - -/* Define this if pushing a word on the stack moves the stack pointer - to a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the addresses of local variable slots are at negative - offsets from the frame pointer. */ -/* #define FRAME_GROWS_DOWNWARD */ - -/* Offset from the frame pointer to the first local variable slot to be - allocated. For the m88k, the debugger wants the return address (r1) - stored at location r30+4, and the previous frame pointer stored at - location r30. */ -#define STARTING_FRAME_OFFSET 8 - -/* If we generate an insn to push BYTES bytes, this says how many the - stack pointer really advances by. The m88k has no push instruction. */ -/* #define PUSH_ROUNDING(BYTES) */ - -/* If defined, the maximum amount of space required for outgoing arguments - will be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed - onto the stack for each call; instead, the function prologue should - increase the stack frame size by this amount. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Offset from the stack pointer register to the first location at which - outgoing arguments are placed. Use the default value zero. */ -/* #define STACK_POINTER_OFFSET 0 */ - -/* Offset of first parameter from the argument pointer register value. - Using an argument pointer, this is 0 for the m88k. GCC knows - how to eliminate the argument pointer references if necessary. */ -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* Define this if functions should assume that stack space has been - allocated for arguments even when their values are passed in - registers. - - The value of this macro is the size, in bytes, of the area reserved for - arguments passed in registers. - - This space can either be allocated by the caller or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' - says which. */ -#define REG_PARM_STACK_SPACE(FNDECL) 32 - -/* Define this macro if REG_PARM_STACK_SPACE is defined but stack - parameters don't skip the area specified by REG_PARM_STACK_SPACE. - Normally, when a parameter is not passed in registers, it is placed on - the stack beyond the REG_PARM_STACK_SPACE area. Defining this macro - suppresses this behavior and causes the parameter to be passed on the - stack in its natural location. */ -#define STACK_PARMS_IN_REG_PARM_AREA - -/* Define this if it is the responsibility of the caller to allocate the - area reserved for arguments passed in registers. If - `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect of this - macro is to determine whether the space is included in - `current_function_outgoing_args_size'. */ -/* #define OUTGOING_REG_PARM_STACK_SPACE */ - -/* Offset from the stack pointer register to an item dynamically allocated - on the stack, e.g., by `alloca'. - - The default value for this macro is `STACK_POINTER_OFFSET' plus the - length of the outgoing arguments. The default is correct for most - machines. See `function.c' for details. */ -/* #define STACK_DYNAMIC_OFFSET(FUNDECL) ... */ - -/* Value is the number of bytes 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. */ -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,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. */ -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, \ - TYPE_MODE (VALTYPE) == BLKmode ? SImode : TYPE_MODE (VALTYPE), \ - 2) - -/* Define this if it differs from FUNCTION_VALUE. */ -/* #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) ... */ - -/* Disable the promotion of some structures and unions to registers. */ -#define RETURN_IN_MEMORY(TYPE) \ - (TYPE_MODE (TYPE) == BLKmode \ - || ((TREE_CODE (TYPE) == RECORD_TYPE || TREE_CODE(TYPE) == UNION_TYPE) \ - && !(TYPE_MODE (TYPE) == SImode \ - || (TYPE_MODE (TYPE) == BLKmode \ - && TYPE_ALIGN (TYPE) == BITS_PER_WORD \ - && int_size_in_bytes (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 - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 2) - -/* True if N is a possible register number for a function value - as seen by the caller. */ -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2) - -/* Determine whether a function argument is passed in a register, and - which register. See m88k.c. */ -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - m88k_function_arg (CUM, MODE, TYPE, NAMED) - -/* Define this if it differs from FUNCTION_ARG. */ -/* #define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) ... */ - -/* A C expression for the number of words, at the beginning of an - argument, must be put in registers. The value must be zero for - arguments that are passed entirely in registers or that are entirely - pushed on the stack. */ -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0) - -/* A C expression that indicates when an argument must be passed by - reference. If nonzero for an argument, a copy of that argument is - made in memory and a pointer to the argument is passed instead of the - argument itself. The pointer is passed in whatever way is appropriate - for passing a pointer to that type. */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) (0) - -/* A C type for declaring a variable that is used as the first argument - of `FUNCTION_ARG' and other related values. It suffices to count - the number of words of argument 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. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0) - -/* A C statement (sans semicolon) to update the summarizer variable - CUM to advance past an argument in the argument list. The values - MODE, TYPE and NAMED describe that argument. Once this is done, - the variable CUM is suitable for analyzing the *following* argument - with `FUNCTION_ARG', etc. (TYPE is null for libcalls where that - information may not be available.) */ -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - do { \ - enum machine_mode __mode = (TYPE) ? TYPE_MODE (TYPE) : (MODE); \ - if ((CUM & 1) \ - && (__mode == DImode || __mode == DFmode \ - || ((TYPE) && TYPE_ALIGN (TYPE) > BITS_PER_WORD))) \ - CUM++; \ - CUM += (((__mode != BLKmode) \ - ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE)) \ - + 3) / 4; \ - } while (0) - -/* True if N is a possible register number for function argument passing. - On the m88000, these are registers 2 through 9. */ -#define FUNCTION_ARG_REGNO_P(N) ((N) <= 9 && (N) >= 2) - -/* A C expression which determines whether, and in which direction, - to pad out an argument with extra space. The value should be of - type `enum direction': either `upward' to pad above the argument, - `downward' to pad below, or `none' to inhibit padding. - - This macro does not control the *amount* of padding; that is always - just enough to reach the next multiple of `FUNCTION_ARG_BOUNDARY'. */ -#define FUNCTION_ARG_PADDING(MODE, TYPE) \ - ((MODE) == BLKmode \ - || ((TYPE) && (TREE_CODE (TYPE) == RECORD_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE)) \ - ? upward : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY ? downward : none) - -/* If defined, a C expression that gives the alignment boundary, in bits, - of an argument with the specified mode and type. If it is not defined, - `PARM_BOUNDARY' is used for all arguments. */ -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ - ? PARM_BOUNDARY : 2 * PARM_BOUNDARY) - -/* Generate necessary RTL for __builtin_saveregs(). - ARGLIST is the argument list; see expr.c. */ -#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) m88k_builtin_saveregs (ARGLIST) - -/* Generate the assembly code for function entry. */ -#define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE) - -/* Perform special actions at the point where the prologue ends. */ -#define FUNCTION_END_PROLOGUE(FILE) m88k_end_prologue(FILE) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. Redefined in sysv3.h, sysv4.h and - dgux.h. */ -#define FUNCTION_PROFILER(FILE, LABELNO) \ - output_function_profiler (FILE, LABELNO, "mcount", 1) - -/* Maximum length in instructions of the code output by FUNCTION_PROFILER. */ -#define FUNCTION_PROFILER_LENGTH (5+3+1+5) - -/* Output assembler code to FILE to initialize basic-block profiling for - the current module. LABELNO is unique to each instance. */ -#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ - output_function_block_profiler (FILE, LABELNO) - -/* Maximum length in instructions of the code output by - FUNCTION_BLOCK_PROFILER. */ -#define FUNCTION_BLOCK_PROFILER_LENGTH (3+5+2+5) - -/* Output assembler code to FILE to increment the count associated with - the basic block number BLOCKNO. */ -#define BLOCK_PROFILER(FILE, BLOCKNO) output_block_profiler (FILE, BLOCKNO) - -/* Maximum length in instructions of the code output by BLOCK_PROFILER. */ -#define BLOCK_PROFILER_LENGTH 4 - -/* 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) m88k_end_epilogue(FILE, SIZE) - -/* Perform special actions at the point where the epilogue begins. */ -#define FUNCTION_BEGIN_EPILOGUE(FILE) m88k_begin_epilogue(FILE) - -/* 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 \ -(current_function_varargs \ - || (TARGET_OMIT_LEAF_FRAME_POINTER && !leaf_function_p ()) \ - || (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)) - -/* Definitions for register eliminations. - - We have two registers that can be eliminated on the m88k. First, the - frame pointer register can often be eliminated in favor of the stack - pointer register. Secondly, the argument pointer register can always be - eliminated; it is replaced with either the stack or frame pointer. */ - -/* This is an array of structures. Each structure initializes one pair - of eliminable registers. The "from" register number is given first, - followed by "to". Eliminations of the same "from" register are listed - in order of preference. */ -#define ELIMINABLE_REGS \ -{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - -/* Given FROM and TO register numbers, say whether this elimination - is allowed. */ -#define CAN_ELIMINATE(FROM, TO) \ - (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)) - -/* Define the offset between two registers, one to be eliminated, and the other - its replacement, at the start of a routine. */ -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ m88k_layout_frame (); \ - if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = m88k_fp_offset; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ - (OFFSET) = m88k_stack_size - m88k_fp_offset; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = m88k_stack_size; \ - else \ - abort (); \ -} - -/*** Trampolines for Nested Functions ***/ - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - This block is placed on the stack and filled in. It is aligned - 0 mod 128 and those portions that are executed are constant. - This should work for instruction caches that have cache lines up - to the aligned amount (128 is arbitrary), provided no other code - producer is attempting to play the same game. This of course is - in violation of any number of 88open standards. */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - char buf[256]; \ - static int labelno = 0; \ - labelno++; \ - ASM_GENERATE_INTERNAL_LABEL (buf, "LTRMP", labelno); \ - /* Save the return address (r1) in the static chain reg (r11). */ \ - fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[11], reg_names[1]); \ - /* Locate this block; transfer to the next instruction. */ \ - fprintf (FILE, "\tbsr\t %s\n", &buf[1]); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "LTRMP", labelno); \ - /* Save r10; use it as the relative pointer; restore r1. */ \ - fprintf (FILE, "\tst\t %s,%s,24\n", reg_names[10], reg_names[1]); \ - fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[10], reg_names[1]); \ - fprintf (FILE, "\tor\t %s,%s,0\n", reg_names[1], reg_names[11]); \ - /* Load the function's address and go there. */ \ - fprintf (FILE, "\tld\t %s,%s,32\n", reg_names[11], reg_names[10]); \ - fprintf (FILE, "\tjmp.n\t %s\n", reg_names[11]); \ - /* Restore r10 and load the static chain register. */ \ - fprintf (FILE, "\tld.d\t %s,%s,24\n", reg_names[10], reg_names[10]); \ - /* Storage: r10 save area, static chain, function address. */ \ - ASM_OUTPUT_INT (FILE, const0_rtx); \ - ASM_OUTPUT_INT (FILE, const0_rtx); \ - ASM_OUTPUT_INT (FILE, const0_rtx); \ -} - -/* Length in units of the trampoline for entering a nested function. - This is really two components. The first 32 bytes are fixed and - must be copied; the last 12 bytes are just storage that's filled - in later. So for allocation purposes, it's 32+12 bytes, but for - initialization purposes, it's 32 bytes. */ - -#define TRAMPOLINE_SIZE (32+12) - -/* Alignment required for a trampoline. 128 is used to find the - beginning of a line in the instruction cache and to allow for - instruction cache lines of up to 128 bytes. */ - -#define TRAMPOLINE_ALIGNMENT 128 - -/* 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. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 40)), FNADDR); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 36)), CXT); \ -} - -/*** Library Subroutine Names ***/ - -/* Define this macro if GNU CC should generate calls to the System V - (and ANSI C) library functions `memcpy' and `memset' rather than - the BSD functions `bcopy' and `bzero'. */ -#define TARGET_MEM_FUNCTIONS - -/*** Addressing Modes ***/ - -#define EXTRA_CC_MODES CCEVENmode - -#define EXTRA_CC_NAMES "CCEVEN" - -#define SELECT_CC_MODE(OP,X,Y) CCmode - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Recognize any constant value that is a valid address. - When PIC, we do not accept an address that would require a scratch reg - to load into a register. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \ - || (GET_CODE (X) == CONST \ - && ! (flag_pic && pic_address_needs_scratch (X)))) - - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 2 - -/* The condition for memory shift insns. */ -#define SCALED_ADDRESS_P(ADDR) \ - (GET_CODE (ADDR) == PLUS \ - && (GET_CODE (XEXP (ADDR, 0)) == MULT \ - || GET_CODE (XEXP (ADDR, 1)) == MULT)) - -/* Can the reference to X be made short? */ -#define SHORT_ADDRESS_P(X,TEMP) \ - ((TEMP) = (GET_CODE (X) == CONST ? get_related_value (X) : X), \ - ((TEMP) && GET_CODE (TEMP) == SYMBOL_REF && SYMBOL_REF_FLAG (TEMP))) - -/* 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. - - On the m88000, a legitimate address has the form REG, REG+REG, - REG+SMALLINT, REG+(REG*modesize) (REG[REG]), or SMALLINT. - - The register elimination process should deal with the argument - pointer and frame pointer changing to REG+SMALLINT. */ - -#define LEGITIMATE_INDEX_P(X, MODE) \ - ((GET_CODE (X) == CONST_INT \ - && SMALL_INT (X)) \ - || (REG_P (X) \ - && REG_OK_FOR_INDEX_P (X)) \ - || (GET_CODE (X) == MULT \ - && REG_P (XEXP (X, 0)) \ - && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) == GET_MODE_SIZE (MODE))) - -#define RTX_OK_FOR_BASE_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 RTX_OK_FOR_INDEX_P(X) \ - ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && REG_OK_FOR_INDEX_P (SUBREG_REG (X)))) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - register rtx _x; \ - if (REG_P (X)) \ - { \ - if (REG_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - } \ - else if (GET_CODE (X) == PLUS) \ - { \ - register rtx _x0 = XEXP (X, 0); \ - register rtx _x1 = XEXP (X, 1); \ - if ((flag_pic \ - && _x0 == pic_offset_table_rtx \ - && (flag_pic == 2 \ - ? RTX_OK_FOR_BASE_P (_x1) \ - : (GET_CODE (_x1) == SYMBOL_REF \ - || GET_CODE (_x1) == LABEL_REF))) \ - || (REG_P (_x0) \ - && (REG_OK_FOR_BASE_P (_x0) \ - && LEGITIMATE_INDEX_P (_x1, MODE))) \ - || (REG_P (_x1) \ - && (REG_OK_FOR_BASE_P (_x1) \ - && LEGITIMATE_INDEX_P (_x0, MODE)))) \ - goto ADDR; \ - } \ - else if (GET_CODE (X) == LO_SUM) \ - { \ - register rtx _x0 = XEXP (X, 0); \ - register rtx _x1 = XEXP (X, 1); \ - if (((REG_P (_x0) \ - && REG_OK_FOR_BASE_P (_x0)) \ - || (GET_CODE (_x0) == SUBREG \ - && REG_P (SUBREG_REG (_x0)) \ - && REG_OK_FOR_BASE_P (SUBREG_REG (_x0)))) \ - && CONSTANT_P (_x1)) \ - goto ADDR; \ - } \ - else if (GET_CODE (X) == CONST_INT \ - && SMALL_INT (X)) \ - goto ADDR; \ - else if (SHORT_ADDRESS_P (X, _x)) \ - goto ADDR; \ -} - -/* 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. Not the argument pointer. */ -#define REG_OK_FOR_INDEX_P(X) \ - (!XRF_REGNO_P(REGNO (X))) -/* 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) (REG_OK_FOR_INDEX_P (X)) - -#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 - -/* 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. */ - -/* On the m88000, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ \ - if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ - copy_to_mode_reg (SImode, XEXP (X, 1))); \ - if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ - (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \ - copy_to_mode_reg (SImode, XEXP (X, 0))); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ - (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \ - force_operand (XEXP (X, 0), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ - (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \ - (X) = gen_rtx (PLUS, Pmode, force_operand (XEXP (X, 0), NULL_RTX),\ - XEXP (X, 1)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \ - (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), NULL_RTX)); \ - if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \ - || GET_CODE (X) == LABEL_REF) \ - (X) = legitimize_address (flag_pic, X, 0, 0); \ - if (memory_address_p (MODE, X)) \ - 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 m88000 this is never true. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - -/* 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) - -/* Define this, so that when PIC, reload won't try to reload invalid - addresses which require two reload registers. */ - -#define LEGITIMATE_PIC_OPERAND_P(X) (! pic_address_needs_scratch (X)) - - -/*** Condition Code Information ***/ - -/* C code for a data type which is used for declaring the `mdep' - component of `cc_status'. It defaults to `int'. */ -/* #define CC_STATUS_MDEP int */ - -/* A C expression to initialize the `mdep' field to "empty". */ -/* #define CC_STATUS_MDEP_INIT (cc_status.mdep = 0) */ - -/* Macro to zap the normal portions of CC_STATUS, but leave the - machine dependent parts (ie, literal synthesis) alone. */ -/* #define CC_STATUS_INIT_NO_MDEP \ - (cc_status.flags = 0, cc_status.value1 = 0, cc_status.value2 = 0) */ - -/* When using a register to hold the condition codes, the cc_status - mechanism cannot be used. */ -#define NOTICE_UPDATE_CC(EXP, INSN) (0) - -/*** Miscellaneous Parameters ***/ - -/* Define the codes that are matched by predicates in m88k.c. */ -#define PREDICATE_CODES \ - {"move_operand", {SUBREG, REG, CONST_INT, LO_SUM, MEM}}, \ - {"call_address_operand", {SUBREG, REG, SYMBOL_REF, LABEL_REF, CONST}}, \ - {"arith_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith5_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith32_operand", {SUBREG, REG, CONST_INT}}, \ - {"arith64_operand", {SUBREG, REG, CONST_INT}}, \ - {"int5_operand", {CONST_INT}}, \ - {"int32_operand", {CONST_INT}}, \ - {"add_operand", {SUBREG, REG, CONST_INT}}, \ - {"reg_or_bbx_mask_operand", {SUBREG, REG, CONST_INT}}, \ - {"real_or_0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ - {"relop", {EQ, NE, LT, LE, GE, GT, LTU, LEU, GEU, GTU}}, \ - {"even_relop", {EQ, LT, GT, LTU, GTU}}, \ - {"odd_relop", { NE, LE, GE, LEU, GEU}}, \ - {"partial_ccmode_register_operand", { SUBREG, REG}}, \ - {"relop_no_unsigned", {EQ, NE, LT, LE, GE, GT}}, \ - {"equality_op", {EQ, NE}}, \ - {"pc_or_label_ref", {PC, LABEL_REF}}, - -/* The case table contains either words or branch instructions. This says - which. We always claim that the vector is PC-relative. It is position - independent when -fpic is used. */ -#define CASE_VECTOR_INSNS (TARGET_88100 || flag_pic) - -/* An alias for a machine mode name. This is the machine mode that - elements of a jump-table should have. */ -#define CASE_VECTOR_MODE SImode - -/* 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 - -/* Define this if control falls through a `case' insn when the index - value is out of range. This means the specified default-label is - actually ignored by the `case' insn proper. */ -/* #define CASE_DROPS_THROUGH */ - -/* Define this to be the smallest number of different values for which it - is best to use a jump-table instead of a tree of conditional branches. - The default is 4 for machines with a casesi instruction and 5 otherwise. - The best 88110 number is around 7, though the exact number isn't yet - known. A third alternative for the 88110 is to use a binary tree of - bb1 instructions on bits 2/1/0 if the range is dense. This may not - win very much though. */ -#define CASE_VALUES_THRESHOLD (TARGET_88100 ? 4 : 7) - -/* 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 - -/* The 88open ABI says size_t is unsigned int. */ -#define SIZE_TYPE "unsigned int" - -/* Allow and ignore #sccs directives */ -#define SCCS_DIRECTIVE - -/* Handle #pragma pack and sometimes #pragma weak. */ -#define HANDLE_SYSV_PRAGMA - -/* Tell when to handle #pragma weak. This is only done for V.4. */ -#define SUPPORTS_WEAK TARGET_SVR4 -#define SUPPORTS_ONE_ONLY TARGET_SVR4 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 8 - -/* Define if normal loads of shorter-than-word items from memory clears - the rest of the bigs in the register. */ -#define BYTE_LOADS_ZERO_EXTEND - -/* Zero if access to memory by bytes is faster. */ -#define SLOW_BYTE_ACCESS 1 - -/* 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 - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. */ -#define NO_FUNCTION_CSE - -/* Define this macro if an argument declared as `char' or - `short' in a prototype should actually be passed as an - `int'. In addition to avoiding errors in certain cases of - mismatch, it also makes for better code on certain machines. */ -#define PROMOTE_PROTOTYPES - -/* Define this macro if a float function always returns float - (even in traditional mode). Redefined in luna.h. */ -#define TRADITIONAL_RETURN_FLOAT - -/* 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 - -/* 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 word address (for indexing purposes) - so give the MEM rtx word mode. */ -#define FUNCTION_MODE SImode - -/* A barrier will be aligned so account for the possible expansion. - A volatile load may be preceded by a serializing instruction. - Account for profiling code output at NOTE_INSN_PROLOGUE_END. - Account for block profiling code at basic block boundaries. */ -#define ADJUST_INSN_LENGTH(RTX, LENGTH) \ - if (GET_CODE (RTX) == BARRIER \ - || (TARGET_SERIALIZE_VOLATILE \ - && GET_CODE (RTX) == INSN \ - && GET_CODE (PATTERN (RTX)) == SET \ - && ((GET_CODE (SET_SRC (PATTERN (RTX))) == MEM \ - && MEM_VOLATILE_P (SET_SRC (PATTERN (RTX))))))) \ - LENGTH += 1; \ - else if (GET_CODE (RTX) == NOTE \ - && NOTE_LINE_NUMBER (RTX) == NOTE_INSN_PROLOGUE_END) \ - { \ - if (profile_block_flag) \ - LENGTH += FUNCTION_BLOCK_PROFILER_LENGTH; \ - if (profile_flag) \ - LENGTH += (FUNCTION_PROFILER_LENGTH + REG_PUSH_LENGTH \ - + REG_POP_LENGTH); \ - } \ - else if (profile_block_flag \ - && (GET_CODE (RTX) == CODE_LABEL \ - || GET_CODE (RTX) == JUMP_INSN \ - || (GET_CODE (RTX) == INSN \ - && GET_CODE (PATTERN (RTX)) == SEQUENCE \ - && GET_CODE (XVECEXP (PATTERN (RTX), 0, 0)) == JUMP_INSN)))\ - LENGTH += BLOCK_PROFILER_LENGTH; - -/* Track the state of the last volatile memory reference. Clear the - state with CC_STATUS_INIT for now. */ -#define CC_STATUS_INIT m88k_volatile_code = '\0' - -/* 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. - - We assume that any 16 bit integer can easily be recreated, so we - indicate 0 cost, in an attempt to get GCC not to optimize things - like comparison against a constant. - - The cost of CONST_DOUBLE is zero (if it can be placed in an insn, it - is as good as a register; since it can't be placed in any insn, it - won't do anything in cse, but it will cause expand_binop to pass the - constant to the define_expands). */ -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (SMALL_INT (RTX)) \ - return 0; \ - else if (SMALL_INTVAL (- INTVAL (RTX))) \ - return 2; \ - else if (classify_integer (SImode, INTVAL (RTX)) != m88k_oru_or) \ - return 4; \ - return 7; \ - case HIGH: \ - return 2; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - if (flag_pic) \ - return (flag_pic == 2) ? 11 : 8; \ - return 5; \ - case CONST_DOUBLE: \ - return 0; - -/* Provide the costs of an addressing mode that contains ADDR. - If ADDR is not a valid address, its cost is irrelevant. - REG+REG is made slightly more expensive because it might keep - a register live for longer than we might like. */ -#define ADDRESS_COST(ADDR) \ - (GET_CODE (ADDR) == REG ? 1 : \ - GET_CODE (ADDR) == LO_SUM ? 1 : \ - GET_CODE (ADDR) == HIGH ? 2 : \ - GET_CODE (ADDR) == MULT ? 1 : \ - GET_CODE (ADDR) != PLUS ? 4 : \ - (REG_P (XEXP (ADDR, 0)) && REG_P (XEXP (ADDR, 1))) ? 2 : 1) - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MEM: \ - return COSTS_N_INSNS (2); \ - case MULT: \ - return COSTS_N_INSNS (3); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (38); - -/* A C expressions returning the cost of moving data of MODE from a register - to or from memory. This is more costly than between registers. */ -#define MEMORY_MOVE_COST(MODE,CLASS,IN) 4 - -/* Provide the cost of a branch. Exact meaning under development. */ -#define BRANCH_COST (TARGET_88100 ? 1 : 2) - -/* A C statement (sans semicolon) to update the integer variable COST - based on the relationship between INSN that is dependent on - DEP_INSN through the dependence LINK. The default is to make no - adjustment to COST. On the m88k, ignore the cost of anti- and - output-dependencies. On the m88100, a store can issue two cycles - before the value (not the address) has finished computing. */ -#define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ - do { \ - if (REG_NOTE_KIND (LINK) != 0) \ - (COST) = 0; /* Anti or output dependence. */ \ - else if (! TARGET_88100 \ - && recog_memoized (INSN) >= 0 \ - && get_attr_type (INSN) == TYPE_STORE \ - && SET_SRC (PATTERN (INSN)) == SET_DEST (PATTERN (DEP_INSN))) \ - (COST) -= 4; /* 88110 store reservation station. */ \ - } while (0) - -/* Do not break .stabs pseudos into continuations. */ -#define DBX_CONTIN_LENGTH 0 - -/*** Output of Assembler Code ***/ - -/* Control the assembler format that we output. */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will end at - the end of the line. */ -#define ASM_COMMENT_START ";" - -/* Allow pseudo-ops to be overridden. Override these in svr[34].h. */ -#undef INT_ASM_OP -#undef ASCII_DATA_ASM_OP -#undef CONST_SECTION_ASM_OP -#undef CTORS_SECTION_ASM_OP -#undef DTORS_SECTION_ASM_OP -#undef ASM_OUTPUT_SECTION_NAME -#undef INIT_SECTION_ASM_OP -#undef FINI_SECTION_ASM_OP -#undef TYPE_ASM_OP -#undef SIZE_ASM_OP -#undef SET_ASM_OP -#undef SKIP_ASM_OP -#undef COMMON_ASM_OP -#undef ALIGN_ASM_OP -#undef IDENT_ASM_OP - -/* These are used in varasm.c as well. */ -#define TEXT_SECTION_ASM_OP "text" -#define DATA_SECTION_ASM_OP "data" - -/* Other sections. */ -#define CONST_SECTION_ASM_OP (TARGET_SVR4 \ - ? "section\t .rodata,\"a\"" \ - : "section\t .rodata,\"x\"") -#define TDESC_SECTION_ASM_OP (TARGET_SVR4 \ - ? "section\t .tdesc,\"a\"" \ - : "section\t .tdesc,\"x\"") - -/* These must be constant strings for crtstuff.c. */ -#define CTORS_SECTION_ASM_OP "section\t .ctors,\"d\"" -#define DTORS_SECTION_ASM_OP "section\t .dtors,\"d\"" -#define INIT_SECTION_ASM_OP "section\t .init,\"x\"" -#define FINI_SECTION_ASM_OP "section\t .fini,\"x\"" - -/* These are pretty much common to all assemblers. */ -#define IDENT_ASM_OP "ident" -#define FILE_ASM_OP "file" -#define SECTION_ASM_OP "section" -#define SET_ASM_OP "def" -#define GLOBAL_ASM_OP "global" -#define ALIGN_ASM_OP "align" -#define SKIP_ASM_OP "zero" -#define COMMON_ASM_OP "comm" -#define BSS_ASM_OP "bss" -#define FLOAT_ASM_OP "float" -#define DOUBLE_ASM_OP "double" -#define INT_ASM_OP "word" -#define ASM_LONG INT_ASM_OP -#define SHORT_ASM_OP "half" -#define CHAR_ASM_OP "byte" -#define ASCII_DATA_ASM_OP "string" - -/* These are particular to the global pool optimization. */ -#define SBSS_ASM_OP "sbss" -#define SCOMM_ASM_OP "scomm" -#define SDATA_SECTION_ASM_OP "sdata" - -/* These are specific to PIC. */ -#define TYPE_ASM_OP "type" -#define SIZE_ASM_OP "size" -#ifndef AS_BUG_POUND_TYPE /* Faulty assemblers require @ rather than #. */ -#undef TYPE_OPERAND_FMT -#define TYPE_OPERAND_FMT "#%s" -#endif - -/* This is how we tell the assembler that a symbol is weak. */ - -#undef ASM_WEAKEN_LABEL -#define ASM_WEAKEN_LABEL(FILE,NAME) \ - do { fputs ("\tweak\t", FILE); assemble_name (FILE, NAME); \ - fputc ('\n', FILE); } while (0) - -/* These are specific to version 03.00 assembler syntax. */ -#define INTERNAL_ASM_OP "local" -#define VERSION_ASM_OP "version" -#define UNALIGNED_SHORT_ASM_OP "uahalf" -#define UNALIGNED_INT_ASM_OP "uaword" -#define PUSHSECTION_ASM_OP "section" -#define POPSECTION_ASM_OP "previous" - -/* These are specific to the version 04.00 assembler syntax. */ -#define REQUIRES_88110_ASM_OP "requires_88110" - -/* Output any initial stuff to the assembly file. Always put out - a file directive, even if not debugging. - - Immediately after putting out the file, put out a "sem.<value>" - declaration. This should be harmless on other systems, and - is used in DG/UX by the debuggers to supplement COFF. The - fields in the integer value are as follows: - - Bits Value Meaning - ---- ----- ------- - 0-1 0 No information about stack locations - 1 Auto/param locations are based on r30 - 2 Auto/param locations are based on CFA - - 3-2 0 No information on dimension order - 1 Array dims in sym table matches source language - 2 Array dims in sym table is in reverse order - - 5-4 0 No information about the case of global names - 1 Global names appear in the symbol table as in the source - 2 Global names have been converted to lower case - 3 Global names have been converted to upper case. */ - -#ifdef SDB_DEBUGGING_INFO -#define ASM_COFFSEM(FILE) \ - if (write_symbols == SDB_DEBUG) \ - { \ - fprintf (FILE, "\nsem.%x:\t\t; %s\n", \ - (((TARGET_OCS_FRAME_POSITION) ? 2 : 1) << 0) + (1 << 2) + (1 << 4),\ - (TARGET_OCS_FRAME_POSITION) \ - ? "frame is CFA, normal array dims, case unchanged" \ - : "frame is r30, normal array dims, case unchanged"); \ - } -#else -#define ASM_COFFSEM(FILE) -#endif - -/* Output the first line of the assembly file. Redefined in dgux.h. */ - -#define ASM_FIRST_LINE(FILE) \ - do { \ - if (TARGET_SVR4) \ - { \ - if (TARGET_88110) \ - fprintf (FILE, "\t%s\t \"%s\"\n", VERSION_ASM_OP, "04.00"); \ - else \ - fprintf (FILE, "\t%s\t \"%s\"\n", VERSION_ASM_OP, "03.00"); \ - } \ - } while (0) - -/* Override svr[34].h. */ -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ - output_file_start (FILE, f_options, sizeof f_options / sizeof f_options[0], \ - W_options, sizeof W_options / sizeof W_options[0]) - -#undef ASM_FILE_END - -#define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) \ - fprintf (FILE, "\t%s\t \"%s\"\n", FILE_ASM_OP, NAME) - -#ifdef SDB_DEBUGGING_INFO -#undef ASM_OUTPUT_SOURCE_LINE -#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ - if (m88k_prologue_done) \ - fprintf (FILE, "\n\tln\t %d\t\t\t\t; Real source line %d\n",\ - LINE - sdb_begin_function_line, LINE) -#endif - -/* Code to handle #ident directives. Override svr[34].h definition. */ -#undef ASM_OUTPUT_IDENT -#ifdef DBX_DEBUGGING_INFO -#define ASM_OUTPUT_IDENT(FILE, NAME) -#else -#define ASM_OUTPUT_IDENT(FILE, NAME) \ - output_ascii (FILE, IDENT_ASM_OP, 4000, NAME, strlen (NAME)); -#endif - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ -#define ASM_APP_OFF "" - -/* Format the assembly opcode so that the arguments are all aligned. - The maximum instruction size is 8 characters (fxxx.xxx), so a tab and a - space will do to align the output. Abandon the output if a `%' is - encountered. */ -#define ASM_OUTPUT_OPCODE(STREAM, PTR) \ - { \ - int ch; \ - char *orig_ptr; \ - \ - for (orig_ptr = (PTR); \ - (ch = *(PTR)) && ch != ' ' && ch != '\t' && ch != '\n' && ch != '%'; \ - (PTR)++) \ - putc (ch, STREAM); \ - \ - if (ch == ' ' && orig_ptr != (PTR) && (PTR) - orig_ptr < 8) \ - putc ('\t', STREAM); \ - } - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number. - Updated by OVERRIDE_OPTIONS to include the # for version 03.00 syntax. */ - -#define REGISTER_NAMES \ - {"#r0"+1, "#r1"+1, "#r2"+1, "#r3"+1, "#r4"+1, "#r5"+1, "#r6"+1, "#r7"+1, \ - "#r8"+1, "#r9"+1, "#r10"+1,"#r11"+1,"#r12"+1,"#r13"+1,"#r14"+1,"#r15"+1,\ - "#r16"+1,"#r17"+1,"#r18"+1,"#r19"+1,"#r20"+1,"#r21"+1,"#r22"+1,"#r23"+1,\ - "#r24"+1,"#r25"+1,"#r26"+1,"#r27"+1,"#r28"+1,"#r29"+1,"#r30"+1,"#r31"+1,\ - "#x0"+1, "#x1"+1, "#x2"+1, "#x3"+1, "#x4"+1, "#x5"+1, "#x6"+1, "#x7"+1, \ - "#x8"+1, "#x9"+1, "#x10"+1,"#x11"+1,"#x12"+1,"#x13"+1,"#x14"+1,"#x15"+1,\ - "#x16"+1,"#x17"+1,"#x18"+1,"#x19"+1,"#x20"+1,"#x21"+1,"#x22"+1,"#x23"+1,\ - "#x24"+1,"#x25"+1,"#x26"+1,"#x27"+1,"#x28"+1,"#x29"+1,"#x30"+1,"#x31"+1} - -/* Define additional names for use in asm clobbers and asm declarations. - - We define the fake Condition Code register as an alias for reg 0 (which - is our `condition code' register), so that condition codes can easily - be clobbered by an asm. The carry bit in the PSR is now used. */ - -#define ADDITIONAL_REGISTER_NAMES {"psr", 0, "cc", 0} - -/* How to renumber registers for dbx and gdb. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Tell when to declare ASM names. Override svr4.h to provide this hook. */ -#undef DECLARE_ASM_NAME -#define DECLARE_ASM_NAME TARGET_SVR4 - -/* Write the extra assembler code needed to declare a function properly. */ -#undef ASM_DECLARE_FUNCTION_NAME -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do { \ - if (DECLARE_ASM_NAME) \ - { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ - putc ('\n', FILE); \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Write the extra assembler code needed to declare an object properly. */ -#undef ASM_DECLARE_OBJECT_NAME -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do { \ - if (DECLARE_ASM_NAME) \ - { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#undef ASM_FINISH_DECLARE_OBJECT -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && DECLARE_ASM_NAME \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, name); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - } while (0) - -/* This is how to declare the size of a function. */ -#undef ASM_DECLARE_FUNCTION_SIZE -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (DECLARE_ASM_NAME) \ - { \ - if (!flag_inhibit_size_directive) \ - { \ - char label[256]; \ - static int labelno = 0; \ - labelno++; \ - ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, (FNAME)); \ - fprintf (FILE, ",%s-", &label[1]); \ - assemble_name (FILE, (FNAME)); \ - putc ('\n', FILE); \ - } \ - } \ - } while (0) - -/* 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 { \ - fprintf (FILE, "\t%s\t ", GLOBAL_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc ('\n', FILE); \ - } while (0) - -/* The prefix to add to user-visible assembler symbols. - Override svr[34].h. */ -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" - -/* This is how to output a reference to a user-level label named NAME. - Override svr[34].h. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - { \ - if (!TARGET_NO_UNDERSCORES && !TARGET_SVR4) \ - fputc ('_', FILE); \ - fputs (NAME, FILE); \ - } - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - For V.4, labels use `.' rather than `@'. */ - -#undef ASM_OUTPUT_INTERNAL_LABEL -#ifdef AS_BUG_DOT_LABELS /* The assembler requires a declaration of local. */ -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, TARGET_SVR4 ? ".%s%d:\n\t%s\t .%s%d\n" : "@%s%d:\n", \ - PREFIX, NUM, INTERNAL_ASM_OP, PREFIX, NUM) -#else -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, TARGET_SVR4 ? ".%s%d:\n" : "@%s%d:\n", PREFIX, NUM) -#endif /* AS_BUG_DOT_LABELS */ - -/* 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'. This must agree - with ASM_OUTPUT_INTERNAL_LABEL above, except for being prefixed - with an `*'. */ - -#undef ASM_GENERATE_INTERNAL_LABEL -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, TARGET_SVR4 ? "*.%s%d" : "*@%s%d", PREFIX, NUM) - -/* Internal macro to get a single precision floating point value into - an int, so we can print its value in hex. */ -#define FLOAT_TO_INT_INTERNAL( FVALUE, IVALUE ) \ - { union { \ - REAL_VALUE_TYPE d; \ - struct { \ - unsigned sign : 1; \ - unsigned exponent1 : 1; \ - unsigned exponent2 : 3; \ - unsigned exponent3 : 7; \ - unsigned mantissa1 : 20; \ - unsigned mantissa2 : 3; \ - unsigned mantissa3 : 29; \ - } s; \ - } _u; \ - \ - union { \ - int i; \ - struct { \ - unsigned sign : 1; \ - unsigned exponent1 : 1; \ - unsigned exponent3 : 7; \ - unsigned mantissa1 : 20; \ - unsigned mantissa2 : 3; \ - } s; \ - } _u2; \ - \ - _u.d = REAL_VALUE_TRUNCATE (SFmode, FVALUE); \ - _u2.s.sign = _u.s.sign; \ - _u2.s.exponent1 = _u.s.exponent1; \ - _u2.s.exponent3 = _u.s.exponent3; \ - _u2.s.mantissa1 = _u.s.mantissa1; \ - _u2.s.mantissa2 = _u.s.mantissa2; \ - IVALUE = _u2.i; \ - } - -/* This is how to output an assembler line defining a `double' constant. - Use "word" pseudos to avoid printing NaNs, infinity, etc. */ -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - do { \ - union { REAL_VALUE_TYPE d; long l[2]; } x; \ - x.d = (VALUE); \ - fprintf (FILE, "\t%s\t 0x%.8x, 0x%.8x\n", INT_ASM_OP, \ - x.l[0], x.l[1]); \ - } while (0) - -/* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - do { \ - int i; \ - FLOAT_TO_INT_INTERNAL (VALUE, i); \ - fprintf (FILE, "\t%s\t 0x%.8x\n", INT_ASM_OP, i); \ - } while (0) - -/* Likewise for `int', `short', and `char' constants. */ -#define ASM_OUTPUT_INT(FILE,VALUE) \ -( fprintf (FILE, "\t%s\t ", INT_ASM_OP), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fprintf (FILE, "\t%s\t ", SHORT_ASM_OP), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\t%s\t ", CHAR_ASM_OP), \ - 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%s\t 0x%x\n", CHAR_ASM_OP, (VALUE)) - -/* The single-byte pseudo-op is the default. Override svr[34].h. */ -#undef ASM_BYTE_OP -#define ASM_BYTE_OP "byte" -#undef ASM_OUTPUT_ASCII -#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \ - output_ascii (FILE, ASCII_DATA_ASM_OP, 48, P, SIZE) - -/* Override svr4.h. Change to the readonly data section for a table of - addresses. final_scan_insn changes back to the text section. */ -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \ - do { \ - if (! CASE_VECTOR_INSNS) \ - { \ - readonly_data_section (); \ - ASM_OUTPUT_ALIGN (FILE, 2); \ - } \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ - } while (0) - -/* Epilogue for case labels. This jump instruction is called by casesi - to transfer to the appropriate branch instruction within the table. - The label `@L<n>e' is coined to mark the end of the table. */ -#define ASM_OUTPUT_CASE_END(FILE, NUM, TABLE) \ - do { \ - if (CASE_VECTOR_INSNS) \ - { \ - char label[256]; \ - ASM_GENERATE_INTERNAL_LABEL (label, "L", NUM); \ - fprintf (FILE, "%se:\n", &label[1]); \ - if (! flag_delayed_branch) \ - fprintf (FILE, "\tlda\t %s,%s[%s]\n", reg_names[1], \ - reg_names[1], reg_names[m88k_case_index]); \ - fprintf (FILE, "\tjmp\t %s\n", reg_names[1]); \ - } \ - } while (0) - -/* This is how to output an element of a case-vector that is absolute. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - do { \ - char buffer[256]; \ - ASM_GENERATE_INTERNAL_LABEL (buffer, "L", VALUE); \ - fprintf (FILE, CASE_VECTOR_INSNS ? "\tbr\t %s\n" : "\tword\t %s\n", \ - &buffer[1]); \ - } while (0) - -/* 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_OUTPUT_ADDR_VEC_ELT (FILE, VALUE) - -/* 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) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t%s\t %d\n", ALIGN_ASM_OP, 1<<(LOG)) - -/* On the m88100, align the text address to half a cache boundary when it - can only be reached by jumping. Pack code tightly when compiling - crtstuff.c. */ -#define LABEL_ALIGN_AFTER_BARRIER(LABEL) \ - (TARGET_88100 && !flag_inhibit_size_directive ? 3 : 2) - -/* Override svr[34].h. */ -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t%s\t %u\n", SKIP_ASM_OP, (SIZE)) - -/* Override svr4.h. */ -#undef ASM_OUTPUT_EXTERNAL_LIBCALL - -/* This says how to output an assembler line to define a global common - symbol. Size can be zero for the unusual case of a `struct { int : 0; }'. - Override svr[34].h. */ -#undef ASM_OUTPUT_COMMON -#undef ASM_OUTPUT_ALIGNED_COMMON -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fprintf ((FILE), "\t%s\t ", \ - ((SIZE) ? (SIZE) : 1) <= m88k_gp_threshold ? SCOMM_ASM_OP : COMMON_ASM_OP), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (SIZE) ? (SIZE) : 1)) - -/* This says how to output an assembler line to define a local common - symbol. Override svr[34].h. */ -#undef ASM_OUTPUT_LOCAL -#undef ASM_OUTPUT_ALIGNED_LOCAL -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fprintf ((FILE), "\t%s\t ", \ - ((SIZE) ? (SIZE) : 1) <= m88k_gp_threshold ? SBSS_ASM_OP : BSS_ASM_OP), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u,%d\n", (SIZE) ? (SIZE) : 1, (SIZE) <= 4 ? 4 : 8)) - -/* 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))) - -/* 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, "\tsubu\t %s,%s,%d\n\tst\t %s,%s,0\n", \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM], \ - (STACK_BOUNDARY / BITS_PER_UNIT), \ - reg_names[REGNO], \ - reg_names[STACK_POINTER_REGNUM]) - -/* Length in instructions of the code output by ASM_OUTPUT_REG_PUSH. */ -#define REG_PUSH_LENGTH 2 - -/* This is how to output an insn to pop a register from the stack. */ -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tld\t %s,%s,0\n\taddu\t %s,%s,%d\n", \ - reg_names[REGNO], \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM], \ - (STACK_BOUNDARY / BITS_PER_UNIT)) - -/* Length in instructions of the code output by ASM_OUTPUT_REG_POP. */ -#define REG_POP_LENGTH 2 - -/* 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 - -/* Macros to deal with OCS debug information */ - -#define OCS_START_PREFIX "Ltb" -#define OCS_END_PREFIX "Lte" - -#define PUT_OCS_FUNCTION_START(FILE) \ - { ASM_OUTPUT_INTERNAL_LABEL (FILE, OCS_START_PREFIX, m88k_function_number); } - -#define PUT_OCS_FUNCTION_END(FILE) \ - { ASM_OUTPUT_INTERNAL_LABEL (FILE, OCS_END_PREFIX, m88k_function_number); } - -/* Macros for debug information */ -#define DEBUGGER_AUTO_OFFSET(X) \ - (m88k_debugger_offset (X, 0) \ - + (TARGET_OCS_FRAME_POSITION ? 0 : m88k_stack_size - m88k_fp_offset)) - -#define DEBUGGER_ARG_OFFSET(OFFSET, X) \ - (m88k_debugger_offset (X, OFFSET) \ - + (TARGET_OCS_FRAME_POSITION ? 0 : m88k_stack_size - m88k_fp_offset)) - -/* Macros to deal with SDB debug information */ -#ifdef SDB_DEBUGGING_INFO - -/* Output structure tag names even when it causes a forward reference. */ -#define SDB_ALLOW_FORWARD_REFERENCES - -/* Print out extra debug information in the assembler file */ -#define PUT_SDB_SCL(a) \ - do { \ - register int s = (a); \ - register char *scl; \ - switch (s) \ - { \ - case C_EFCN: scl = "end of function"; break; \ - case C_NULL: scl = "NULL storage class"; break; \ - case C_AUTO: scl = "automatic"; break; \ - case C_EXT: scl = "external"; break; \ - case C_STAT: scl = "static"; break; \ - case C_REG: scl = "register"; break; \ - case C_EXTDEF: scl = "external definition"; break; \ - case C_LABEL: scl = "label"; break; \ - case C_ULABEL: scl = "undefined label"; break; \ - case C_MOS: scl = "structure member"; break; \ - case C_ARG: scl = "argument"; break; \ - case C_STRTAG: scl = "structure tag"; break; \ - case C_MOU: scl = "union member"; break; \ - case C_UNTAG: scl = "union tag"; break; \ - case C_TPDEF: scl = "typedef"; break; \ - case C_USTATIC: scl = "uninitialized static"; break; \ - case C_ENTAG: scl = "enumeration tag"; break; \ - case C_MOE: scl = "member of enumeration"; break; \ - case C_REGPARM: scl = "register parameter"; break; \ - case C_FIELD: scl = "bit field"; break; \ - case C_BLOCK: scl = "block start/end"; break; \ - case C_FCN: scl = "function start/end"; break; \ - case C_EOS: scl = "end of structure"; break; \ - case C_FILE: scl = "filename"; break; \ - case C_LINE: scl = "line"; break; \ - case C_ALIAS: scl = "duplicated tag"; break; \ - case C_HIDDEN: scl = "hidden"; break; \ - default: scl = "unknown"; break; \ - } \ - \ - fprintf(asm_out_file, "\tscl\t %d\t\t\t\t; %s\n", s, scl); \ - } while (0) - -#define PUT_SDB_TYPE(a) \ - do { \ - register int t = (a); \ - static char buffer[100]; \ - register char *p = buffer, *q; \ - register int typ = t; \ - register int i,d; \ - \ - for (i = 0; i <= 5; i++) \ - { \ - switch ((typ >> ((i*N_TSHIFT) + N_BTSHFT)) & 03) \ - { \ - case DT_PTR: \ - strcpy (p, "ptr to "); \ - p += sizeof("ptr to"); \ - break; \ - \ - case DT_ARY: \ - strcpy (p, "array of "); \ - p += sizeof("array of"); \ - break; \ - \ - case DT_FCN: \ - strcpy (p, "func ret "); \ - p += sizeof("func ret"); \ - break; \ - } \ - } \ - \ - switch (typ & N_BTMASK) \ - { \ - case T_NULL: q = "<no type>"; break; \ - case T_CHAR: q = "char"; break; \ - case T_SHORT: q = "short"; break; \ - case T_INT: q = "int"; break; \ - case T_LONG: q = "long"; break; \ - case T_FLOAT: q = "float"; break; \ - case T_DOUBLE: q = "double"; break; \ - case T_STRUCT: q = "struct"; break; \ - case T_UNION: q = "union"; break; \ - case T_ENUM: q = "enum"; break; \ - case T_MOE: q = "enum member"; break; \ - case T_UCHAR: q = "unsigned char"; break; \ - case T_USHORT: q = "unsigned short"; break; \ - case T_UINT: q = "unsigned int"; break; \ - case T_ULONG: q = "unsigned long"; break; \ - default: q = "void"; break; \ - } \ - \ - strcpy (p, q); \ - fprintf(asm_out_file, "\ttype\t %d\t\t\t\t; %s\n", \ - t, buffer); \ - } while (0) - -#define PUT_SDB_INT_VAL(a) \ - fprintf (asm_out_file, "\tval\t %d\n", (a)) - -#define PUT_SDB_VAL(a) \ -( fprintf (asm_out_file, "\tval\t "), \ - output_addr_const (asm_out_file, (a)), \ - fputc ('\n', asm_out_file)) - -#define PUT_SDB_DEF(a) \ - do { fprintf (asm_out_file, "\tsdef\t "); \ - ASM_OUTPUT_LABELREF (asm_out_file, a); \ - fputc ('\n', asm_out_file); \ - } while (0) - -#define PUT_SDB_PLAIN_DEF(a) \ - fprintf(asm_out_file,"\tsdef\t .%s\n", a) - -/* Simply and endef now. */ -#define PUT_SDB_ENDEF \ - fputs("\tendef\n\n", asm_out_file) - -#define PUT_SDB_SIZE(a) \ - fprintf (asm_out_file, "\tsize\t %d\n", (a)) - -/* Max dimensions to store for debug information (limited by COFF). */ -#define SDB_MAX_DIM 6 - -/* New method for dim operations. */ -#define PUT_SDB_START_DIM \ - fputs("\tdim\t ", asm_out_file) - -/* How to end the DIM sequence. */ -#define PUT_SDB_LAST_DIM(a) \ - fprintf(asm_out_file, "%d\n", a) - -#define PUT_SDB_TAG(a) \ - do { \ - fprintf (asm_out_file, "\ttag\t "); \ - ASM_OUTPUT_LABELREF (asm_out_file, a); \ - fputc ('\n', asm_out_file); \ - } while( 0 ) - -#define PUT_SDB_BLOCK_OR_FUNCTION(NAME, SCL, LINE) \ - do { \ - fprintf (asm_out_file, "\n\tsdef\t %s\n\tval\t .\n", \ - NAME); \ - PUT_SDB_SCL( SCL ); \ - fprintf (asm_out_file, "\tline\t %d\n\tendef\n\n", \ - (LINE)); \ - } while (0) - -#define PUT_SDB_BLOCK_START(LINE) \ - PUT_SDB_BLOCK_OR_FUNCTION (".bb", C_BLOCK, (LINE)) - -#define PUT_SDB_BLOCK_END(LINE) \ - PUT_SDB_BLOCK_OR_FUNCTION (".eb", C_BLOCK, (LINE)) - -#define PUT_SDB_FUNCTION_START(LINE) \ - do { \ - fprintf (asm_out_file, "\tln\t 1\n"); \ - PUT_SDB_BLOCK_OR_FUNCTION (".bf", C_FCN, (LINE)); \ - } while (0) - -#define PUT_SDB_FUNCTION_END(LINE) \ - do { \ - PUT_SDB_BLOCK_OR_FUNCTION (".ef", C_FCN, (LINE)); \ - } while (0) - -#define PUT_SDB_EPILOGUE_END(NAME) \ - do { \ - text_section (); \ - fprintf (asm_out_file, "\n\tsdef\t "); \ - ASM_OUTPUT_LABELREF(asm_out_file, (NAME)); \ - fputc('\n', asm_out_file); \ - PUT_SDB_SCL( C_EFCN ); \ - fprintf (asm_out_file, "\tendef\n\n"); \ - } while (0) - -#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ - sprintf ((BUFFER), ".%dfake", (NUMBER)); - -#endif /* SDB_DEBUGGING_INFO */ - -/* Support const and tdesc sections. Generally, a const section will - be distinct from the text section whenever we do V.4-like things - and so follows DECLARE_ASM_NAME. Note that strings go in text - rather than const. Override svr[34].h. */ - -#undef USE_CONST_SECTION -#undef EXTRA_SECTIONS - -#define USE_CONST_SECTION DECLARE_ASM_NAME - -#if defined(USING_SVR4_H) - -#define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_ctors, in_dtors -#define INIT_SECTION_FUNCTION -#define FINI_SECTION_FUNCTION - -#else -#if defined(USING_SVR3_H) - -#define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_ctors, in_dtors, \ - in_init, in_fini - -#else /* luna or other not based on svr[34].h. */ - -#undef INIT_SECTION_ASM_OP -#define EXTRA_SECTIONS in_const, in_tdesc, in_sdata -#define CONST_SECTION_FUNCTION \ -void \ -const_section () \ -{ \ - text_section(); \ -} -#define CTORS_SECTION_FUNCTION -#define DTORS_SECTION_FUNCTION -#define INIT_SECTION_FUNCTION -#define FINI_SECTION_FUNCTION - -#endif /* USING_SVR3_H */ -#endif /* USING_SVR4_H */ - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - \ -void \ -tdesc_section () \ -{ \ - if (in_section != in_tdesc) \ - { \ - fprintf (asm_out_file, "%s\n", TDESC_SECTION_ASM_OP); \ - in_section = in_tdesc; \ - } \ -} \ - \ -void \ -sdata_section () \ -{ \ - if (in_section != in_sdata) \ - { \ - fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \ - in_section = in_sdata; \ - } \ -} \ - \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION \ - INIT_SECTION_FUNCTION \ - FINI_SECTION_FUNCTION - -/* A C statement or statements to switch to the appropriate - section for output of DECL. DECL is either a `VAR_DECL' node - or a constant of some sort. RELOC indicates whether forming - the initial value of DECL requires link-time relocations. - - For strings, the section is selected before the segment info is encoded. */ -#undef SELECT_SECTION -#define SELECT_SECTION(DECL,RELOC) \ -{ \ - if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (! flag_writable_strings) \ - const_section (); \ - else if ( TREE_STRING_LENGTH (DECL) <= m88k_gp_threshold) \ - sdata_section (); \ - else \ - data_section (); \ - } \ - else if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0))) \ - sdata_section (); \ - else if ((flag_pic && RELOC) \ - || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ - || !DECL_INITIAL (DECL) \ - || (DECL_INITIAL (DECL) != error_mark_node \ - && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - data_section (); \ - else \ - const_section (); \ - } \ - else \ - const_section (); \ -} - -/* Jump tables consist of branch instructions and should be output in - the text section. When we use a table of addresses, we explicitly - change to the readonly data section. */ -#define JUMP_TABLES_IN_TEXT_SECTION 1 - -/* Define this macro if references to a symbol must be treated differently - depending on something about the variable or function named by the - symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the rtl for - DECL has been created and stored in `DECL_RTL (DECL)'. The value of the - rtl will be a `mem' whose address is a `symbol_ref'. - - For the m88k, determine if the item should go in the global pool. */ -#define ENCODE_SECTION_INFO(DECL) \ - do { \ - if (m88k_gp_threshold > 0) \ - if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL)) \ - { \ - int size = int_size_in_bytes (TREE_TYPE (DECL)); \ - \ - if (size > 0 && size <= m88k_gp_threshold) \ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ - } \ - } \ - else if (TREE_CODE (DECL) == STRING_CST \ - && flag_writable_strings \ - && TREE_STRING_LENGTH (DECL) <= m88k_gp_threshold) \ - SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 1; \ - } 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. */ -#define PRINT_OPERAND_PUNCT_VALID_P(c) \ - ((c) == '#' || (c) == '.' || (c) == '!' || (c) == '*' || (c) == ';') - -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - -/* Print a memory address as an operand to reference that memory location. */ -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) - -/* This says not to strength reduce the addr calculations within loops - (otherwise it does not take advantage of m88k scaled loads and stores */ - -#define DONT_REDUCE_ADDR diff --git a/gcc/config/m88k/m88k.md b/gcc/config/m88k/m88k.md deleted file mode 100755 index 118ebe3..0000000 --- a/gcc/config/m88k/m88k.md +++ /dev/null @@ -1,4023 +0,0 @@ -;;- Machine description for the Motorola 88000 for GNU C compiler -;;; Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. -;; Contributed by Michael Tiemann (tiemann@mcc.com) -;; Currently maintained by (gcc@dg-rtp.dg.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. - - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; RCS rev field. This is a NOP, just to get the RCS id into the -;; program image. -(define_expand "m88k_rcs_id" - [(match_operand:SI 0 "" "")] - "" - "{ static char rcs_id[] = \"$What: <@(#) m88k.md,v 1.1.1.2.2.2> $\"; - FAIL; }") - -;; Attribute describing the processor. This attribute must match exactly -;; with the processor_type enumeration in m88k.h. - -; Target CPU. -(define_attr "cpu" "m88100,m88110,m88000" - (const (symbol_ref "m88k_cpu"))) - -; Type of each instruction. Default is arithmetic. -; I'd like to write the list as this, but genattrtab won't accept it. -; -; "branch,jump,call, ; flow-control instructions -; load,store,loadd,loada, ; data unit instructions -; spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions -; spmul,dpmul,imul, ; FPU multiply instructions -; arith,bit,mov ; integer unit instructions -; marith,weird" ; multi-word instructions - -; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. -(define_attr "type" - "branch,jump,call,load,store,loadd,loada,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,weird" - (const_string "arith")) - -(define_attr "fpu" "yes,no" - (if_then_else - (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv") - (const_string "yes") (const_string "no"))) - -; Length in # of instructions of each insn. The values are not exact, but -; are safe. -(define_attr "length" "" - (cond [(eq_attr "type" "marith,weird,branch") - (const_int 2)] - (const_int 1))) - -; Describe a user's asm statement. -(define_asm_attributes - [(set_attr "type" "weird")]) - -; Define the delay slot requirements for branches and calls. -; The m88100 annuls instructions if a conditional branch is taken. -; For insns of TYPE_BRANCH that are multi-word instructions, the -; delay slot applies to the first instruction. - -; @@ For the moment, reorg.c requires that the delay slot of a branch not -; be a call or branch. - -(define_delay (eq_attr "type" "branch,jump") - [(and - (and - (eq_attr "type" "!branch,jump,call,marith,weird") ; required. - (eq_attr "type" "!load,loadd")) ; issue as-soon-as-possible. - (eq_attr "fpu" "no")) ; issue as-soon-as-possible. - (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1) - -; output_call supports an unconditional branch in the delay slot of -; a call. (@@ Support for this case is expected in reorg.c soon.) - -(define_delay (eq_attr "type" "call") - [(eq_attr "type" "!branch,call,marith,weird") ; required. - (nil) (nil)]) - -; An abstract block diagram of the function units for the m88100. -; -; * -; | -; +---v----+ -; | decode | -; +-vv-v-v-+ fpu -; ,----------'| | `----------------------. -; | | | | ,-----. -; load | store | | arith | | | -; | | | +-v-v-+ | dp source -; | | | | fp1 |---' -; store | | | div +-v-v-+ -; ,------. | | | ,-----. ,-----------' `-----------. -; | | | | | | | | | -; | +--v---v--+ ,---' | | +-v-v---+ +---v---+ -; | | stage 2 | | | `---| add 2 | | mul 2 | -; | +---------+ | +--v--+ +-------+ imul +-------+ -; | | stage 1 | | | alu | | add 3 | ,--------| mul 3 | -; | +---------+ | +--v--+ +-------+ | +-------+ -; | | stage 0 | | | | add 4 | | | mul 4 | -; | +--v---v--+ | | +---v---+ | +-------+ -; | | | | | | | | mul 5 | -; | * | | | | | +---v---+ -; | | | | | +----v----+ | -; | load | | | fp add `------>| fp last |<------' fp mul -; | | | | +---v-v--^+ -; | | | | | | | -; | | | | | `--' dp dest -; | | +--v-----v--+ | -; | `--->| writeback |<--------------------' -; | +--v-----v--+ -; | | | -; `------------------' * -; -; The decode unit need not be specified. -; Consideration of writeback contention is critical to superb scheduling. -; -; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) - -; Describing the '100 alu is currently not useful. -;(define_function_unit "alu" 1 0 (eq_attr "type" -; "!store,marith,weird") 1 0) -;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0) - -(define_function_unit "alu" 1 0 - (and (eq_attr "type" "loada,arith,mov") (eq_attr "cpu" "!m88100")) 2 0) -(define_function_unit "alu" 1 0 - (and (eq_attr "type" "marith,weird") (eq_attr "cpu" "!m88100")) 4 0) - -(define_function_unit "bit" 1 0 - (and (eq_attr "type" "bit") (eq_attr "cpu" "!m88100")) 2 2) - -(define_function_unit "mem100" 1 0 - (and (eq_attr "type" "store,loada") (eq_attr "cpu" "m88100")) 1 0) -(define_function_unit "mem100" 1 0 - (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 0) -(define_function_unit "mem100" 1 0 - (and (eq_attr "type" "loadd") (eq_attr "cpu" "m88100")) 3 2) - -(define_function_unit "mem110" 1 0 - (and (eq_attr "type" "load,loadd") (eq_attr "cpu" "!m88100")) 3 2) -(define_function_unit "mem110" 1 0 - (and (eq_attr "type" "store") (eq_attr "cpu" "!m88100")) 1 2) - -; The times are adjusted to include fp1 and fplast, but then are further -; adjusted based on the actual generated code. The notation to the right -; is the total latency. A range denotes a group of instructions and/or -; conditions (the extra clock of fplast time with some sequences). - -(define_function_unit "fpmul100" 1 0 - (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 0) ; 6-8 -(define_function_unit "fpmul100" 1 0 - (and (eq_attr "type" "dpmul") (eq_attr "cpu" "m88100")) 7 0) ; 9-10 -(define_function_unit "fpmul100" 1 0 - (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 0) ; 4 - -(define_function_unit "fpmul110" 1 0 - (and (eq_attr "type" "imul,spmul,dpmul") - (eq_attr "cpu" "!m88100")) 5 2) ; 3 - -(define_function_unit "fpadd100" 1 5 - (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 0) ; 5-6 -(define_function_unit "fpadd100" 1 5 - (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 0) ; 6-7 - -(define_function_unit "fpadd110" 1 0 - (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 5 2) ; 3 -(define_function_unit "fpadd110" 1 0 - (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2) ; 1 - -(define_function_unit "fpadd100" 1 5 - (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 0) ; 30-31 -(define_function_unit "fpadd100" 1 5 - (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 0) ; 60-61 -(define_function_unit "fpadd100" 1 5 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 0) ; 38 - -(define_function_unit "div" 1 1 - (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 25 2) ; 13 -(define_function_unit "div" 1 1 - (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 45 2) ; 23 -(define_function_unit "div" 1 1 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 35 2) ; 18 - -;; Superoptimizer sequences - -;; geu+: { r = ((unsigned_word) v0 >= (unsigned_word) v1) + v2; } -;; subu.co r5,r2,r3 -;; addu.cio r6,r4,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (geu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "register_operand" "r"))))] - "" - [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) - (set (match_dup 0) - (plus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 0)))] - "") - -;; leu+: { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; } -;; subu.co r5,r3,r2 -;; addu.cio r6,r4,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (leu:SI (match_operand:SI 3 "register_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "" - [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) - (set (match_dup 0) - (plus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 0)))] - "") - -;; eq0+: { r = (v0 == 0) + v1; } -;; subu.co r4,r0,r2 -;; addu.cio r5,r3,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (eq:SI (match_operand:SI 2 "register_operand" "r") - (const_int 0))))] - "" - [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1)) - (set (match_dup 0) - (plus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 0)))] - "") - -;; ltu-: { r = v2 - ((unsigned_word) v0 < (unsigned_word) v1); } -;; subu.co r5,r2,r3 -;; subu.cio r6,r4,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (ltu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 1 "register_operand" "r")))] - "" - [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) - (set (match_dup 0) - (minus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 1)))] - "") - -;; gtu-: { r = v2 - ((unsigned_word) v0 > (unsigned_word) v1); } -;; subu.co r5,r3,r2 -;; subu.cio r6,r4,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (gtu:SI (match_operand:SI 3 "register_operand" "r") - (match_operand:SI 2 "register_operand" "r")) - (match_operand:SI 1 "register_operand" "r")))] - "" - [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) - (set (match_dup 0) - (minus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 1)))] - "") - -;; ne0-: { r = v1 - (v0 != 0); } -;; subu.co r4,r0,r2 -;; subu.cio r5,r3,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (ne:SI (match_operand:SI 2 "register_operand" "r") - (const_int 0)) - (match_operand:SI 1 "register_operand" "r")))] - "" - [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1)) - (set (match_dup 0) - (minus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 1)))] - "") - -;; ges0-: { r = v1 - ((signed_word) v0 >= 0); } -;; addu.co r4,r2,r2 -;; subu.cio r5,r3,r0 - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (xor:SI (lshiftrt:SI - (match_operand:SI 2 "register_operand" "r") - (const_int 31)) - (const_int 1))))] - "" - [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 2)] 0)) - (set (match_dup 0) - (minus:SI (match_dup 1) - (unspec:SI [(const_int 0) - (reg:CC 0)] 1)))] - "") - -;; This rich set of complex patterns are mostly due to Torbjorn Granlund -;; (tege@sics.se). They've changed since then, so don't complain to him -;; if they don't work right. - -;; Regarding shifts, gen_lshlsi3 generates ASHIFT. The gen functions -;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing -;; special needs to be done here. - -;; Optimize possible cases of the set instruction. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (const_int -1) - (match_operand:SI 1 "register_operand" "r")))] - "" - "set %0,%#r0,%1" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (ashift:SI (const_int -1) - (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "set %0,%2,%1" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "r") - (ashift:SI (const_int -1) - (match_operand:SI 2 "register_operand" "r"))))] - "" - "set %0,%1,%2" - [(set_attr "type" "bit")]) - -;; Optimize possible cases of the mak instruction. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "immediate_operand" "n")))] - "mak_mask_p (INTVAL (operands[3]) >> INTVAL (operands[2]))" - "* -{ - operands[4] = GEN_INT (exact_log2 (1 + (INTVAL (operands[3]) - >> INTVAL(operands[2])))); - return \"mak %0,%1,%4<%2>\"; -}" - [(set_attr "type" "bit")]) - -;; Optimize possible cases of output_and. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "") - (match_operand:SI 3 "int5_operand" "")) - (match_operand:SI 4 "int5_operand" "")))] - "INTVAL (operands[2]) + INTVAL (operands[3]) + INTVAL (operands[4]) == 32" - "* -{ - operands[2] - = GEN_INT (((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[4])); - return output_and (operands); -}" - [(set_attr "type" "marith")]) ; arith,bit,marith. length is 1 or 2. - -;; Improve logical operations on compare words -;; -;; We define all logical operations on CCmode values to preserve the pairwise -;; relationship of the compare bits. This allows a future branch prediction -;; pass the degree of freedom needed to change and/bb0-le into or/bb1-gt. -;; THIS IS CURRENTLY FALSE! -;; -;; Opportunities arise when conditional expressions using && and || are made -;; unconditional. When these are used to branch, the sequence is -;; cmp/cmp/extu/extu/{and,or}/bcnd-{eq0,ne0}. When these are used to create -;; a value, the sequence is cmp/cmp/extu/extu/{and,or} for 1 or 0 or -;; cmp/cmp/ext/ext/{and,or} for -1 or 0. -;; -;; When the extracted conditions are the same, the define_split patterns -;; below change extu/extu/{and,or} into {and,or}/extu. If the reversed -;; conditions match, one compare word can be complimented, resulting in -;; {and.c,or.c}/extu. These changes are done for ext/ext/{and,or} as well. -;; If the conditions don't line up, one can be rotated. To keep the pairwise -;; relationship, it may be necessary to both rotate and compliment. Rotating -;; makes branching cheaper, but doesn't help (or hurt) creating a value, so -;; we don't do this for ext/ext/{and,or}. -;; -;; These changes result in the sequence extu/bcnd-{eq0,ne0} which is combined -;; into an alternate form of bb0 and bb1. - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (neg:SI - (match_operator 1 "even_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (ior:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) == GET_CODE (operands[3])) - ; /* The conditions match. */ - else if (GET_CODE (operands[1]) - == reverse_condition (GET_CODE (operands[3]))) - /* Reverse the condition by complimenting the compare word. */ - operands[4] = gen_rtx (NOT, CCmode, operands[4]); - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - - operands[4] = gen_rtx (ROTATE, CCmode, operands[4], - GEN_INT (((cv2 & ~1) - (cv1 & ~1)) & 0x1f)); - /* Reverse the condition if needed. */ - if ((cv1 & 1) != (cv2 & 1)) - operands[4] = gen_rtx (NOT, CCmode, operands[4]); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (neg:SI - (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "odd_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (and:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) == GET_CODE (operands[3])) - ; /* The conditions match. */ - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - - operands[4] = gen_rtx (ROTATE, CCmode, operands[4], - GEN_INT ((cv2 - cv1) & 0x1f)); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (neg:SI - (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "even_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (ior:CCEVEN (not:CC (match_dup 2)) - (match_dup 4))) - (set (match_dup 0) - (neg:SI (match_op_dup 3 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) - == reverse_condition (GET_CODE (operands[3]))) - ; - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - - operands[2] = gen_rtx (ROTATE, CCmode, operands[2], - GEN_INT (((cv1 & ~1) - (cv2 & ~1)) & 0x1f)); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operator 1 "even_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == GET_CODE (operands[3]) - || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" - [(set (match_dup 5) - (ior:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - /* Reverse the condition by complimenting the compare word. */ - if (GET_CODE (operands[1]) != GET_CODE (operands[3])) - operands[4] = gen_rtx (NOT, CCmode, operands[4]);") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "odd_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == GET_CODE (operands[3])" - [(set (match_dup 5) - (and:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "even_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" - [(set (match_dup 5) - (ior:CCEVEN (not:CC (match_dup 4)) - (match_dup 2))) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (neg:SI - (match_operator 1 "even_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (and:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) == GET_CODE (operands[3])) - ; /* The conditions match. */ - else if (GET_CODE (operands[1]) - == reverse_condition (GET_CODE (operands[3]))) - /* Reverse the condition by complimenting the compare word. */ - operands[4] = gen_rtx (NOT, CCmode, operands[4]); - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - operands[4] = gen_rtx (ROTATE, CCmode, operands[4], - GEN_INT (((cv2 & ~1) - (cv1 & ~1)) & 0x1f)); - /* Reverse the condition if needed. */ - if ((cv1 & 1) != (cv2 & 1)) - operands[4] = gen_rtx (NOT, CCmode, operands[4]); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (neg:SI - (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "odd_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (ior:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) == GET_CODE (operands[3])) - ; /* The conditions match. */ - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - operands[4] = gen_rtx (ROTATE, CCmode, operands[4], - GEN_INT ((cv2 - cv1) & 0x1f)); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (neg:SI - (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)])) - (neg:SI - (match_operator 3 "even_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)])))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "" - [(set (match_dup 5) - (and:CCEVEN (not:CC (match_dup 2)) - (match_dup 4))) - (set (match_dup 0) - (neg:SI (match_op_dup 3 [(match_dup 5) (const_int 0)])))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - if (GET_CODE (operands[1]) - == reverse_condition (GET_CODE (operands[3]))) - ; - else - { - /* Make the condition pairs line up by rotating the compare word. */ - int cv1 = condition_value (operands[1]); - int cv2 = condition_value (operands[3]); - operands[2] = gen_rtx (ROTATE, CCmode, operands[2], - GEN_INT (((cv1 & ~1) - (cv2 & ~1)) & 0x1f)); - }") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operator 1 "even_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == GET_CODE (operands[3]) - || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" - [(set (match_dup 5) - (and:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0); - /* Reverse the condition by complimenting the compare word. */ - if (GET_CODE (operands[1]) != GET_CODE (operands[3])) - operands[4] = gen_rtx (NOT, CCmode, operands[4]);") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "odd_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == GET_CODE (operands[3])" - [(set (match_dup 5) - (ior:CCEVEN (match_dup 4) - (match_dup 2))) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operator 1 "odd_relop" - [(match_operand 2 "partial_ccmode_register_operand" "%r") - (const_int 0)]) - (match_operator 3 "even_relop" - [(match_operand 4 "partial_ccmode_register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 5 "register_operand" "=r"))] - "GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" - [(set (match_dup 5) - (and:CCEVEN (not:CC (match_dup 2)) - (match_dup 4))) - (set (match_dup 0) - (match_op_dup 3 [(match_dup 5) (const_int 0)]))] - "operands[5] = gen_rtx(SUBREG, CCEVENmode, operands[5], 0);") - - -;; Logical operations on compare words. - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (not:CC (match_operand 1 "partial_ccmode_register_operand" "r")) - (match_operand 2 "partial_ccmode_register_operand" "r")))] - "" - "and.c %0,%2,%1") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (match_operand 1 "partial_ccmode_register_operand" "%r") - (match_operand 2 "partial_ccmode_register_operand" "r")))] - "" - "and %0,%1,%2") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CCEVEN (not:CC (match_operand 1 "partial_ccmode_register_operand" "r")) - (match_operand 2 "partial_ccmode_register_operand" "r")))] - "" - "or.c %0,%2,%1") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CCEVEN (match_operand 1 "partial_ccmode_register_operand" "%r") - (match_operand 2 "partial_ccmode_register_operand" "r")))] - "" - "or %0,%1,%2") - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r") - (rotate:CC (match_operand:CC 1 "register_operand" "r") - (match_operand:CC 2 "int5_operand" "")))] - "" - "rot %0,%1,%2" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" "")))] - "" - "rot %0,%1,%2" - [(set_attr "type" "bit")]) - -;; rotate/and[.c] and rotate/ior[.c] - -(define_split - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" "")) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))] - "" - [(set (match_dup 4) - (rotate:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (ior:CCEVEN (match_dup 4) (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" "")) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_scratch:CCEVEN 4 "=r"))] - "" - "#") - -(define_split - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" ""))) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))] - "" - [(set (match_dup 4) - (rotate:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (ior:CCEVEN (not:CC (match_dup 4)) (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (ior:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" ""))) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_scratch:CCEVEN 4 "=r"))] - "" - "#") - -(define_split - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" "")) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))] - "" - [(set (match_dup 4) - (rotate:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (and:CCEVEN (match_dup 4) (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" "")) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_scratch:CCEVEN 4 "=r"))] - "" - "#") - -(define_split - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" ""))) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_operand:CCEVEN 4 "register_operand" "=r"))] - "" - [(set (match_dup 4) - (rotate:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (and:CCEVEN (not:CC (match_dup 4)) (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:CCEVEN 0 "register_operand" "=r") - (and:CCEVEN (not:CC (rotate:CC (match_operand 1 "partial_ccmode_register_operand" "r") - (match_operand:CC 2 "int5_operand" ""))) - (match_operand 3 "partial_ccmode_register_operand" "r"))) - (clobber (match_scratch:CCEVEN 4 "=r"))] - "" - "#") - - -;; Recognize bcnd instructions for integer values. This is distinguished -;; from a conditional branch instruction (below) with SImode instead of -;; CCmode. - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "relop_no_unsigned" - [(match_operand:SI 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%B0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -;; Recognize tests for sign and zero. - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(match_operand:SI 1 "register_operand" "r") - (const_int -2147483648)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%E0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(zero_extract:SI - (match_operand:SI 1 "register_operand" "r") - (const_int 31) - (const_int 1)) - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%D0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -;; Recognize bcnd instructions for double integer values - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "relop_no_unsigned" - [(sign_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%B0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%B0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -; @@ I doubt this is interesting until cmpdi is provided. Anyway, it needs -; to be reworked. -; -;(define_insn "" -; [(set (pc) -; (if_then_else -; (match_operator 0 "relop_no_unsigned" -; [(match_operand:DI 1 "register_operand" "r") -; (const_int 0)]) -; (match_operand 2 "pc_or_label_ref" "") -; (match_operand 3 "pc_or_label_ref" "")))] -; "" -; "* -;{ -; switch (GET_CODE (operands[0])) -; { -; case EQ: -; case NE: -; /* I'm not sure if it's safe to use .n here. */ -; return \"or %!,%1,%d1\;bcnd %R3%B0,%!,%P2%P3\"; -; case GE: -; case LT: -; return \"bcnd%. %R3%B0,%1,%P2%P3\"; -; case GT: -; { -; rtx op2 = operands[2]; -; operands[2] = operands[3]; -; operands[3] = op2; -; } -; case LE: -; if (GET_CODE (operands[3]) == LABEL_REF) -; { -; int label_num; -; operands[2] = gen_label_rtx (); -; label_num = XINT (operands[2], 3); -; output_asm_insn -; (\"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#ne0,%!,%3\", operands); -; output_label (label_num); -; return \"\"; -; } -; else -; return \"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#eq0,%!,%2\"; -; } -;}") - -;; Recognize bcnd instructions for single precision float values -;; Exclude relational operations as they must signal NaNs. - -;; @@ These bcnd insns for float and double values don't seem to be recognized. - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(float_extend:DF - (match_operand:SF 1 "register_operand" "r")) - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%D0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(match_operand:SF 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bcnd%. %R3%D0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -;; Recognize bcnd instructions for double precision float values -;; Exclude relational operations as they must signal NaNs. - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "equality_op" - [(match_operand:DF 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "* -{ - int label_num; - - if (GET_CODE (operands[0]) == NE) - { - rtx op2 = operands[2]; - operands[2] = operands[3]; - operands[3] = op2; - } - if (GET_CODE (operands[3]) == LABEL_REF) - return \"bcnd 0x5,%1,%3\;bcnd %#ne0,%d1,%3\"; - - operands[3] = gen_label_rtx (); - label_num = XINT (operands[3], 3); - output_asm_insn (\"bcnd 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands); - output_label (label_num); - return \"\"; -}" - [(set_attr "type" "weird") - (set_attr "length" "3")]) - -;; Recognize bb0 and bb1 instructions. These use two unusual template -;; patterns, %Lx and %Px. %Lx outputs a 1 if operand `x' is a LABEL_REF -;; otherwise it outputs a 0. It then may print ".n" if the delay slot -;; is used. %Px does noting if `x' is PC and outputs the operand if `x' -;; is a LABEL_REF. - -(define_insn "" - [(set (pc) - (if_then_else - (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "int5_operand" "")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2 (31-%1),%0,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "int5_operand" "")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3 (31-%1),%0,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "int5_operand" "")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2 (31-%1),%0,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "int5_operand" "")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3 (31-%1),%0,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") - (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "(GET_CODE (operands[0]) == CONST_INT) - != (GET_CODE (operands[1]) == CONST_INT)" - "bb%L3 %p1,%0,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") - (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "(GET_CODE (operands[0]) == CONST_INT) - != (GET_CODE (operands[1]) == CONST_INT)" - "bb%L2 %p1,%0,%P2%P3" - [(set_attr "type" "branch")]) - -;; The comparison operations store the comparison into a register and -;; record that register. The following Bxx or Sxx insn uses that -;; register as an input. To facilitate use of bcnd instead of cmp/bb1, -;; cmpsi records its operands and produces no code when any operand -;; is constant. In this case, the Bxx insns use gen_bcnd and the -;; Sxx insns use gen_test to ensure a cmp has been emitted. -;; -;; This could also be done for SFmode and DFmode having only beq and bne -;; use gen_bcnd. The others must signal NaNs. It seems though that zero -;; has already been copied into a register. -;; -;; cmpsi/beq and cmpsi/bne can always be done with bcnd if any operand -;; is a constant. (This idea is due to Torbjorn Granlund.) Others can -;; use bcnd only if an operand is zero. -;; -;; It is necessary to distinguish a register holding condition codes. -;; This is done by context. - -(define_expand "test" - [(set (match_dup 2) - (compare:CC (match_operand 0 "" "") - (match_operand 1 "" "")))] - "" - " -{ - if (m88k_compare_reg) - abort (); - - if (GET_CODE (operands[0]) == CONST_INT - && ! SMALL_INT (operands[0])) - operands[0] = force_reg (SImode, operands[0]); - - if (GET_CODE (operands[1]) == CONST_INT - && ! SMALL_INT (operands[1])) - operands[1] = force_reg (SImode, operands[1]); - - operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); -}") - -; @@ The docs say don't do this. It's probably a nop since the insn looks -; identical to cmpsi against zero. Is there an advantage to providing -; this, perhaps with a different form? - -;(define_expand "tstsi" -; [(set (match_dup 1) -; (compare:CC (match_operand:SI 0 "register_operand" "") -; (const_int 0)))] -; "" -; " -;{ -; m88k_compare_reg = 0; -; m88k_compare_op0 = operands[0]; -; m88k_compare_op1 = const0_rtx; -; DONE; -;}") - -(define_expand "cmpsi" - [(set (match_dup 2) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == CONST_INT - || GET_CODE (operands[1]) == CONST_INT) - { - m88k_compare_reg = 0; - m88k_compare_op0 = operands[0]; - m88k_compare_op1 = operands[1]; - DONE; - } - operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); -}") - -(define_expand "cmpsf" - [(set (match_dup 2) - (compare:CC (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] - "" - "operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);") - -(define_expand "cmpdf" - [(set (match_dup 2) - (compare:CC (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")))] - "" - " -{ - operands[0] = legitimize_operand (operands[0], DFmode); - operands[1] = legitimize_operand (operands[1], DFmode); - operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); -}") - -; @@ Get back to this later on. -; -;(define_insn "cmpdi" -; [(set (cc0) -; (compare:CC (match_operand:DI 0 "register_operand" "r") -; (match_operand:DI 1 "register_operand" "r")))] -; "" -; "* -;{ -; if ((cc_status.mdep & MDEP_LS_CHANGE) != 0) -; abort (); /* output_move_double MDEP_LS_CHANGE bits were set. */ -; -; cc_status.mdep &= ~ MDEP_LS_MASK; -; -; operands[2] = gen_label_rtx (); -; /* Remember, %! is the condition code register and %@ is the -; literal synthesis register. */ -; -; output_asm_insn (\"cmp %!,%0,%1\;bb0 %#eq,%!,%l2\;cmp %!,%d0,%d1\", -; operands); -; -; output_asm_insn (\"extu %@,%!,4<8>\;clr %!,%!,4<4>\", operands); -; output_asm_insn (\"mak %@,%@,4<4>\;or %!,%!,%@\", operands); -; output_label (XINT (operands[2], 3)); -; return \"\"; -;}" - -;; The actual compare instructions. - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r") - (compare:CC (match_operand:SI 1 "register_operand" "rO") - (match_operand:SI 2 "arith_operand" "rI")))] - "" - "cmp %0,%r1,%2") - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r,r,r,r") - (compare:CC (match_operand:SF 1 "register_operand" "r,r,x,x") - (match_operand:SF 2 "real_or_0_operand" "r,G,x,G")))] - "" - "@ - fcmp.sss %0,%1,%2 - fcmp.sss %0,%1,%#r0 - fcmp.sss %0,%1,%2 - fcmp.sss %0,%1,%#x0" - [(set_attr "type" "spcmp")]) - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r,r") - (compare:CC (match_operand:DF 1 "register_operand" "r,x") - (float_extend:DF - (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fcmp.sds %0,%1,%2" - [(set_attr "type" "dpcmp")]) - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r,r") - (compare:CC (float_extend:DF - (match_operand:SF 1 "register_operand" "r,x")) - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fcmp.ssd %0,%1,%2" - [(set_attr "type" "dpcmp")]) - -(define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r,r,r,r") - (compare:CC (match_operand:DF 1 "register_operand" "r,r,x,x") - (match_operand:DF 2 "real_or_0_operand" "r,G,x,G")))] - "" - "@ - fcmp.sdd %0,%1,%2 - fcmp.sds %0,%1,%#r0 - fcmp.sdd %0,%1,%2 - fcmp.sds %0,%1,%#x0" - [(set_attr "type" "dpcmp")]) - -;; Store condition code insns. The compare insns set a register -;; rather than cc0 and record that register for use here. See above -;; for the special treatment of cmpsi with a constant operand. - -;; @@ For the m88110, use fcmpu for bxx sxx inequality comparisons. - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (EQ, SImode);") - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (NE, SImode);") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (GT, SImode);") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (GTU, SImode);") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (LT, SImode);") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (LTU, SImode);") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (GE, SImode);") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (GEU, SImode);") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (LE, SImode);") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "") - (match_dup 1))] - "" - "operands[1] = emit_test (LEU, SImode);") - -;; The actual set condition code instruction. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "relop" - [(match_operand:CC 2 "register_operand" "r") - (const_int 0)]))] - "" - "ext %0,%2,1<%C1>" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "even_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)]))] - "" - "ext %0,%2,1<%C1>" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)])))] - "" - "ext %0,%2,1<%!%C1>" - [(set_attr "type" "bit")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)])) - (clobber (match_operand:SI 3 "register_operand" "=r"))] - "" - [(set (match_dup 3) (not:SI (match_op_dup 1 [(match_dup 2) (const_int 0)]))) - (set (match_dup 0) (not:SI (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)])) - (clobber (match_scratch:SI 3 "=r"))] - "" - "#") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI - (match_operator:SI 1 "relop" - [(match_operand:CC 2 "register_operand" "r") - (const_int 0)])))] - "" - "extu %0,%2,1<%C1>" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI - (match_operator:SI 1 "even_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)])))] - "" - "extu %0,%2,1<%C1>" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI - (not:SI (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)]))))] - "" - "extu %0,%2,1<%!%C1>" - [(set_attr "type" "bit")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)]))) - (clobber (match_operand:SI 3 "register_operand" "=r"))] - "" - [(set (match_dup 3) (neg:SI (not:SI (match_op_dup 1 [(match_dup 2) - (const_int 0)])))) - (set (match_dup 0) (xor:SI (match_dup 3) (const_int 1)))] - "") - -(define_insn - "" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operator:SI 1 "odd_relop" - [(match_operand:CCEVEN 2 "register_operand" "r") - (const_int 0)]))) - (clobber (match_scratch:SI 3 "=r"))] - "" - "#") - - - - -;; Conditional branch insns. The compare insns set a register -;; rather than cc0 and record that register for use here. See above -;; for the special case of cmpsi with a constant operand. - -(define_expand "bcnd" - [(set (pc) - (if_then_else (match_operand 0 "" "") - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "if (m88k_compare_reg) abort ();") - -(define_expand "bxx" - [(set (pc) - (if_then_else (match_operand 0 "" "") - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) abort ();") - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (EQ, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (NE, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (GT, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_jump_insn (gen_bxx (emit_test (GTU, VOIDmode), operands[0])); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (LT, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_jump_insn (gen_bxx (emit_test (LTU, VOIDmode), operands[0])); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (GE, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_jump_insn (gen_bxx (emit_test (GEU, VOIDmode), operands[0])); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_bcnd (LE, operands[0]); - DONE; - } - operands[1] = m88k_compare_reg;") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "if (m88k_compare_reg == 0) - { - emit_jump_insn (gen_bxx (emit_test (LEU, VOIDmode), operands[0])); - DONE; - } - operands[1] = m88k_compare_reg;") - -;; The actual conditional branch instruction (both directions). This -;; uses two unusual template patterns, %Rx and %Px. %Rx is a prefix code -;; for the immediately following condition and reverses the condition iff -;; operand `x' is a LABEL_REF. %Px does nothing if `x' is PC and outputs -;; the operand if `x' is a LABEL_REF. - -(define_insn "" - [(set (pc) (if_then_else - (match_operator 0 "relop" - [(match_operand:CC 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "* -{ - if (mostly_false_jump (insn, operands[0])) - return \"bb0%. %R2%C0,%1,%P2%P3\"; - else - return \"bb1%. %R3%C0,%1,%P2%P3\"; -}" - [(set_attr "type" "branch")]) - -;; -;; Here branch prediction is sacrificed. To get it back, you need -;; - CCODD (CC mode where the ODD bits are valid) -;; - several define_split that can apply De Morgan's Law. -;; - transformations between CCEVEN and CCODD modes. -;; - -(define_insn "" - [(set (pc) (if_then_else - (match_operator 0 "even_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2%. %C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) (if_then_else - (match_operator 0 "odd_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3%. %!%C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -;; Branch conditional on scc values. These arise from manipulations on -;; compare words above. -;; Are these really used ? - -(define_insn "" - [(set (pc) - (if_then_else - (ne (match_operator 0 "relop" - [(match_operand:CC 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2 %C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (match_operator 0 "even_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2 %C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (match_operator 0 "odd_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3 %!%C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (match_operator 0 "relop" - [(match_operand:CC 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3 %C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (match_operator 0 "even_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L3 %C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (match_operator 0 "odd_relop" - [(match_operand:CCEVEN 1 "register_operand" "r") - (const_int 0)]) - (const_int 0)) - (match_operand 2 "pc_or_label_ref" "") - (match_operand 3 "pc_or_label_ref" "")))] - "" - "bb%L2 %!%C0,%1,%P2%P3" - [(set_attr "type" "branch")]) - -(define_insn "locate1" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (unspec:SI [(label_ref (match_operand 1 "" ""))] 0)))] - "" - "or.u %0,%#r0,%#hi16(%1#abdiff)") - -(define_insn "locate2" - [(parallel [(set (reg:SI 1) (pc)) - (set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_dup 0) - (unspec:SI - [(label_ref (match_operand 1 "" ""))] 0)))])] - "" - "bsr.n %1\;or %0,%0,%#lo16(%1#abdiff)\\n%1:" - [(set_attr "length" "2")]) - -;; SImode move instructions - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SImode, 0)) - DONE; -}") - -(define_expand "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "general_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, SImode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,x,x,x,m") - (match_operand:SI 1 "move_operand" "rI,m,rO,J,M,x,r,x,m,x"))] - "(register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || operands[1] == const0_rtx)" - "@ - or %0,%#r0,%1 - %V1ld\\t %0,%1 - %v0st\\t %r1,%0 - subu %0,%#r0,%n1 - set %0,%#r0,%s1 - mov.s %0,%1 - mov.s %0,%1 - mov %0,%1 - %V1ld\\t %0,%1 - %v0st\\t %1,%0" - [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (match_operand:SI 1 "arith32_operand" "rI,J,L,M,n"))] - "" - "@ - or %0,%#r0,%1 - subu %0,%#r0,%n1 - or.u %0,%#r0,%X1 - set %0,%#r0,%s1 - or.u %0,%#r0,%X1\;or %0,%0,%x1" - [(set_attr "type" "arith,arith,arith,bit,marith")]) - -;; @@ Why the constraint "in"? Doesn't `i' include `n'? -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")))] - "" - "or %0,%1,%#lo16(%g2)") - -;; For PIC, symbol_refs are put inside unspec so that the optimizer won't -;; confuse them with real addresses. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] - "" - "or %0,%1,%#lo16(%g2)" - ;; Need to set length for this arith insn because operand2 - ;; is not an "arith_operand". - [(set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (match_operand 1 "" "")))] - "" - "or.u %0,%#r0,%#hi16(%g1)") - -;; For PIC, symbol_refs are put inside unspec so that the optimizer won't -;; confuse them with real addresses. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] - "" - "or.u %0,%#r0,%#hi16(%g1)" - ;; Need to set length for this arith insn because operand2 - ;; is not an arith_operand. - [(set_attr "length" "1")]) - -;; HImode move instructions - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HImode, 0)) - DONE; -}") - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") - (match_operand:HI 1 "move_operand" "rP,m,rO,N"))] - "(register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || operands[1] == const0_rtx)" - "@ - or %0,%#r0,%h1 - %V1ld.hu\\t %0,%1 - %v0st.h\\t %r1,%0 - subu %0,%#r0,%H1" - [(set_attr "type" "arith,load,store,arith")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (subreg:HI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")) 0))] - "!flag_pic" - "or %0,%1,%#lo16(%2)") - -;; QImode move instructions - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, QImode, 0)) - DONE; -}") - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r") - (match_operand:QI 1 "move_operand" "rP,m,rO,N"))] - "(register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || operands[1] == const0_rtx)" - "@ - or %0,%#r0,%q1 - %V1ld.bu\\t %0,%1 - %v0st.b\\t %r1,%0 - subu %r0,%#r0,%Q1" - [(set_attr "type" "arith,load,store,arith")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (subreg:QI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")) 0))] - "!flag_pic" - "or %0,%1,%#lo16(%2)") - -;; DImode move instructions - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DImode, 0)) - DONE; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,x") - (const_int 0))] - "" - "@ - or %0,%#r0,0\;or %d0,%#r0,0 - mov %0,%#x0" - [(set_attr "type" "marith,mov")]) - -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,x,x,x,m") - (match_operand:DI 1 "nonimmediate_operand" "r,m,r,x,r,x,m,x"))] - "" - "@ - or %0,%#r0,%1\;or %d0,%#r0,%d1 - %V1ld.d\\t %0,%1 - %v0st.d\\t %1,%0 - mov.d %0,%1 - mov.d %0,%1 - mov %0,%1 - %V1ld.d\\t %0,%1 - %v0st.d\\t %1,%0" - [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (subreg:DI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")) 0))] - "!flag_pic" - "or %0,%1,%#lo16(%2)") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "immediate_operand" "n"))] - "" - "* return output_load_const_dimode (operands);" - [(set_attr "type" "marith") - (set_attr "length" "4")]) ; length is 2, 3 or 4. - -;; DFmode move instructions - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DFmode, 0)) - DONE; -}") - -(define_split - [(set (match_operand:DF 0 "register_operand" "=r") - (match_operand:DF 1 "register_operand" "r"))] - "reload_completed - && GET_CODE (operands[0]) == REG && !XRF_REGNO_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && !XRF_REGNO_P (REGNO (operands[1]))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ operands[2] = operand_subword (operands[0], 0, 0, DFmode); - operands[3] = operand_subword (operands[1], 0, 0, DFmode); - operands[4] = operand_subword (operands[0], 1, 0, DFmode); - operands[5] = operand_subword (operands[1], 1, 0, DFmode); }") - -;; @@ This pattern is incomplete and doesn't appear necessary. -;; -;; This pattern forces (set (reg:DF ...) (const_double ...)) -;; to be reloaded by putting the constant into memory. -;; It must come before the more general movdf pattern. - -;(define_insn "" -; [(set (match_operand:DF 0 "general_operand" "=r,o") -; (match_operand:DF 1 "" "G,G"))] -; "GET_CODE (operands[1]) == CONST_DOUBLE" -; "* -;{ -; switch (which_alternative) -; { -; case 0: -; return \"or %0,%#r0,0\;or %d0,%#r0,0\"; -; case 1: -; operands[1] = adj_offsettable_operand (operands[0], 4); -; return \"%v0st\\t %#r0,%0\;st %#r0,%1\"; -; } -;}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (const_int 0))] - "" - "@ - or %0,%#r0,0\;or %d0,%#r0,0 - mov %0,%#x0" - [(set_attr "type" "marith,mov")]) - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m") - (match_operand:DF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))] - "" - "@ - or %0,%#r0,%1\;or %d0,%#r0,%d1 - %V1ld.d\\t %0,%1 - %v0st.d\\t %1,%0 - mov.d %0,%1 - mov.d %0,%1 - mov %0,%1 - %V1ld.d\\t %0,%1 - %v0st.d\\t %1,%0" - [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (subreg:DF (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")) 0))] - "!flag_pic" - "or %0,%1,%#lo16(%2)") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (match_operand:DF 1 "immediate_operand" "F"))] - "" - "* return output_load_const_double (operands);" - [(set_attr "type" "marith") - (set_attr "length" "4")]) ; length is 2, 3, or 4. - -;; SFmode move instructions - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SFmode, 0)) - DONE; -}") - -;; @@ What happens to fconst0_rtx? -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (const_int 0))] - "" - "@ - or %0,%#r0,0 - mov %0,%#x0" - [(set_attr "type" "arith,mov")]) - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m") - (match_operand:SF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))] - "" - "@ - or %0,%#r0,%1 - %V1ld\\t %0,%1 - %v0st\\t %r1,%0 - mov.s %0,%1 - mov.s %0,%1 - mov %0,%1 - %V1ld\\t %0,%1 - %v0st\\t %r1,%0" - [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (subreg:SF (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "in")) 0))] - "!flag_pic" - "or %0,%1,%#lo16(%2)") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (match_operand:SF 1 "immediate_operand" "F"))] - "operands[1] != const0_rtx" - "* return output_load_const_float (operands);" - [(set_attr "type" "marith")]) ; length is 1 or 2. - -;; String/block move insn. See m88k.c for details. - -(define_expand "movstrsi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) - (mem:BLK (match_operand:BLK 1 "" ""))) - (use (match_operand:SI 2 "arith32_operand" "")) - (use (match_operand:SI 3 "immediate_operand" ""))])] - "" - " -{ - rtx dest_mem = operands[0]; - rtx src_mem = operands[1]; - operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); - operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); - expand_block_move (dest_mem, src_mem, operands); - DONE; -}") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (match_operand:BLK 1 "memory_operand" "m"))] - "" - "%V1ld.bu\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:BLK 1 "memory_operand" "m"))] - "" - "%V1ld.hu\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:BLK 1 "memory_operand" "m"))] - "" - "%V1ld\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:BLK 1 "memory_operand" "m"))] - "" - "%V1ld.d\\t %0,%1" - [(set_attr "type" "loadd")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:QI 1 "register_operand" "r"))] - "" - "%v0st.b\\t %1,%0" - [(set_attr "type" "store")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:HI 1 "register_operand" "r"))] - "" - "%v0st.h\\t %1,%0" - [(set_attr "type" "store")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:SI 1 "register_operand" "r"))] - "" - "%v0st\\t %1,%0" - [(set_attr "type" "store")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:DI 1 "register_operand" "r"))] - "" - "%v0st.d\\t %1,%0" - [(set_attr "type" "store")]) - -;; Call a non-looping block move library function (e.g. __movstrSI96x64). -;; operand 0 is the function name -;; operand 1 is the destination pointer -;; operand 2 is the source pointer -;; operand 3 is the offset for the source and destination pointers -;; operand 4 is the first value to be loaded -;; operand 5 is the register to hold the value (r4 or r5) - -(define_expand "call_block_move" - [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "immediate_operand" ""))) - (set (match_operand 5 "register_operand" "") - (match_operand 4 "memory_operand" "")) - (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "") - (match_dup 3))) - (use (reg:SI 2)) - (use (reg:SI 3)) - (use (match_dup 5)) - (parallel [(set (reg:DI 2) - (call (mem:SI (match_operand 0 "" "")) - (const_int 0))) - (clobber (reg:SI 1))])] - "" - "") - -;; Call an SImode looping block move library function (e.g. __movstrSI64n68). -;; operands 0-5 as in the non-looping interface -;; operand 6 is the loop count - -(define_expand "call_movstrsi_loop" - [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "immediate_operand" ""))) - (set (match_operand:SI 5 "register_operand" "") - (match_operand 4 "memory_operand" "")) - (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "") - (match_dup 3))) - (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "")) - (use (reg:SI 2)) - (use (reg:SI 3)) - (use (match_dup 5)) - (use (reg:SI 6)) - (parallel [(set (reg:DI 2) - (call (mem:SI (match_operand 0 "" "")) - (const_int 0))) - (clobber (reg:SI 1))])] - "" - "") - -;;- zero extension instructions - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (zero_extend:SI (match_operand:HI 1 "move_operand" "!r,n,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - mask %0,%1,0xffff - or %0,%#r0,%h1 - %V1ld.hu\\t %0,%1" - [(set_attr "type" "arith,arith,load")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (zero_extend:HI (match_operand:QI 1 "move_operand" "r,n,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - mask %0,%1,0xff - or %0,%#r0,%q1 - %V1ld.bu\\t %0,%1" - [(set_attr "type" "arith,arith,load")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - { - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (ZERO_EXTEND, SImode, operands[1]))); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (zero_extend:SI (match_operand:QI 1 "move_operand" "r,n,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - mask %0,%1,0xff - or %0,%#r0,%q1 - %V1ld.bu\\t %0,%1" - [(set_attr "type" "arith,arith,load")]) - -;;- sign extension instructions - -(define_expand "extendsidi2" - [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1) - (match_operand:SI 1 "general_operand" "g")) - (set (subreg:SI (match_dup 0) 0) - (ashiftrt:SI (subreg:SI (match_dup 0) 1) - (const_int 31)))] - "" - "") - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (sign_extend:SI (match_operand:HI 1 "move_operand" "!r,P,N,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - ext %0,%1,16<0> - or %0,%#r0,%h1 - subu %0,%#r0,%H1 - %V1ld.h\\t %0,%1" - [(set_attr "type" "bit,arith,arith,load")]) - -(define_expand "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (sign_extend:HI (match_operand:QI 1 "move_operand" "!r,P,N,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - ext %0,%1,8<0> - or %0,%#r0,%q1 - subu %0,%#r0,%Q1 - %V1ld.b\\t %0,%1" - [(set_attr "type" "bit,arith,arith,load")]) - -(define_expand "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && symbolic_address_p (XEXP (operands[1], 0))) - operands[1] - = legitimize_address (flag_pic, operands[1], 0, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (sign_extend:SI (match_operand:QI 1 "move_operand" "!r,P,N,m")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - ext %0,%1,8<0> - or %0,%#r0,%q1 - subu %0,%#r0,%Q1 - %V1ld.b\\t %0,%1" - [(set_attr "type" "bit,arith,arith,load")]) - -;; Conversions between float and double. - -;; The fadd instruction does not conform to IEEE 754 when used to -;; convert between float and double. In particular, the sign of -0 is -;; not preserved. Interestingly, fsub does conform. - -(define_expand "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=r") - (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] - "" - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] - "! TARGET_88110" - "fsub.dss %0,%1,%#r0" - [(set_attr "type" "spadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")))] - "TARGET_88110" - "fcvt.ds %0,%1" - [(set_attr "type" "spadd")]) - -(define_expand "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] - "" - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] - "! TARGET_88110" - "fsub.sds %0,%1,%#r0" - [(set_attr "type" "dpadd")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (float_truncate:SF (match_operand:DF 1 "register_operand" "r,x")))] - "TARGET_88110" - "fcvt.sd %0,%1" - [(set_attr "type" "dpadd")]) - -;; Conversions between floating point and integer - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (float:DF (match_operand:SI 1 "register_operand" "r,r")))] - "" - "flt.ds %0,%1" - [(set_attr "type" "spadd,dpadd")]) - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (float:SF (match_operand:SI 1 "register_operand" "r,r")))] - "" - "flt.ss %0,%1" - [(set_attr "type" "spadd,spadd")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (fix:SI (match_operand:DF 1 "register_operand" "r,x")))] - "" - "trnc.sd %0,%1" - [(set_attr "type" "dpadd,dpadd")]) - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (fix:SI (match_operand:SF 1 "register_operand" "r,x")))] - "" - "trnc.ss %0,%1" - [(set_attr "type" "spadd,dpadd")]) - - -;;- arithmetic instructions -;;- add instructions - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operand:SI 1 "add_operand" "%r,r") - (match_operand:SI 2 "add_operand" "rI,J")))] - "" - "@ - addu %0,%1,%2 - subu %0,%1,%n2") - -;; patterns for mixed mode floating point. -;; Do not define patterns that utilize mixed mode arithmetic that result -;; in narrowing the precision, because it loses accuracy, since the standard -;; requires double rounding, whereas the 88000 instruction only rounds once. - -(define_expand "adddf3" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (plus:DF (match_operand:DF 1 "general_operand" "%r,x") - (match_operand:DF 2 "general_operand" "r,x")))] - "" - " -{ - operands[1] = legitimize_operand (operands[1], DFmode); - operands[2] = legitimize_operand (operands[2], DFmode); -}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fadd.dss %0,%1,%2" - [(set_attr "type" "spadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (plus:DF (match_operand:DF 1 "register_operand" "r,x") - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fadd.dds %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fadd.dsd %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (plus:DF (match_operand:DF 1 "register_operand" "%r,x") - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fadd.ddd %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (plus:SF (match_operand:SF 1 "register_operand" "%r,x") - (match_operand:SF 2 "register_operand" "r,x")))] - "" - "fadd.sss %0,%1,%2" - [(set_attr "type" "spadd")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (match_operand:DI 1 "register_operand" "r") - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r")))) - (clobber (reg:CC 0))] - "" - "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0" - [(set_attr "type" "marith")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r"))) - (clobber (reg:CC 0))] - "" - "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2" - [(set_attr "type" "marith")]) - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r"))) - (clobber (reg:CC 0))] - "" - "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2" - [(set_attr "type" "marith")]) - -;; Add with carry insns. - -(define_insn "" - [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") - (match_operand:SI 2 "reg_or_0_operand" "rO"))) - (set (reg:CC 0) - (unspec:CC [(match_dup 1) (match_dup 2)] 0))])] - "" - "addu.co %r0,%r1,%r2") - -(define_insn "" - [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO") - (match_operand:SI 1 "reg_or_0_operand" "rO")] - 0))] - "" - "addu.co %#r0,%r0,%r1") - -(define_insn "" - [(set (match_operand:SI 0 "reg_or_0_operand" "=r") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") - (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO") - (reg:CC 0)] 0)))] - "" - "addu.ci %r0,%r1,%r2") - -;;- subtract instructions - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith32_operand" "rI")))] - "" - "subu %0,%1,%2") - -;; patterns for mixed mode floating point -;; Do not define patterns that utilize mixed mode arithmetic that result -;; in narrowing the precision, because it loses accuracy, since the standard -;; requires double rounding, whereas the 88000 instruction only rounds once. - -(define_expand "subdf3" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (minus:DF (match_operand:DF 1 "general_operand" "r,x") - (match_operand:DF 2 "general_operand" "r,x")))] - "" - " -{ - operands[1] = legitimize_operand (operands[1], DFmode); - operands[2] = legitimize_operand (operands[2], DFmode); -}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fsub.dss %0,%1,%2" - [(set_attr "type" "spadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (minus:DF (match_operand:DF 1 "register_operand" "r,x") - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fsub.dds %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fsub.dsd %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (minus:DF (match_operand:DF 1 "register_operand" "r,x") - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fsub.ddd %0,%1,%2" - [(set_attr "type" "dpadd")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (minus:SF (match_operand:SF 1 "register_operand" "r,x") - (match_operand:SF 2 "register_operand" "r,x")))] - "" - "fsub.sss %0,%1,%2" - [(set_attr "type" "spadd")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "register_operand" "r") - (zero_extend:DI - (match_operand:SI 2 "register_operand" "r")))) - (clobber (reg:CC 0))] - "" - "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0" - [(set_attr "type" "marith")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r"))) - (clobber (reg:CC 0))] - "" - "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2" - [(set_attr "type" "marith")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "register_operand" "r"))) - (clobber (reg:CC 0))] - "" - "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2" - [(set_attr "type" "marith")]) - -;; Subtract with carry insns. - -(define_insn "" - [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") - (match_operand:SI 2 "reg_or_0_operand" "rO"))) - (set (reg:CC 0) - (unspec:CC [(match_dup 1) (match_dup 2)] 1))])] - "" - "subu.co %r0,%r1,%r2") - -(define_insn "" - [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO") - (match_operand:SI 1 "reg_or_0_operand" "rO")] - 1))] - "" - "subu.co %#r0,%r0,%r1") - -(define_insn "" - [(set (match_operand:SI 0 "reg_or_0_operand" "=r") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") - (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO") - (reg:CC 0)] 1)))] - "" - "subu.ci %r0,%r1,%r2") - -;;- multiply instructions -;; -;; There is an unfounded silicon errata for E.1 requiring that an -;; immediate constant value in div/divu/mul instructions be less than -;; 0x800. This is no longer provided for. - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (match_operand:SI 1 "arith32_operand" "%r") - (match_operand:SI 2 "arith32_operand" "rI")))] - "" - "mul %0,%1,%2" - [(set_attr "type" "imul")]) - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] - "TARGET_88110" - "mulu.d %0,%1,%2" - [(set_attr "type" "imul")]) - -;; patterns for mixed mode floating point -;; Do not define patterns that utilize mixed mode arithmetic that result -;; in narrowing the precision, because it loses accuracy, since the standard -;; requires double rounding, whereas the 88000 instruction only rounds once. - -(define_expand "muldf3" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (mult:DF (match_operand:DF 1 "general_operand" "%r,x") - (match_operand:DF 2 "general_operand" "r,x")))] - "" - " -{ - operands[1] = legitimize_operand (operands[1], DFmode); - operands[2] = legitimize_operand (operands[2], DFmode); -}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fmul.dss %0,%1,%2" - [(set_attr "type" "spmul")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (mult:DF (match_operand:DF 1 "register_operand" "r,x") - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fmul.dds %0,%1,%2" - [(set_attr "type" "spmul")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fmul.dsd %0,%1,%2" - [(set_attr "type" "spmul")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (mult:DF (match_operand:DF 1 "register_operand" "%r,x") - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fmul.ddd %0,%1,%2" - [(set_attr "type" "dpmul")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (mult:SF (match_operand:SF 1 "register_operand" "%r,x") - (match_operand:SF 2 "register_operand" "r,x")))] - "" - "fmul.sss %0,%1,%2" - [(set_attr "type" "spmul")]) - -;;- divide instructions -;; -;; The 88k div and divu instructions don't reliably trap on -;; divide-by-zero. A trap to vector 503 asserts divide-by-zero. The -;; general scheme for doing divide is to do a 4-way split based on the -;; sign of the two operand and do the appropriate negates. -;; -;; The conditional trap instruction is not used as this serializes the -;; processor. Instead a conditional branch and an unconditional trap -;; are used, but after the divu. Since the divu takes up to 38 cycles, -;; the conditional branch is essentially free. -;; -;; Two target options control how divide is done. One options selects -;; whether to do the branch and negate scheme instead of using the div -;; instruction; the other option selects whether to explicitly check -;; for divide-by-zero or take your chances. If the div instruction is -;; used, the O/S must complete the operation if the operands are -;; negative. The O/S will signal an overflow condition if the most -;; negative number (-2147483648) is divided by negative 1. -;; -;; There is an unfounded silicon errata for E.1 requiring that an -;; immediate constant value in div/divu/mul instructions be less than -;; 0x800. This is no longer provided for. - -;; Division by 0 trap -(define_insn "trap_divide_by_zero" - [(trap_if (const_int 1) (const_int 503))] - "" - "tb0 0,%#r0,503" - [(set_attr "type" "weird")]) - -;; Conditional division by 0 trap. -(define_expand "tcnd_divide_by_zero" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "register_operand" "") - (const_int 0)) - (pc) - (match_operand 1 "" ""))) - (trap_if (const_int 1) (const_int 503))] - "" - " -{ - emit_insn (gen_cmpsi (operands[0], const0_rtx)); - emit_jump_insn (gen_bne (operands[1])); - emit_insn (gen_trap_divide_by_zero ()); - DONE; -}") - -(define_expand "divsi3" - [(set (match_operand:SI 0 "register_operand" "") - (div:SI (match_operand:SI 1 "arith32_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx join_label; - - /* @@ This needs to be reworked. Torbjorn Granlund has suggested making - it a runtime (perhaps quite special). */ - - if (GET_CODE (op1) == CONST_INT) - op1 = force_reg (SImode, op1); - - else if (GET_CODE (op2) == CONST_INT - && ! SMALL_INT (operands[2])) - op2 = force_reg (SImode, op2); - - if (op2 == const0_rtx) - { - emit_insn (gen_trap_divide_by_zero ()); - emit_insn (gen_dummy (op0)); - DONE; - } - - if (TARGET_USE_DIV) - { - emit_move_insn (op0, gen_rtx (DIV, SImode, op1, op2)); - if (TARGET_CHECK_ZERO_DIV && GET_CODE (op2) != CONST_INT) - { - rtx label = gen_label_rtx (); - emit_insn (gen_tcnd_divide_by_zero (op2, label)); - emit_label (label); - emit_insn (gen_dummy (op0)); - } - DONE; - } - - join_label = gen_label_rtx (); - if (GET_CODE (op1) == CONST_INT) - { - int neg = FALSE; - rtx neg_op2 = gen_reg_rtx (SImode); - rtx label1 = gen_label_rtx (); - - if (INTVAL (op1) < 0) - { - neg = TRUE; - op1 = GEN_INT (-INTVAL (op1)); - } - op1 = force_reg (SImode, op1); - - emit_insn (gen_negsi2 (neg_op2, op2)); - emit_insn (gen_cmpsi (op2, const0_rtx)); - emit_jump_insn (gen_bgt (label1)); - /* constant / 0-or-negative */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2)); - if (!neg) - emit_insn (gen_negsi2 (op0, op0)); - - if (TARGET_CHECK_ZERO_DIV) - emit_insn (gen_tcnd_divide_by_zero (op2, join_label)); - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - - emit_label (label1); /* constant / positive */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); - if (neg) - emit_insn (gen_negsi2 (op0, op0)); - } - - else if (GET_CODE (op2) == CONST_INT) - { - int neg = FALSE; - rtx neg_op1 = gen_reg_rtx (SImode); - rtx label1 = gen_label_rtx (); - - if (INTVAL (op2) < 0) - { - neg = TRUE; - op2 = GEN_INT (-INTVAL (op2)); - } - else if (! SMALL_INT (operands[2])) - op2 = force_reg (SImode, op2); - - emit_insn (gen_negsi2 (neg_op1, op1)); - emit_insn (gen_cmpsi (op1, const0_rtx)); - emit_jump_insn (gen_bge (label1)); - /* 0-or-negative / constant */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2)); - if (!neg) - emit_insn (gen_negsi2 (op0, op0)); - - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - - emit_label (label1); /* positive / constant */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); - if (neg) - emit_insn (gen_negsi2 (op0, op0)); - } - - else - { - rtx neg_op1 = gen_reg_rtx (SImode); - rtx neg_op2 = gen_reg_rtx (SImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - rtx label3 = gen_label_rtx (); - rtx label4; - - emit_insn (gen_negsi2 (neg_op2, op2)); - emit_insn (gen_cmpsi (op2, const0_rtx)); - emit_jump_insn (gen_bgt (label1)); - - emit_insn (gen_negsi2 (neg_op1, op1)); - emit_insn (gen_cmpsi (op1, const0_rtx)); - emit_jump_insn (gen_bge (label2)); - /* negative / negative-or-0 */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, neg_op2)); - - if (TARGET_CHECK_ZERO_DIV) - { - label4 = gen_label_rtx (); - emit_insn (gen_cmpsi (op2, const0_rtx)); - emit_jump_insn (gen_bne (join_label)); - emit_label (label4); - emit_insn (gen_trap_divide_by_zero ()); - } - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - - emit_label (label2); /* pos.-or-0 / neg.-or-0 */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2)); - - if (TARGET_CHECK_ZERO_DIV) - { - emit_insn (gen_cmpsi (op2, const0_rtx)); - emit_jump_insn (gen_beq (label4)); - } - - emit_insn (gen_negsi2 (op0, op0)); - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - - emit_label (label1); - emit_insn (gen_negsi2 (neg_op1, op1)); - emit_insn (gen_cmpsi (op1, const0_rtx)); - emit_jump_insn (gen_bge (label3)); - /* negative / positive */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2)); - emit_insn (gen_negsi2 (op0, op0)); - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - - emit_label (label3); /* positive-or-0 / positive */ - emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); - } - - emit_label (join_label); - - emit_insn (gen_dummy (op0)); - DONE; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (div:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith_operand" "rI")))] - "" - "div %0,%1,%2" - [(set_attr "type" "idiv")]) - -(define_expand "udivsi3" - [(set (match_operand:SI 0 "register_operand" "") - (udiv:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - rtx op2 = operands[2]; - - if (op2 == const0_rtx) - { - emit_insn (gen_trap_divide_by_zero ()); - emit_insn (gen_dummy (operands[0])); - DONE; - } - else if (GET_CODE (op2) != CONST_INT && TARGET_CHECK_ZERO_DIV) - { - rtx label = gen_label_rtx (); - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (UDIV, SImode, operands[1], op2))); - emit_insn (gen_tcnd_divide_by_zero (op2, label)); - emit_label (label); - emit_insn (gen_dummy (operands[0])); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (udiv:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith32_operand" "rI")))] - "operands[2] != const0_rtx" - "divu %0,%1,%2" - [(set_attr "type" "idiv")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (udiv:SI (match_operand:SI 1 "register_operand" "r") - (const_int 0)))] - "" - "tb0 0,%#r0,503" - [(set_attr "type" "weird")]) - -;; patterns for mixed mode floating point. -;; Do not define patterns that utilize mixed mode arithmetic that result -;; in narrowing the precision, because it loses accuracy, since the standard -;; requires double rounding, whereas the 88000 instruction only rounds once. - -(define_expand "divdf3" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (div:DF (match_operand:DF 1 "general_operand" "r,x") - (match_operand:DF 2 "general_operand" "r,x")))] - "" - " -{ - operands[1] = legitimize_operand (operands[1], DFmode); - if (real_power_of_2_operand (operands[2])) - { - union real_extract u; - bcopy (&CONST_DOUBLE_LOW (operands[2]), &u, sizeof u); - emit_insn (gen_muldf3 (operands[0], operands[1], - CONST_DOUBLE_FROM_REAL_VALUE (1.0/u.d, DFmode))); - DONE; - } - else if (! register_operand (operands[2], DFmode)) - operands[2] = force_reg (DFmode, operands[2]); -}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fdiv.dss %0,%1,%2" - [(set_attr "type" "dpdiv")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (div:DF (match_operand:DF 1 "register_operand" "r,x") - (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] - "" - "fdiv.dds %0,%1,%2" - [(set_attr "type" "dpdiv")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fdiv.dsd %0,%1,%2" - [(set_attr "type" "dpdiv")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (div:SF (match_operand:SF 1 "register_operand" "r,x") - (match_operand:SF 2 "register_operand" "r,x")))] - "" - "fdiv.sss %0,%1,%2" - [(set_attr "type" "spdiv")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,x") - (div:DF (match_operand:DF 1 "register_operand" "r,x") - (match_operand:DF 2 "register_operand" "r,x")))] - "" - "fdiv.ddd %0,%1,%2" - [(set_attr "type" "dpdiv")]) - -;; - remainder instructions, don't define, since the hardware doesn't have any -;; direct support, and GNU can synthesis them out of div/mul just fine. - -;;- load effective address, must come after add, so that we favor using -;; addu reg,reg,reg instead of: lda reg,reg,reg (addu doesn't require -;; the data unit), and also future 88k chips might not support unscaled -;; lda instructions. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "address_operand" "p"))] - "m88k_gp_threshold > 0 && symbolic_address_p (operands[1])" - "addu %0,%a1") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:HI 1 "address_operand" "p"))] - "" - "lda.h %0,%a1" - [(set_attr "type" "loada")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "address_operand" "p"))] - "" - "lda %0,%a1" - [(set_attr "type" "loada")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:DI 1 "address_operand" "p"))] - "" - "lda.d %0,%a1" - [(set_attr "type" "loada")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SF 1 "address_operand" "p"))] - "" - "lda %0,%a1" - [(set_attr "type" "loada")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:DF 1 "address_operand" "p"))] - "" - "lda.d %0,%a1" - [(set_attr "type" "loada")]) - -;;- and instructions (with complement also) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "and.c %0,%2,%1") - -;; If the operation is being performed on a 32-bit constant such that -;; it cannot be done in one insn, do it in two. We may lose a bit on -;; CSE in pathological cases, but it seems better doing it this way. - -(define_expand "andsi3" - [(set (match_operand:SI 0 "register_operand" "") - (and:SI (match_operand:SI 1 "arith32_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int value = INTVAL (operands[2]); - - if (! (SMALL_INTVAL (value) - || (value & 0xffff0000) == 0xffff0000 - || (value & 0xffff) == 0xffff - || (value & 0xffff) == 0 - || integer_ok_for_set (~value))) - { - emit_insn (gen_andsi3 (operands[0], operands[1], - GEN_INT (value | 0xffff))); - operands[1] = operands[0]; - operands[2] = GEN_INT (value | 0xffff0000); - } - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (and:SI (match_operand:SI 1 "arith32_operand" "%r,r") - (match_operand:SI 2 "arith32_operand" "rIJL,rn")))] - "" - "* return output_and (operands);" - [(set_attr "type" "arith,marith")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r")))] - "" - "and.c %d0,%d2,%d1\;and.c %0,%2,%1" - [(set_attr "type" "marith")]) - -(define_insn "anddi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (match_operand:DI 1 "arith64_operand" "%r") - (match_operand:DI 2 "arith64_operand" "rn")))] - "" - "* -{ - rtx xoperands[10]; - - xoperands[0] = operand_subword (operands[0], 1, 0, DImode); - xoperands[1] = operand_subword (operands[1], 1, 0, DImode); - xoperands[2] = operand_subword (operands[2], 1, 0, DImode); - - output_asm_insn (output_and (xoperands), xoperands); - - operands[0] = operand_subword (operands[0], 0, 0, DImode); - operands[1] = operand_subword (operands[1], 0, 0, DImode); - operands[2] = operand_subword (operands[2], 0, 0, DImode); - - return output_and (operands); -}" - [(set_attr "type" "marith") - (set_attr "length" "4")]) ; length is 2, 3, or 4. - -;;- Bit set (inclusive or) instructions (with complement also) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "or.c %0,%2,%1") - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ior:SI (match_operand:SI 1 "arith32_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int value = INTVAL (operands[2]); - - if (! (SMALL_INTVAL (value) - || (value & 0xffff) == 0 - || integer_ok_for_set (value))) - { - emit_insn (gen_iorsi3 (operands[0], operands[1], - GEN_INT (value & 0xffff0000))); - operands[1] = operands[0]; - operands[2] = GEN_INT (value & 0xffff); - } - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (ior:SI (match_operand:SI 1 "arith32_operand" "%r,r,r,r") - (match_operand:SI 2 "arith32_operand" "rI,L,M,n")))] - "" - "@ - or %0,%1,%2 - or.u %0,%1,%X2 - set %0,%1,%s2 - or.u %0,%1,%X2\;or %0,%0,%x2" - [(set_attr "type" "arith,arith,bit,marith")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r")))] - "" - "or.c %d0,%d2,%d1\;or.c %0,%2,%1" - [(set_attr "type" "marith")]) - -(define_insn "iordi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (match_operand:DI 1 "arith64_operand" "%r") - (match_operand:DI 2 "arith64_operand" "rn")))] - "" - "* -{ - rtx xoperands[10]; - - xoperands[0] = operand_subword (operands[0], 1, 0, DImode); - xoperands[1] = operand_subword (operands[1], 1, 0, DImode); - xoperands[2] = operand_subword (operands[2], 1, 0, DImode); - - output_asm_insn (output_ior (xoperands), xoperands); - - operands[0] = operand_subword (operands[0], 0, 0, DImode); - operands[1] = operand_subword (operands[1], 0, 0, DImode); - operands[2] = operand_subword (operands[2], 0, 0, DImode); - - return output_ior (operands); -}" - [(set_attr "type" "marith") - (set_attr "length" "4")]) ; length is 2, 3, or 4. - -;;- xor instructions (with complement also) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r"))))] - "" - "xor.c %0,%1,%2") - -(define_expand "xorsi3" - [(set (match_operand:SI 0 "register_operand" "") - (xor:SI (match_operand:SI 1 "arith32_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int value = INTVAL (operands[2]); - - if (! (SMALL_INTVAL (value) - || (value & 0xffff) == 0)) - { - emit_insn (gen_xorsi3 (operands[0], operands[1], - GEN_INT (value & 0xffff0000))); - operands[1] = operands[0]; - operands[2] = GEN_INT (value & 0xffff); - } - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (xor:SI (match_operand:SI 1 "arith32_operand" "%r,r,r") - (match_operand:SI 2 "arith32_operand" "rI,L,n")))] - "" - "@ - xor %0,%1,%2 - xor.u %0,%1,%X2 - xor.u %0,%1,%X2\;xor %0,%0,%x2" - [(set_attr "type" "arith,arith,marith")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "register_operand" "r"))))] - "" - "xor.c %d0,%d1,%d2\;xor.c %0,%1,%2" - [(set_attr "type" "marith")]) - -(define_insn "xordi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (match_operand:DI 1 "arith64_operand" "%r") - (match_operand:DI 2 "arith64_operand" "rn")))] - "" - "* -{ - rtx xoperands[10]; - - xoperands[0] = operand_subword (operands[0], 1, 0, DImode); - xoperands[1] = operand_subword (operands[1], 1, 0, DImode); - xoperands[2] = operand_subword (operands[2], 1, 0, DImode); - - output_asm_insn (output_xor (xoperands), xoperands); - - operands[0] = operand_subword (operands[0], 0, 0, DImode); - operands[1] = operand_subword (operands[1], 0, 0, DImode); - operands[2] = operand_subword (operands[2], 0, 0, DImode); - - return output_xor (operands); -}" - [(set_attr "type" "marith") - (set_attr "length" "4")]) ; length is 2, 3, or 4. - -;;- ones complement instructions -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "xor.c %0,%1,%#r0") - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (match_operand:DI 1 "register_operand" "r")))] - "" - "xor.c %d0,%d1,%#r0\;xor.c %0,%1,%#r0" - [(set_attr "type" "marith")]) - -;; Optimized special cases of shifting. -;; Must precede the general case. - -;; @@ What about HImode shifted by 8? - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 24)))] - "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "%V1ld.b\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 24)))] - "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "%V1ld.bu\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 16)))] - "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "%V1ld.h\\t %0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 16)))] - "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "%V1ld.hu\\t %0,%1" - [(set_attr "type" "load")]) - -;;- arithmetic shift instructions. - -;; @@ Do the optimized patterns with -1 get used? Perhaps operand 1 should -;; be arith32_operand? - -;; Use tbnd to support TARGET_TRAP_LARGE_SHIFT. -(define_insn "tbnd" - [(trap_if (gtu (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "arith_operand" "rI")) - (const_int 7))] - "" - "tbnd %r0,%1" - [(set_attr "type" "weird")]) - -;; Just in case the optimizer decides to fold away the test. -(define_insn "" - [(trap_if (const_int 1) (const_int 7))] - "" - "tbnd %#r31,0" - [(set_attr "type" "weird")]) - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if ((unsigned) INTVAL (operands[2]) > 31) - { - if (TARGET_TRAP_LARGE_SHIFT) - emit_insn (gen_tbnd (force_reg (SImode, operands[2]), - GEN_INT (31))); - else - emit_move_insn (operands[0], const0_rtx); - DONE; - } - } - - else if (TARGET_TRAP_LARGE_SHIFT) - emit_insn (gen_tbnd (operands[2], GEN_INT (31))); - - else if (TARGET_HANDLE_LARGE_SHIFT) - { - rtx reg = gen_reg_rtx (SImode); - emit_insn (gen_cmpsi (operands[2], GEN_INT (31))); - emit_insn (gen_sleu (reg)); - emit_insn (gen_andsi3 (reg, operands[1], reg)); - operands[1] = reg; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "arith5_operand" "r,K")))] - "" - "@ - mak %0,%1,%2 - mak %0,%1,0<%2>" - [(set_attr "type" "bit")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if ((unsigned) INTVAL (operands[2]) > 31) - { - if (TARGET_TRAP_LARGE_SHIFT) - { - emit_insn (gen_tbnd (force_reg (SImode, operands[2]), - GEN_INT (31))); - DONE; - } - else - operands[2] = GEN_INT (31); - } - } - - else if (TARGET_TRAP_LARGE_SHIFT) - emit_insn (gen_tbnd (operands[2], GEN_INT (31))); - - else if (TARGET_HANDLE_LARGE_SHIFT) - { - rtx reg = gen_reg_rtx (SImode); - emit_insn (gen_cmpsi (operands[2], GEN_INT (31))); - emit_insn (gen_sgtu (reg)); - emit_insn (gen_iorsi3 (reg, operands[2], reg)); - operands[2] = reg; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "arith5_operand" "r,K")))] - "" - "@ - ext %0,%1,%2 - ext %0,%1,0<%2>" - [(set_attr "type" "bit")]) - -;;- logical shift instructions. Logical shift left becomes arithmetic -;; shift left. - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if ((unsigned) INTVAL (operands[2]) > 31) - { - if (TARGET_TRAP_LARGE_SHIFT) - emit_insn (gen_tbnd (force_reg (SImode, operands[2]), - GEN_INT (31))); - else - emit_move_insn (operands[0], const0_rtx); - DONE; - } - } - - else if (TARGET_TRAP_LARGE_SHIFT) - emit_insn (gen_tbnd (operands[2], GEN_INT (31))); - - else if (TARGET_HANDLE_LARGE_SHIFT) - { - rtx reg = gen_reg_rtx (SImode); - emit_insn (gen_cmpsi (operands[2], GEN_INT (31))); - emit_insn (gen_sleu (reg)); - emit_insn (gen_andsi3 (reg, operands[1], reg)); - operands[1] = reg; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "arith5_operand" "r,K")))] - "" - "@ - extu %0,%1,%2 - extu %0,%1,0<%2>" - [(set_attr "type" "bit")]) - -;;- rotate instructions - -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (rotatert:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT - && (unsigned) INTVAL (operands[2]) >= 32) - operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); - else - { - rtx op = gen_reg_rtx (SImode); - emit_insn (gen_negsi2 (op, operands[2])); - operands[2] = op; - } -}") - -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (rotatert:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith_operand" "rI")))] - "" - "rot %0,%1,%2" - [(set_attr "type" "bit")]) - -;; find first set. - -;; The ff1 instruction searches from the most significant bit while ffs -;; searches from the least significant bit. The bit index and treatment of -;; zero also differ. This amazing sequence was discovered using the GNU -;; Superoptimizer. - -(define_insn "ffssi2" - [(set (match_operand:SI 0 "register_operand" "=r,&r") - (ffs:SI (match_operand:SI 1 "register_operand" "0,r"))) - (clobber (reg:CC 0)) - (clobber (match_scratch:SI 2 "=r,X"))] - "" - "@ - subu.co %2,%#r0,%1\;and %2,%2,%1\;addu.ci %2,%2,%2\;ff1 %0,%2 - subu.co %0,%#r0,%1\;and %0,%0,%1\;addu.ci %0,%0,%0\;ff1 %0,%0" - [(set_attr "type" "marith") - (set_attr "length" "4")]) - -;; Bit field instructions. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 32) - (const_int 0)))] - "" - "or %0,%#r0,%1") - -(define_insn "extv" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "") - (match_operand:SI 3 "int5_operand" "")))] - "" - "* -{ - operands[4] = GEN_INT ((32 - INTVAL (operands[2])) - INTVAL (operands[3])); - return \"ext %0,%1,%2<%4>\"; /* <(32-%2-%3)> */ -}" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 32) - (const_int 0)))] - "" - "or %0,%#r0,%1") - -(define_insn "extzv" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "") - (match_operand:SI 3 "int5_operand" "")))] - "" - "* -{ - operands[4] = GEN_INT ((32 - INTVAL (operands[2])) - INTVAL (operands[3])); - return \"extu %0,%1,%2<%4>\"; /* <(32-%2-%3)> */ -}" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "int5_operand" "") - (match_operand:SI 2 "int5_operand" "")) - (const_int 0))] - "" - "* -{ - operands[3] = GEN_INT ((32 - INTVAL (operands[1])) - INTVAL (operands[2])); - return \"clr %0,%0,%1<%3>\"; /* <(32-%1-%2)> */ -}" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "int5_operand" "") - (match_operand:SI 2 "int5_operand" "")) - (const_int -1))] - "" - "* -{ - operands[3] = GEN_INT ((32 - INTVAL (operands[1])) - INTVAL (operands[2])); - return \"set %0,%0,%1<%3>\"; /* <(32-%1-%2)> */ -}" - [(set_attr "type" "bit")]) - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "int5_operand" "") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "int32_operand" "n"))] - "" - "* -{ - int value = INTVAL (operands[3]); - - if (INTVAL (operands[1]) < 32) - value &= (1 << INTVAL (operands[1])) - 1; - - operands[2] = GEN_INT (32 - (INTVAL(operands[1]) + INTVAL(operands[2]))); - - value <<= INTVAL (operands[2]); - operands[3] = GEN_INT (value); - - if (SMALL_INTVAL (value)) - return \"clr %0,%0,%1<%2>\;or %0,%0,%3\"; - else if ((value & 0x0000ffff) == 0) - return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\"; - else - return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\;or %0,%0,%x3\"; -}" - [(set_attr "type" "marith") - (set_attr "length" "3")]) ; may be 2 or 3. - -;; negate insns -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] - "" - "subu %0,%#r0,%1") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,x") - (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r,x"))))] - "" - "@ - fsub.ssd %0,%#r0,%1 - fsub.ssd %0,%#x0,%1" - [(set_attr "type" "dpadd")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=&r,r") - (neg:DF (match_operand:DF 1 "register_operand" "r,0")))] - "" - "@ - xor.u %0,%1,0x8000\;or %d0,%#r0,%d1 - xor.u %0,%0,0x8000" - [(set_attr "type" "marith,arith")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (neg:SF (match_operand:SF 1 "register_operand" "r")))] - "" - "xor.u %0,%1,0x8000") - -;; absolute value insns for floating-point (integer abs can be done using the -;; machine-independent sequence). - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=&r,r") - (abs:DF (match_operand:DF 1 "register_operand" "r,0")))] - "" - "@ - and.u %0,%1,0x7fff\;or %d0,%#r0,%d1 - and.u %0,%0,0x7fff" - [(set_attr "type" "marith,arith")]) - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (abs:SF (match_operand:SF 1 "register_operand" "r")))] - "" - "and.u %0,%1,0x7fff") - -;; Subroutines of "casesi". - -;; Operand 0 is index -;; operand 1 is the minimum bound -;; operand 2 is the maximum bound - minimum bound + 1 -;; operand 3 is CODE_LABEL for the table; -;; operand 4 is the CODE_LABEL to go to if index out of range. - -(define_expand "casesi" - ;; We don't use these for generating the RTL, but we must describe - ;; the operands here. - [(match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "immediate_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand 3 "" "") - (match_operand 4 "" "")] - "" - " -{ - register rtx index_diff = gen_reg_rtx (SImode); - register rtx low = GEN_INT (-INTVAL (operands[1])); - register rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[3]); - register rtx base; - - if (! CASE_VECTOR_INSNS) - /* These instructions are likely to be scheduled and made loop invariant. - This decreases the cost of the dispatch at the expense of the default - case. */ - base = force_reg (SImode, memory_address_noforce (SImode, label)); - - /* Compute the index difference and handle the default case. */ - emit_insn (gen_addsi3 (index_diff, - force_reg (SImode, operands[0]), - ADD_INT (low) ? low : force_reg (SImode, low))); - emit_insn (gen_cmpsi (index_diff, operands[2])); - /* It's possible to replace this branch with sgtu/iorsi3 and adding a -1 - entry to the table. However, that doesn't seem to win on the m88110. */ - emit_jump_insn (gen_bgtu (operands[4])); - - if (CASE_VECTOR_INSNS) - /* Call the jump that will branch to the appropriate case. */ - emit_jump_insn (gen_casesi_enter (label, index_diff, operands[3])); - else - /* Load the table entry and jump to it. */ - emit_jump_insn (gen_casesi_jump (gen_reg_rtx (SImode), base, index_diff, operands[3])); - - /* Claim that flow drops into the table so it will be adjacent by not - emitting a barrier. */ - DONE; -}") - -(define_expand "casesi_jump" - [(set (match_operand:SI 0 "" "") - (mem:SI (plus:SI (match_operand:SI 1 "" "") - (mult:SI (match_operand:SI 2 "" "") - (const_int 4))))) - (parallel [(set (pc) (match_dup 0)) - (use (label_ref (match_operand 3 "" "")))])] - "" - "") - -(define_insn "" - [(set (pc) (match_operand:SI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp%. %0" - [(set_attr "type" "jump")]) - -;; The bsr.n instruction is directed to the END of the table. See -;; ASM_OUTPUT_CASE_END. - -(define_insn "casesi_enter" - [(set (pc) (match_operand 0 "" "")) - (use (match_operand:SI 1 "register_operand" "r")) - ;; The USE here is so that at least one jump-insn will refer to the label, - ;; to keep it alive in jump_optimize. - (use (label_ref (match_operand 2 "" ""))) - (clobber (reg:SI 1))] - "" - "* -{ - if (flag_delayed_branch) - return \"bsr.n %0e\;lda %#r1,%#r1[%1]\"; - m88k_case_index = REGNO (operands[1]); - return \"bsr %0e\"; -}" - [(set_attr "type" "weird") - (set_attr "length" "3")]) ; Including the "jmp r1". - -;;- jump to subroutine -(define_expand "call" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (clobber (reg:SI 1))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! call_address_operand (XEXP (operands[0], 0), SImode)) - operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), - force_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "" - [(parallel [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rQ")) - (match_operand 1 "" "")) - (clobber (reg:SI 1))])] - "" - "* return output_call (operands, operands[0]);" - [(set_attr "type" "call")]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (match_operand:SI 1 "" "") - (match_operand 2 "" ""))) - (clobber (reg:SI 1))])] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && ! call_address_operand (XEXP (operands[1], 0), SImode)) - operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), - force_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(parallel [(set (match_operand 0 "register_operand" "=r") - (call (mem:SI - (match_operand:SI 1 "call_address_operand" "rQ")) - (match_operand 2 "" ""))) - (clobber (reg:SI 1))])] - "" - "* return output_call (operands, operands[1]);" - [(set_attr "type" "call")]) - -;; Nop instruction and others - -(define_insn "nop" - [(const_int 0)] - "" - "ff0 %#r0,%#r0" - [(set_attr "type" "bit")]) - -(define_insn "return" - [(return)] - "reload_completed" - "jmp%. %#r1" - [(set_attr "type" "jump")]) - -(define_expand "prologue" - [(const_int 0)] - "" - "m88k_expand_prologue (); DONE;") - -(define_expand "epilogue" - [(return)] - "! null_prologue ()" - "m88k_expand_epilogue ();") - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "length" "0")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "jmp%. %0" - [(set_attr "type" "jump")]) - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "br%. %l0" - [(set_attr "type" "jump")]) - -;; This insn is used for some loop tests, typically loops reversed when -;; strength reduction is used. It is actually created when the instruction -;; combination phase combines the special loop test. Since this insn -;; is both a jump insn and has an output, it must deal with its own -;; reloads, hence the `m' constraints. The `!' constraints direct reload -;; to not choose the register alternatives in the event a reload is needed. - -(define_expand "decrement_and_branch_until_zero" - [(parallel [(set (pc) - (if_then_else - (match_operator 0 "relop_no_unsigned" - [(match_operand:SI 1 "register_operand" "") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (set (match_dup 1) - (plus:SI (match_dup 1) - (match_operand:SI 3 "add_operand" ""))) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "=X,X,&r,&r"))])] - "" - "") - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "relop_no_unsigned" - [(match_operand:SI 1 "register_operand" "+!r,!r,m,m") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (set (match_dup 1) - (plus:SI (match_dup 1) - (match_operand:SI 3 "add_operand" "rI,J,rI,J"))) - (clobber (match_scratch:SI 4 "=X,X,&r,&r")) - (clobber (match_scratch:SI 5 "=X,X,&r,&r"))] - "find_reg_note (insn, REG_NONNEG, 0)" - "@ - bcnd.n %B0,%1,%2\;addu %1,%1,%3 - bcnd.n %B0,%1,%2\;subu %1,%1,%n3 - ld %4,%1\;addu %5,%4,%3\;bcnd.n %B0,%4,%2\;st %5,%1 - ld %4,%1\;subu %5,%4,%n3\;bcnd.n %B0,%4,%2\;st %5,%1" - [(set_attr "type" "weird") - (set_attr "length" "2,2,4,4")]) - -;; Special insn to serve as the last insn of a define_expand. This insn -;; will generate no code. - -(define_expand "dummy" - [(set (match_operand 0 "" "") (match_dup 0))] - "" - "") diff --git a/gcc/config/m88k/sysv3.h b/gcc/config/m88k/sysv3.h deleted file mode 100755 index ef35189..0000000 --- a/gcc/config/m88k/sysv3.h +++ /dev/null @@ -1,150 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port. - Copyright (C) 1990, 1991, 1997 Free Software Foundation, Inc. - Contributed by Ray Essick (ressick@mot.com) - Enhanced by Tom Wood (Tom_Wood@NeXT.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 "m88k/m88k.h" - -/* Default switches */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_CHECK_ZERO_DIV | \ - MASK_OCS_DEBUG_INFO | \ - MASK_OCS_FRAME_POSITION) - -/* Macros to be automatically defined. */ -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dm88000 -Dm88k -Dunix -DsysV88 -D__CLASSIFY_TYPE__=2 -Asystem(unix) -Asystem(svr3) -Acpu(m88k) -Amachine(m88k)" - -/* Override svr3.h to link with ?crt0.o instead of ?crt1.o and ?crtn.o. - From arul@sdsu.edu. */ -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} crtbegin.o%s" - -/* Profiled libraries live in a different directory but keep the same - names other than that. arul@sdsu.edu says -lg is always needed. */ -#undef LIB_SPEC -#define LIB_SPEC "%{p:-L/lib/libp}%{pg:%{!p:-L/lib/libp}} -lg -lc crtend.o%s" - -/* Hot version of the profiler that uses r10 to pass the address of - the counter. the _gcc_mcount routine knows not to screw with - the parameter registers. - - DG/UX does this; i wrote a gnu-c/88k specific version and put it - in libgcc2.c -- RBE; this macro knows about the leading underscore - convention. */ -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - output_function_profiler (FILE, LABELNO, "_gcc_mcount", 0) - -/* Various other changes that we want to have in place without - too many changes to the m88k.h file. */ -#undef USE_LIBG -#define USE_LIBG - -/* Define a few machine-specific details of the implementation of - constructors. */ - -/* Although the .init section is used, it is not automatically invoked. */ -#define INVOKE__main - -/* State that atexit exists so __do_global_ctors will register - __do_global_dtors. */ -#define HAVE_ATEXIT - -#define CTOR_LIST_BEGIN \ - asm (INIT_SECTION_ASM_OP); \ - asm ("\tsubu\t r31,r31,16"); /* (STACK_BOUNDARY / BITS_PER_UNIT) == 16 */ \ - asm ("\tst\t r0,r31,32"); /* REG_PARM_STACK_SPACE (0) == 32 */ -#define CTOR_LIST_END - -/* ASM_OUTPUT_CONSTRUCTOR outputs code into the .init section to push the - address of the constructor. This becomes the body of __do_global_ctors - in crtstuff.c. r13 is a temporary register. */ -#undef ASM_OUTPUT_CONSTRUCTOR -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - init_section (); \ - fprintf (FILE, "\tor.u\t r13,r0,hi16("); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ")\n\tor\t r13,r13,lo16("); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n", \ - STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0)); \ - } while (0) - -#undef DO_GLOBAL_CTORS_BODY -#define DO_GLOBAL_CTORS_BODY \ -do { \ - func_ptr *__CTOR_LIST__ = __builtin_alloca (1), *p; \ - for (p = __CTOR_LIST__ + 4; *p; p += 4) \ - (*p) (); \ -} while (0) - -#define DTOR_LIST_BEGIN \ - asm (FINI_SECTION_ASM_OP); \ - func_ptr __DTOR_LIST__[4] = { (func_ptr) (-1), (func_ptr) (-1), \ - (func_ptr) (-1), (func_ptr) (-1) } -#define DTOR_LIST_END \ - asm (FINI_SECTION_ASM_OP); \ - func_ptr __DTOR_END__[4] = { (func_ptr) 0, (func_ptr) 0, \ - (func_ptr) 0, (func_ptr) 0 } - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. The table is constructed in the .fini section - so that an explicit linker script is not required. The complication - is that this section is padded with NOP instructions and to either - 8 or 16 byte alignment depending on the specific system. A clever - way to avoid trouble is to output a block of 16 bytes where the - extra words are known values (-1). */ -#undef ASM_OUTPUT_DESTRUCTOR -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - register int i; \ - fini_section (); \ - fprintf (FILE, "\t%s\t ", ASM_LONG); \ - assemble_name (FILE,NAME); \ - fprintf (FILE, "\n"); \ - for (i = 1; i < 4; i++) \ - fprintf (FILE, "\t%s\t -1\n", ASM_LONG); \ - } while (0) - -/* Walk the list looking for the terminating zero and ignoring all values of - -1. */ -#undef DO_GLOBAL_DTORS_BODY -#define DO_GLOBAL_DTORS_BODY \ - do { \ - int i; \ - for (i = 0; __DTOR_LIST__[i] != 0; i++) \ - if (((int *)__DTOR_LIST__)[i] != -1) \ - __DTOR_LIST__[i] (); \ - } while (0) - -#undef INITIALIZE_TRAMPOLINE -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 40)), FNADDR); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 36)), CXT); \ - emit_call_insn (gen_call (gen_rtx (MEM, SImode, \ - gen_rtx (SYMBOL_REF, Pmode, \ - "__enable_execute_stack")), \ - const0_rtx)); \ -} diff --git a/gcc/config/m88k/sysv4.h b/gcc/config/m88k/sysv4.h deleted file mode 100755 index ff6dc78..0000000 --- a/gcc/config/m88k/sysv4.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Motorola 88100 in an 88open ABI environment. - Copyright (C) 1990, 1991 Free Software Foundation, Inc. - - Written by Ron Guilmette (rfg@netcom.com). - Contributed to FSF by Network Computing Devices. - - Other contributions by Vince Guarna (vguarna@urbana.mcd.mot.com), - Ray Essick (essick@i88.isc.com), Wilson Tien (wtien@urbana.mcd.mot.com), - and Tom Wood (Tom_Wood@NeXT.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. */ - -/* DWARF_DEBUGGING_INFO defined in svr4.h. */ - -#ifndef NO_BUGS -#define AS_BUG_DOT_LABELS -#define AS_BUG_POUND_TYPE -#endif - -#include "svr4.h" -#include "m88k/m88k.h" - -/* Identify the compiler. */ -#undef VERSION_INFO1 -#define VERSION_INFO1 "88open ABI, " - -/* Default switches */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_CHECK_ZERO_DIV | \ - MASK_OCS_DEBUG_INFO | \ - MASK_SVR4) - -/* Cpp spec. These pre-assertions are needed for SVR4 as they occur - often in the system header files. __svr4__ is our extension. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES \ - "-Dm88000 -Dm88k -Dunix -D__svr4__ -Amachine(m88k) -Acpu(m88k) -Asystem(unix) -Asystem(svr4)" - -/* For the AT&T SVR4 port, the function is _mcount. */ -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - output_function_profiler (FILE, LABELNO, "_mcount", 1) - -/* Override svr4.h and m88k.h. */ -#undef INIT_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP "section\t.init,\"xa\",#progbits" -#undef FINI_SECTION_ASM_OP -#define FINI_SECTION_ASM_OP "section\t.fini,\"xa\",#progbits" - -/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. - - Note that we want to give these sections the SHF_WRITE attribute - because these sections will actually contain data (i.e. tables of - addresses of functions in the current root executable or shared library - file) and, in the case of a shared library, the relocatable addresses - will have to be properly resolved/relocated (and then written into) by - the dynamic linker when it actually attaches the given shared library - to the executing process. (Note that on SVR4, you may wish to use the - `-z text' option to the ELF linker, when building a shared library, as - an additional check that you are doing everything right. But if you do - use the `-z text' option when building a shared library, you will get - errors unless the .ctors and .dtors sections are marked as writable - via the SHF_WRITE attribute.) */ - -#undef CTORS_SECTION_ASM_OP -#define CTORS_SECTION_ASM_OP "section\t.ctors,\"aw\"" -#undef DTORS_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP "section\t.dtors,\"aw\"" diff --git a/gcc/config/m88k/t-bug b/gcc/config/m88k/t-bug deleted file mode 100755 index a5e71dd..0000000 --- a/gcc/config/m88k/t-bug +++ /dev/null @@ -1,12 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null diff --git a/gcc/config/m88k/t-dgux b/gcc/config/m88k/t-dgux deleted file mode 100755 index cced6b1..0000000 --- a/gcc/config/m88k/t-dgux +++ /dev/null @@ -1,26 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null - -# In a coff environment, a link script is required for ctors and dtors. -m88kdgux.ld: $(srcdir)/config/m88k/dgux.ld - rm -f m88kdgux.ld; cp $(srcdir)/config/m88k/dgux.ld ./m88kdgux.ld - -# A bcs crtbegin.o is needed since bcs does not -# increment the stack pointer in the init section as elf does -bcscrtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_BEGIN -DBCS \ - -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c -o bcscrtbegin.o - -# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects -GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET -mno-ocs-debug-info diff --git a/gcc/config/m88k/t-dgux-gas b/gcc/config/m88k/t-dgux-gas deleted file mode 100755 index c7368c3..0000000 --- a/gcc/config/m88k/t-dgux-gas +++ /dev/null @@ -1,17 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null -T_CPPFLAGS = -DUSE_GAS - -# In a coff environment, a link script is required. -m88kdgux.ld: $(srcdir)/config/m88k/dgux.ld - rm -f m88kdgux.ld; cp $(srcdir)/config/m88k/dgux.ld ./m88kdgux.ld diff --git a/gcc/config/m88k/t-dguxbcs b/gcc/config/m88k/t-dguxbcs deleted file mode 100755 index c42a9bf..0000000 --- a/gcc/config/m88k/t-dguxbcs +++ /dev/null @@ -1,28 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null - -# In a coff environment, a link script is required for ctors and dtors. -m88kdgux.ld: $(srcdir)/config/m88k/dgux.ld - rm -f m88kdgux.ld; cp $(srcdir)/config/m88k/dgux.ld ./m88kdgux.ld - -# A bcs crtbegin.o is needed since bcs does not -# increment the stack pointer in the init section as elf does -bcscrtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_BEGIN -DBCS \ - -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/crtstuff.c -o bcscrtbegin.o - -# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects -GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET -mno-ocs-debug-info - -T_CFLAGS = -O -D_M88KBCS_TARGET diff --git a/gcc/config/m88k/t-luna b/gcc/config/m88k/t-luna deleted file mode 100755 index dce5f22..0000000 --- a/gcc/config/m88k/t-luna +++ /dev/null @@ -1,12 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh -no-tdesc - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null diff --git a/gcc/config/m88k/t-luna-gas b/gcc/config/m88k/t-luna-gas deleted file mode 100755 index 1d6692a..0000000 --- a/gcc/config/m88k/t-luna-gas +++ /dev/null @@ -1,13 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - bash $(srcdir)/config/m88k/m88k-move.sh -no-tdesc - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null -T_CPPFLAGS = -DUSE_GAS diff --git a/gcc/config/m88k/t-m88k b/gcc/config/m88k/t-m88k deleted file mode 100755 index a5e71dd..0000000 --- a/gcc/config/m88k/t-m88k +++ /dev/null @@ -1,12 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null diff --git a/gcc/config/m88k/t-m88k-gas b/gcc/config/m88k/t-m88k-gas deleted file mode 100755 index dc436e1..0000000 --- a/gcc/config/m88k/t-m88k-gas +++ /dev/null @@ -1,18 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null -T_CPPFLAGS = -DUSE_GAS - -# For svr4 we build crtbegin.o and crtend.o which serve to add begin and -# end labels to the .ctors and .dtors section when we link using gcc. - -EXTRA_PARTS=crtbegin.o crtend.o diff --git a/gcc/config/m88k/t-sysv4 b/gcc/config/m88k/t-sysv4 deleted file mode 100755 index 3f90cd5..0000000 --- a/gcc/config/m88k/t-sysv4 +++ /dev/null @@ -1,22 +0,0 @@ -# Specify how to create the *.asm files - -MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ - moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ - moveDI96x.asm - -# Use the -abi option for version 03.00 syntax. - -$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh - $(srcdir)/config/m88k/m88k-move.sh -abi - -LIB2FUNCS_EXTRA = $(MOVE_ASM) -LIBGCC1 = libgcc1.null -CROSS_LIBGCC1 = libgcc1.null - -# We need to use -fPIC when we are using gcc to compile the routines in -# crtstuff.c. This is only really needed when we are going to use gcc/g++ -# to produce a shared library, but since we don't know ahead of time when -# we will be doing that, we just always use -fPIC when compiling the -# routines in crtstuff.c. - -CRTSTUFF_T_CFLAGS=-fPIC diff --git a/gcc/config/m88k/tekXD88.h b/gcc/config/m88k/tekXD88.h deleted file mode 100755 index 5b37dea..0000000 --- a/gcc/config/m88k/tekXD88.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Tektronix XD88 UTekV 3.2e (svr3 derived from UniSoft System V/88) - - Copyright (C) 1993 Free Software Foundation, Inc. - Contributed by Kaveh R. Ghazi (ghazi@caip.rutgers.edu) 2/22/93. - - 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 "m88k/sysv3.h" - -/* Don't output structure tag names when it causes a forward reference. - Symptom: - Error messages like - as: "/usr/tmp/cca22733.s": cannot reduce symbol table, unused symbols remain - when compiling some programs. - example program (C++): struct bad { bad(); }; bad::bad() {} - - This problem seems to have gone away, perhaps with release 3.6 of the O/S - from Dolphin. */ -/* #undef SDB_ALLOW_FORWARD_REFERENCES */ -/* I don't know if this SDB thing is needed or not --KRG */ - - -/* Use T_ARG as T_VOID. T_VOID is not defined in <syms.h> as it should be. */ -#define T_VOID T_ARG - - -/* The bundled ld program needs link editor directives which normally - reside in /lib/default.ld. We'll pass our own copy during the link - phase because additional information about extra sections must be added - so that gcc generated files will link properly. - --KRG. - */ -#undef LINK_SPEC -#define LINK_SPEC "gcc.ld%s" diff --git a/gcc/config/m88k/tekXD88.ld b/gcc/config/m88k/tekXD88.ld deleted file mode 100755 index 86c6522..0000000 --- a/gcc/config/m88k/tekXD88.ld +++ /dev/null @@ -1,39 +0,0 @@ -/* gcc.ld - COFF linker directives for the Tektronix XD88. - - 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 does the following: - - Sets VIRTUAL addr of .text to 0x10200 - Sets FILE addr of .text to 0x200 (BLOCK directive) - - Depending on size of .text section rounds up to next - 4 MG boundary, adds (size of .text and vaddr of .text) mod 64K - This is to handle sections larger than 4 MG. -*/ - -SECTIONS { - .text 0x10200 BLOCK (0x200): - { *(.init) *(.text) *(.rodata) *(.tdesc) *(.fini)} - - GROUP BIND( ((SIZEOF(.text) / 0x400000 * 0x400000) + 0x400000) + - ((SIZEOF(.text) + ADDR(.text)) % 0x10000) ) : - { - .data : { } - .bss : { } - } -} diff --git a/gcc/config/m88k/x-dgux b/gcc/config/m88k/x-dgux deleted file mode 100755 index f2c55a7..0000000 --- a/gcc/config/m88k/x-dgux +++ /dev/null @@ -1,6 +0,0 @@ -CC = gcc -BISONFLAGS = -l -USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) - -STMP_FIXPROTO = -X_CFLAGS = -O -mstandard -mlegend diff --git a/gcc/config/m88k/x-dguxbcs b/gcc/config/m88k/x-dguxbcs deleted file mode 100755 index 8baf0ca..0000000 --- a/gcc/config/m88k/x-dguxbcs +++ /dev/null @@ -1,4 +0,0 @@ -CC = gcc -BISONFLAGS = -l -USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) -STMP_FIXPROTO = diff --git a/gcc/config/m88k/x-dolph b/gcc/config/m88k/x-dolph deleted file mode 100755 index b31a7a9..0000000 --- a/gcc/config/m88k/x-dolph +++ /dev/null @@ -1,19 +0,0 @@ -# Use link editor directives to make NULL pointers point to -# invalid addresses. - -EXTRA_PARTS=crtbegin.o crtend.o gcc.ld - -gcc.ld: $(srcdir)/config/m88k/dolphin.ld - rm -f gcc.ld; cp $(srcdir)/config/m88k/dolphin.ld gcc.ld - -# Green Hills C on Dolphin UNIX System V/88 Release 3.2 Version 3.6/5.86 does -# not provide alloca. It does not harm to have it defined on version 3.8.alfa -# even though it's not needed there. - -ALLOCA=alloca.o - -# Under DolphinOS 3.8.alfa, /bin/cc defines __GNUC__, but not __m88k__, -# causing gdstarg.h to fail. Defining __m88k__ does probably not hurt on -# DolphinOS 3.6. - -X_CFLAGS =-D__m88k__ diff --git a/gcc/config/m88k/x-sysv3 b/gcc/config/m88k/x-sysv3 deleted file mode 100755 index 3ee9067..0000000 --- a/gcc/config/m88k/x-sysv3 +++ /dev/null @@ -1,7 +0,0 @@ -# this is m88k/x-sysv3 - -# native compiler does not provide alloca - -ALLOCA = alloca.o - -# end m88k/x-sysv3 diff --git a/gcc/config/m88k/x-sysv4 b/gcc/config/m88k/x-sysv4 deleted file mode 100755 index dd24287..0000000 --- a/gcc/config/m88k/x-sysv4 +++ /dev/null @@ -1,10 +0,0 @@ -# Problems in early version of the assembler have been fixed (-DNO_BUGS). -# There are peculiar problems with the include files that require __STDC__ -# to be defined as 0. This results in sigset_t being defined which otherwise -# results in a problem when <wait.h> includes <siginfo.h>. - -X_CFLAGS = -DNO_BUGS -D__STDC__=0 - -# The CI5 compiler does not provide alloca. - -ALLOCA = alloca.o diff --git a/gcc/config/m88k/x-tekXD88 b/gcc/config/m88k/x-tekXD88 deleted file mode 100755 index b8b4a2f..0000000 --- a/gcc/config/m88k/x-tekXD88 +++ /dev/null @@ -1,12 +0,0 @@ -# Install the custom Tektronix XD88 link editor directives file. -EXTRA_PARTS=crtbegin.o crtend.o gcc.ld - -gcc.ld: $(srcdir)/config/m88k/tekXD88.ld - rm -f gcc.ld; cp $(srcdir)/config/m88k/tekXD88.ld ./gcc.ld - -# Green Hills C on the Tektronix XD88 does not provide alloca. -ALLOCA=alloca.o - -# rc is cleaner, but the ar program sometimes crashes. -# This is a workaround. -AR_FLAGS=qc diff --git a/gcc/config/m88k/xm-m88k.h b/gcc/config/m88k/xm-m88k.h deleted file mode 100755 index b330f59..0000000 --- a/gcc/config/m88k/xm-m88k.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Configuration for GNU compiler. - Motorola m88100 in an 88open OCS/BCS environment. - Copyright (C) 1988, 89, 90, 91, 93, 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. */ - - -/* #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 - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* The 88open BCS (and ABI) environment doesn't support BSD features - (vfork, getrusage), so use USG. The Omron Luna/88k is BSD though. */ -#ifndef luna88k -#ifndef USG -#define USG -#endif -#define NO_SYS_SIGLIST -#endif - -/* If not compiled with GNU C, use the C alloca */ -#ifndef __GNUC__ -#define USE_C_ALLOCA -#endif - -/* For DG/UX, the best size is different. */ -#ifdef __DGUX__ -#define OBSTACK_CHUNK_SIZE (8192-16) -#endif - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" diff --git a/gcc/config/m88k/xm-sysv3.h b/gcc/config/m88k/xm-sysv3.h deleted file mode 100755 index 84110d7..0000000 --- a/gcc/config/m88k/xm-sysv3.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Configuration for GNU C-compiler. - Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port. - Copyright (C) 1990, 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. */ - -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#define F_OK 0 - -/* for the emacs version of alloca */ -#define STACK_DIRECTION -1 - -/* We need POSIX/XOPEN symbols; otherwise make check will fail. */ -#define ADD_MISSING_POSIX 1 -#define ADD_MISSING_XOPEN 1 |