summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-16 11:43:46 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-16 11:43:46 +0000
commita4eb28f68b69e3780aff0858944ee1207b7534c9 (patch)
tree93ee1416eaddeccb1448e06fc0b9eea02af325c3 /gcc
parent067277c389ff24af29f0ce9a1b31d7d002ae9fe8 (diff)
downloadgcc-a4eb28f68b69e3780aff0858944ee1207b7534c9.tar.gz
Checkin missing parts of my 2005-12-12 patch
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108636 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config.gcc4
-rw-r--r--gcc/config/ms1/ABI.txt219
-rw-r--r--gcc/config/ms1/crti.asm71
-rw-r--r--gcc/config/ms1/crtn.asm56
-rw-r--r--gcc/config/ms1/lib2extra-funcs.c232
-rw-r--r--gcc/config/ms1/mt-protos.h66
-rw-r--r--gcc/config/ms1/mt.c2498
-rw-r--r--gcc/config/ms1/mt.h879
-rw-r--r--gcc/config/ms1/mt.md1500
-rw-r--r--gcc/config/ms1/mt.opt56
-rw-r--r--gcc/config/ms1/t-mt70
11 files changed, 2 insertions, 5649 deletions
diff --git a/gcc/config.gcc b/gcc/config.gcc
index e443dd0023f..6c8a2d48461 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1582,9 +1582,9 @@ mn10300-*-*)
use_collect2=no
use_fixproto=yes
;;
-ms1-*-elf)
+mt-*-elf)
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
- tmake_file="${tmake_file} ms1/t-ms1"
+ tmake_file="${tmake_file} mt/t-mt"
;;
ns32k-*-netbsdelf*)
echo "GCC does not yet support the ${target} target"; exit 1
diff --git a/gcc/config/ms1/ABI.txt b/gcc/config/ms1/ABI.txt
deleted file mode 100644
index 97dfbb80a86..00000000000
--- a/gcc/config/ms1/ABI.txt
+++ /dev/null
@@ -1,219 +0,0 @@
- Copyright (C) 2005 Free Software Foundation, Inc.
-
- Copying and distribution of this file, with or without modification,
- are permitted in any medium without royalty provided the copyright
- notice and this notice are preserved.
-
---------------------------------------------------------------------------
-
- MS1 ABI
- =========
-
-Sizes and alignments
---------------------
-
- Type Size (bytes) Alignment (bytes)
-
- char 1 1
- short 2 2
- int 4 4
- unsigned 4 4
- long 4 4
- long long 8 8
- float 4 4
- double 8 8
- pointers 4 4
-
-* alignment within aggregates (structs and unions) is as above, with
- padding added if needed
-* aggregates have alignment equal to that of their most aligned
- member
-* aggregates have sizes which are a multiple of their alignment
-
-
-Floating point
---------------
-
-All emulated using IEEE floating point conventions.
-
-Registers
-----------------
-
-r0 always zero
-r1 argument register 1
-r2 argument register 2
-r3 argument register 3
-r4 argument register 4
-r5 callee must save
-r6 callee must save
-r7 call clobbers
-r8 call clobbers
-r9 call clobbers
-r10 call clobbers
-r11 function return value
-r12 frame pointer
-r13 stack pointer
-r14 linkage pointer
-r15 interrupt pointer
-
-Stack alignment 8 bytes
-
-Structures passed <= 32 bits as values, else as pointers
-
-The MS1 Stack
----------------
-
-Space is allocated as needed in the stack frame for the following at compile
-time:
-
-* Outgoing parameters beyond the fourth
-
-* All automatic arrays, automatic data aggregates, automatic
- scalars which must be addressable, and automatic scalars for
- which there is no room in registers
-
-* Compiler-generated temporary values (typically when there are
- too many for the compiler to keep them all in registers)
-
-Space can be allocated dynamically (at runtime) in the stack frame for the
-following:
-
-* Memory allocated using the alloca() function of the C library
-
-Addressable automatic variables on the stack are addressed with positive
-offsets relative to r12; dynamically allocated space is addressed with positive
-offsets from the pointer returned by alloca().
-
-Stack Frame
------------
-
- +-----------------------+
- | Parameter Word 1 |
- +-----------------------+ <-sp
- | Previous FP |
- +-----------------------+
- | Return address |
- +-----------------------+
- | Saved Registers |
- +-----------------------+
- | ... |
- +-----------------------+
- | Local Variables |
- +-----------------------+ <-fp
- | Alloca |
- +-----------------------+
- | ... |
- +-----------------------+
- | Parameter Word 2 |
- +-----------------------+
- | Parameter Word 1 |
- +-----------------------+ <-sp
-
-
-Parameter Assignment to Registers
----------------------------------
-
-Consider the parameters in a function call as ordered from left (first
-parameter) to right. GR contains the number of the next available
-general-purpose register. STARG is the address of the next available stack
-parameter word.
-
-INITIALIZE:
- Set GR=r1 and STARG to point to parameter word 1.
-
-SCAN:
- If there are no more parameters, terminate.
- Otherwise, select one of the following depending on the type
- of the next parameter:
-
- SIMPLE ARG:
-
- A SIMPLE ARG is one of the following:
-
- * One of the simple integer types which will fit into a
- general-purpose register,
- * A pointer to an object of any type,
- * A struct or union small enough to fit in a register (<= 32 bits)
- * A larger struct or union, which shall be treated as a
- pointer to the object or to a copy of the object.
- (See below for when copies are made.)
-
- If GR > r4, go to STACK. Otherwise, load the parameter value into
- general-purpose register GR and advance GR to the next general-purpose
- register. Values shorter than the register size are sign-extended or
- zero-extended depending on whether they are signed or unsigned. Then
- go to SCAN.
-
- DOUBLE or LONG LONG
-
- If GR > r3, go to STACK. Otherwise, if GR is odd, advance GR to the
- next register. Load the 64-bit long long or double value into register
- pair GR and GR+1. Advance GR to GR+2 and go to SCAN.
-
- STACK:
-
- Parameters not otherwise handled above are passed in the parameter
- words of the caller's stack frame. SIMPLE ARGs, as defined above, are
- considered to have size and alignment equal to the size of a
- general-purpose register, with simple argument types shorter than this
- sign- or zero-extended to this width. Round STARG up to a multiple of
- the alignment requirement of the parameter and copy the argument
- byte-for-byte into STARG, STARG+1, ... STARG+size-1. Set STARG to
- STARG+size and go to SCAN.
-
-
-Structure passing
------------------
-
-As noted above, code which passes structures and unions by value is implemented
-specially. (In this section, "struct" will refer to structs and unions
-inclusively.) Structs small enough to fit in a register are passed by value in
-a single register or in a stack frame slot the size of a register. Structs
-containing a single double or long long component are passed by value in two
-registers or in a stack frame slot the size of two registers. Other structs
-are handled by passing the address of the structure. In this case, a copy of
-the structure will be made if necessary in order to preserve the pass-by-value
-semantics.
-
-Copies of large structs are made under the following rules:
-
- ANSI mode K&R Mode
- --------- --------
-Normal param Callee copies if needed Caller copies
-Varargs (...) param Caller copies Caller copies
-
-In the case of normal (non-varargs) large-struct parameters in ANSI mode, the
-callee is responsible for producing the same effect as if a copy of the
-structure were passed, preserving the pass-by-value semantics. This may be
-accomplished by having the callee make a copy, but in some cases the callee may
-be able to determine that a copy is not necessary in order to produce the same
-results. In such cases, the callee may choose to avoid making a copy of the
-parameter.
-
-
-Varargs handling
-----------------
-
-No special changes are needed for handling varargs parameters other than the
-caller knowing that a copy is needed on struct parameters larger than a
-register (see above).
-
-The varargs macros set up a register save area for the general-purpose
-registers to be saved. Because the save area lies between the caller and
-callee stack frames, the saved register parameters are contiguous with
-parameters passed on the stack. A pointer advances from the register save area
-into the caller's stack frame.
-
-
-Function return values
-----------------------
-
- Type Register
- ---- --------
- int r11
- short r11
- long r11
- long long stack
- float r11
- double stack
-
diff --git a/gcc/config/ms1/crti.asm b/gcc/config/ms1/crti.asm
deleted file mode 100644
index 115b96e7cb8..00000000000
--- a/gcc/config/ms1/crti.asm
+++ /dev/null
@@ -1,71 +0,0 @@
-# crti.asm for ms1
-#
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2, or (at your option) any
-# later version.
-#
-# In addition to the permissions in the GNU General Public License, the
-# Free Software Foundation gives you unlimited permission to link the
-# compiled version of this file with other programs, and to distribute
-# those programs without any restriction coming from the use of this
-# file. (The General Public License restrictions do apply in other
-# respects; for example, they cover modification of the file, and
-# distribution when not linked into another program.)
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING. If not, write to the Free
-# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception, if you link this library with files
-# compiled with GCC to produce an executable, this does not cause
-# the resulting executable to be covered by the GNU General Public License.
-# This exception does not however invalidate any other reasons why
-# the executable file might be covered by the GNU General Public License.
-#
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
- .file "crti.asm"
-
- .section ".init"
- .global _init
- .type _init,#function
- .align 4
-_init:
- subi sp, sp, #4
- stw r14, sp, #0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
-
- .section ".fini"
- .global _fini
- .type _fini,#function
- .align 4
-_fini:
- subi sp, sp, #4
- stw r14, sp, #0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
- or r0, r0, r0
diff --git a/gcc/config/ms1/crtn.asm b/gcc/config/ms1/crtn.asm
deleted file mode 100644
index 5fbe7ece969..00000000000
--- a/gcc/config/ms1/crtn.asm
+++ /dev/null
@@ -1,56 +0,0 @@
-# crtn.asm for ms1
-
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2, or (at your option) any
-# later version.
-#
-# In addition to the permissions in the GNU General Public License, the
-# Free Software Foundation gives you unlimited permission to link the
-# compiled version of this file with other programs, and to distribute
-# those programs without any restriction coming from the use of this
-# file. (The General Public License restrictions do apply in other
-# respects; for example, they cover modification of the file, and
-# distribution when not linked into another program.)
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING. If not, write to the Free
-# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception, if you link this library with files
-# compiled with GCC to produce an executable, this does not cause
-# the resulting executable to be covered by the GNU General Public License.
-# This exception does not however invalidate any other reasons why
-# the executable file might be covered by the GNU General Public License.
-#
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .file "crtn.asm"
-
- .section ".init"
- .align 4
- ldw r14, sp, #0
- addi sp, sp, #4
- nop
- jal r0, r14
- or r0, r0, r0
-
- .section ".fini"
- .align 4
-
- ldw r14, sp, #0
- addi sp, sp, #4
- nop
- jal r0, r14
- or r0, r0, r0
diff --git a/gcc/config/ms1/lib2extra-funcs.c b/gcc/config/ms1/lib2extra-funcs.c
deleted file mode 100644
index 6f5ec6a619c..00000000000
--- a/gcc/config/ms1/lib2extra-funcs.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* Copyright (C) 2005 Free Software Foundation,
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-GCC 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 GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
-
-#define BITS_PER_UNIT 8
-
-typedef int HItype __attribute__ ((mode (HI)));
-typedef unsigned int UHItype __attribute__ ((mode (HI)));
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct SIstruct {HItype low, high;};
-
-typedef union
-{
- struct SIstruct s;
- SItype ll;
-} SIunion;
-
-SItype
-__lshrsi3 (SItype u, word_type b)
-{
- SIunion w;
- word_type bm;
- SIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (HItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (UHItype)uu.s.high >> -bm;
- }
- else
- {
- UHItype carries = (UHItype)uu.s.high << bm;
- w.s.high = (UHItype)uu.s.high >> b;
- w.s.low = ((UHItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-
-SItype
-__ashlsi3 (SItype u, word_type b)
-{
- SIunion w;
- word_type bm;
- SIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (HItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (UHItype)uu.s.low << -bm;
- }
- else
- {
- UHItype carries = (UHItype)uu.s.low >> bm;
- w.s.low = (UHItype)uu.s.low << b;
- w.s.high = ((UHItype)uu.s.high << b) | carries;
- }
-
- return w.ll;
-}
-
-SItype
-__ashrsi3 (SItype u, word_type b)
-{
- SIunion w;
- word_type bm;
- SIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (HItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (sizeof (HItype) * BITS_PER_UNIT - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- UHItype carries = (UHItype)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((UHItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-
-USItype
-__mulsi3 (USItype a, USItype b)
-{
- USItype c = 0;
-
- while (a != 0)
- {
- if (a & 1)
- c += b;
- a >>= 1;
- b <<= 1;
- }
-
- return c;
-}
-
-USItype
-udivmodsi4(USItype num, USItype den, word_type modwanted)
-{
- USItype bit = 1;
- USItype res = 0;
-
- while (den < num && bit && !(den & (1L<<31)))
- {
- den <<=1;
- bit <<=1;
- }
- while (bit)
- {
- if (num >= den)
- {
- num -= den;
- res |= bit;
- }
- bit >>=1;
- den >>=1;
- }
- if (modwanted) return num;
- return res;
-}
-
-SItype
-__divsi3 (SItype a, SItype b)
-{
- word_type neg = 0;
- SItype res;
-
- if (a < 0)
- {
- a = -a;
- neg = !neg;
- }
-
- if (b < 0)
- {
- b = -b;
- neg = !neg;
- }
-
- res = udivmodsi4 (a, b, 0);
-
- if (neg)
- res = -res;
-
- return res;
-}
-
-SItype
-__modsi3 (SItype a, SItype b)
-{
- word_type neg = 0;
- SItype res;
-
- if (a < 0)
- {
- a = -a;
- neg = 1;
- }
-
- if (b < 0)
- b = -b;
-
- res = udivmodsi4 (a, b, 1);
-
- if (neg)
- res = -res;
-
- return res;
-}
-
-SItype
-__udivsi3 (SItype a, SItype b)
-{
- return udivmodsi4 (a, b, 0);
-}
-
-SItype
-__umodsi3 (SItype a, SItype b)
-{
- return udivmodsi4 (a, b, 1);
-}
diff --git a/gcc/config/ms1/mt-protos.h b/gcc/config/ms1/mt-protos.h
deleted file mode 100644
index c37048263ca..00000000000
--- a/gcc/config/ms1/mt-protos.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Prototypes for exported functions defined in ms1.c
- Copyright (C) 2005 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC 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.
-
- GCC 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 GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-extern void ms1_init_expanders (void);
-extern void ms1_expand_prologue (void);
-extern void ms1_expand_epilogue (enum epilogue_type);
-extern unsigned ms1_compute_frame_size (int);
-extern void ms1_override_options (void);
-extern int ms1_initial_elimination_offset (int, int);
-extern const char * ms1_asm_output_opcode (FILE *, const char *);
-extern int ms1_epilogue_uses (int);
-extern void ms1_add_loop (void);
-
-#ifdef TREE_CODE
-extern const char * ms1_cannot_inline_p (tree);
-extern int ms1_function_arg_boundary (enum machine_mode, tree);
-extern void ms1_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-#endif
-
-#ifdef RTX_CODE
-extern void ms1_expand_eh_return (rtx *);
-extern void ms1_emit_eh_epilogue (rtx *);
-extern void ms1_print_operand (FILE *, rtx, int);
-extern void ms1_print_operand_address (FILE *, rtx);
-extern int ms1_check_split (rtx, enum machine_mode);
-extern int ms1_reg_ok_for_base_p (rtx, int);
-extern int ms1_legitimate_address_p (enum machine_mode, rtx, int);
-/* Predicates for machine description. */
-extern int uns_arith_operand (rtx, enum machine_mode);
-extern int arith_operand (rtx, enum machine_mode);
-extern int reg_or_0_operand (rtx, enum machine_mode);
-extern int big_const_operand (rtx, enum machine_mode);
-extern int single_const_operand (rtx, enum machine_mode);
-extern void ms1_emit_cbranch (enum rtx_code, rtx, rtx, rtx);
-extern void ms1_set_memflags (rtx);
-extern rtx ms1_return_addr_rtx (int);
-extern void ms1_split_words (enum machine_mode, enum machine_mode, rtx *);
-extern void ms1_final_prescan_insn (rtx, rtx *, int);
-#endif
-
-#ifdef TREE_CODE
-#ifdef RTX_CODE
-extern void ms1_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
-extern rtx ms1_function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int, int);
-extern void ms1_va_start (tree, rtx);
-extern enum reg_class ms1_secondary_reload_class (enum reg_class, enum machine_mode, rtx);
-extern rtx ms1_function_value (tree, enum machine_mode, tree);
-#endif
-#endif
diff --git a/gcc/config/ms1/mt.c b/gcc/config/ms1/mt.c
deleted file mode 100644
index 3695f0fb8b4..00000000000
--- a/gcc/config/ms1/mt.c
+++ /dev/null
@@ -1,2498 +0,0 @@
-/* Target definitions for the MorphoRISC1
- Copyright (C) 2005 Free Software Foundation, Inc.
- Contributed by Red Hat, Inc.
-
- This file is part of GCC.
-
- GCC 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.
-
- GCC 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 GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "real.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "insn-attr.h"
-#include "recog.h"
-#include "toplev.h"
-#include "output.h"
-#include "integrate.h"
-#include "tree.h"
-#include "function.h"
-#include "expr.h"
-#include "optabs.h"
-#include "libfuncs.h"
-#include "flags.h"
-#include "tm_p.h"
-#include "ggc.h"
-#include "insn-flags.h"
-#include "obstack.h"
-#include "except.h"
-#include "target.h"
-#include "target-def.h"
-#include "basic-block.h"
-
-/* Frame pointer register mask. */
-#define FP_MASK (1 << (GPR_FP))
-
-/* Link register mask. */
-#define LINK_MASK (1 << (GPR_LINK))
-
-/* First GPR. */
-#define MS1_INT_ARG_FIRST 1
-
-/* Given a SIZE in bytes, advance to the next word. */
-#define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* A C structure for machine-specific, per-function data.
- This is added to the cfun structure. */
-struct machine_function GTY(())
-{
- /* Flags if __builtin_return_address (n) with n >= 1 was used. */
- int ra_needs_full_frame;
- struct rtx_def * eh_stack_adjust;
- int interrupt_handler;
- int has_loops;
-};
-
-/* Define the information needed to generate branch and scc insns.
- This is stored from the compare operation. */
-struct rtx_def * ms1_compare_op0;
-struct rtx_def * ms1_compare_op1;
-
-/* Current frame information calculated by compute_frame_size. */
-struct ms1_frame_info current_frame_info;
-
-/* Zero structure to initialize current_frame_info. */
-struct ms1_frame_info zero_frame_info;
-
-/* ms1 doesn't have unsigned compares need a library call for this. */
-struct rtx_def * ms1_ucmpsi3_libcall;
-
-static int ms1_flag_delayed_branch;
-
-
-static rtx
-ms1_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED)
-{
- return gen_rtx_REG (Pmode, RETVAL_REGNUM);
-}
-
-/* Implement RETURN_ADDR_RTX. */
-rtx
-ms1_return_addr_rtx (int count)
-{
- if (count != 0)
- return NULL_RTX;
-
- return get_hard_reg_initial_val (Pmode, GPR_LINK);
-}
-
-/* The following variable value indicates the number of nops required
- between the current instruction and the next instruction to avoid
- any pipeline hazards. */
-static int ms1_nops_required = 0;
-static const char * ms1_nop_reasons = "";
-
-/* Implement ASM_OUTPUT_OPCODE. */
-const char *
-ms1_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED, const char *ptr)
-{
- if (ms1_nops_required)
- fprintf (f, ";# need %d nops because of %s\n\t",
- ms1_nops_required, ms1_nop_reasons);
-
- while (ms1_nops_required)
- {
- fprintf (f, "or r0, r0, r0\n\t");
- -- ms1_nops_required;
- }
-
- return ptr;
-}
-
-/* Given an insn, return whether it's a memory operation or a branch
- operation, otherwise return TYPE_ARITH. */
-static enum attr_type
-ms1_get_attr_type (rtx complete_insn)
-{
- rtx insn = PATTERN (complete_insn);
-
- if (JUMP_P (complete_insn))
- return TYPE_BRANCH;
- if (CALL_P (complete_insn))
- return TYPE_BRANCH;
-
- if (GET_CODE (insn) != SET)
- return TYPE_ARITH;
-
- if (SET_DEST (insn) == pc_rtx)
- return TYPE_BRANCH;
-
- if (GET_CODE (SET_DEST (insn)) == MEM)
- return TYPE_STORE;
-
- if (GET_CODE (SET_SRC (insn)) == MEM)
- return TYPE_LOAD;
-
- return TYPE_ARITH;
-}
-
-/* A helper routine for insn_dependent_p called through note_stores. */
-
-static void
-insn_dependent_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
-{
- rtx * pinsn = (rtx *) data;
-
- if (*pinsn && reg_mentioned_p (x, *pinsn))
- *pinsn = NULL_RTX;
-}
-
-/* Return true if anything in insn X is (anti,output,true)
- dependent on anything in insn Y. */
-
-static bool
-insn_dependent_p (rtx x, rtx y)
-{
- rtx tmp;
-
- if (! INSN_P (x) || ! INSN_P (y))
- return 0;
-
- tmp = PATTERN (y);
- note_stores (PATTERN (x), insn_dependent_p_1, &tmp);
- if (tmp == NULL_RTX)
- return true;
-
- tmp = PATTERN (x);
- note_stores (PATTERN (y), insn_dependent_p_1, &tmp);
- return (tmp == NULL_RTX);
-}
-
-
-/* Return true if anything in insn X is true dependent on anything in
- insn Y. */
-static bool
-insn_true_dependent_p (rtx x, rtx y)
-{
- rtx tmp;
-
- if (! INSN_P (x) || ! INSN_P (y))
- return 0;
-
- tmp = PATTERN (y);
- note_stores (PATTERN (x), insn_dependent_p_1, &tmp);
- return (tmp == NULL_RTX);
-}
-
-/* The following determines the number of nops that need to be
- inserted between the previous instructions and current instruction
- to avoid pipeline hazards on the ms1 processor. Remember that
- the function is not called for asm insns. */
-
-void
-ms1_final_prescan_insn (rtx insn,
- rtx * opvec ATTRIBUTE_UNUSED,
- int noperands ATTRIBUTE_UNUSED)
-{
- rtx prev_i;
- enum attr_type prev_attr;
-
- ms1_nops_required = 0;
- ms1_nop_reasons = "";
-
- /* ms2 constraints are dealt with in reorg. */
- if (ms1_cpu == PROCESSOR_MS2)
- return;
-
- /* Only worry about real instructions. */
- if (! INSN_P (insn))
- return;
-
- /* Find the previous real instructions. */
- for (prev_i = PREV_INSN (insn);
- prev_i != NULL
- && (! INSN_P (prev_i)
- || GET_CODE (PATTERN (prev_i)) == USE
- || GET_CODE (PATTERN (prev_i)) == CLOBBER);
- prev_i = PREV_INSN (prev_i))
- {
- /* If we meet a barrier, there is no flow through here. */
- if (BARRIER_P (prev_i))
- return;
- }
-
- /* If there isn't one then there is nothing that we need do. */
- if (prev_i == NULL || ! INSN_P (prev_i))
- return;
-
- prev_attr = ms1_get_attr_type (prev_i);
-
- /* Delayed branch slots already taken care of by delay branch scheduling. */
- if (prev_attr == TYPE_BRANCH)
- return;
-
- switch (ms1_get_attr_type (insn))
- {
- case TYPE_LOAD:
- case TYPE_STORE:
- /* Avoid consecutive memory operation. */
- if ((prev_attr == TYPE_LOAD || prev_attr == TYPE_STORE)
- && ms1_cpu == PROCESSOR_MS1_64_001)
- {
- ms1_nops_required = 1;
- ms1_nop_reasons = "consecutive mem ops";
- }
- /* Drop through. */
-
- case TYPE_ARITH:
- case TYPE_COMPLEX:
- /* One cycle of delay is required between load
- and the dependent arithmetic instruction. */
- if (prev_attr == TYPE_LOAD
- && insn_true_dependent_p (prev_i, insn))
- {
- ms1_nops_required = 1;
- ms1_nop_reasons = "load->arith dependency delay";
- }
- break;
-
- case TYPE_BRANCH:
- if (insn_dependent_p (prev_i, insn))
- {
- if (prev_attr == TYPE_ARITH
- && ms1_cpu == PROCESSOR_MS1_64_001)
- {
- /* One cycle of delay between arith
- instructions and branch dependent on arith. */
- ms1_nops_required = 1;
- ms1_nop_reasons = "arith->branch dependency delay";
- }
- else if (prev_attr == TYPE_LOAD)
- {
- /* Two cycles of delay are required
- between load and dependent branch. */
- if (ms1_cpu == PROCESSOR_MS1_64_001)
- ms1_nops_required = 2;
- else
- ms1_nops_required = 1;
- ms1_nop_reasons = "load->branch dependency delay";
- }
- }
- break;
-
- default:
- fatal_insn ("ms1_final_prescan_insn, invalid insn #1", insn);
- break;
- }
-}
-
-/* Print debugging information for a frame. */
-static void
-ms1_debug_stack (struct ms1_frame_info * info)
-{
- int regno;
-
- if (!info)
- {
- error ("info pointer NULL");
- gcc_unreachable ();
- }
-
- fprintf (stderr, "\nStack information for function %s:\n",
- ((current_function_decl && DECL_NAME (current_function_decl))
- ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
- : "<unknown>"));
-
- fprintf (stderr, "\ttotal_size = %d\n", info->total_size);
- fprintf (stderr, "\tpretend_size = %d\n", info->pretend_size);
- fprintf (stderr, "\targs_size = %d\n", info->args_size);
- fprintf (stderr, "\textra_size = %d\n", info->extra_size);
- fprintf (stderr, "\treg_size = %d\n", info->reg_size);
- fprintf (stderr, "\tvar_size = %d\n", info->var_size);
- fprintf (stderr, "\tframe_size = %d\n", info->frame_size);
- fprintf (stderr, "\treg_mask = 0x%x\n", info->reg_mask);
- fprintf (stderr, "\tsave_fp = %d\n", info->save_fp);
- fprintf (stderr, "\tsave_lr = %d\n", info->save_lr);
- fprintf (stderr, "\tinitialized = %d\n", info->initialized);
- fprintf (stderr, "\tsaved registers =");
-
- /* Print out reg_mask in a more readable format. */
- for (regno = GPR_R0; regno <= GPR_LAST; regno++)
- if ( (1 << regno) & info->reg_mask)
- fprintf (stderr, " %s", reg_names[regno]);
-
- putc ('\n', stderr);
- fflush (stderr);
-}
-
-/* Print a memory address as an operand to reference that memory location. */
-
-static void
-ms1_print_operand_simple_address (FILE * file, rtx addr)
-{
- if (!addr)
- error ("PRINT_OPERAND_ADDRESS, null pointer");
-
- else
- switch (GET_CODE (addr))
- {
- case REG:
- fprintf (file, "%s, #0", reg_names [REGNO (addr)]);
- break;
-
- case PLUS:
- {
- rtx reg = 0;
- rtx offset = 0;
- rtx arg0 = XEXP (addr, 0);
- rtx arg1 = XEXP (addr, 1);
-
- if (GET_CODE (arg0) == REG)
- {
- reg = arg0;
- offset = arg1;
- if (GET_CODE (offset) == REG)
- fatal_insn ("PRINT_OPERAND_ADDRESS, 2 regs", addr);
- }
-
- else if (GET_CODE (arg1) == REG)
- reg = arg1, offset = arg0;
- else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
- {
- fprintf (file, "%s, #", reg_names [GPR_R0]);
- output_addr_const (file, addr);
- break;
- }
- fprintf (file, "%s, #", reg_names [REGNO (reg)]);
- output_addr_const (file, offset);
- break;
- }
-
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_INT:
- case CONST:
- output_addr_const (file, addr);
- break;
-
- default:
- fatal_insn ("PRINT_OPERAND_ADDRESS, invalid insn #1", addr);
- break;
- }
-}
-
-/* Implement PRINT_OPERAND_ADDRESS. */
-void
-ms1_print_operand_address (FILE * file, rtx addr)
-{
- if (GET_CODE (addr) == AND
- && GET_CODE (XEXP (addr, 1)) == CONST_INT
- && INTVAL (XEXP (addr, 1)) == -3)
- ms1_print_operand_simple_address (file, XEXP (addr, 0));
- else
- ms1_print_operand_simple_address (file, addr);
-}
-
-/* Implement PRINT_OPERAND. */
-void
-ms1_print_operand (FILE * file, rtx x, int code)
-{
- switch (code)
- {
- case '#':
- /* Output a nop if there's nothing for the delay slot. */
- if (dbr_sequence_length () == 0)
- fputs ("\n\tor r0, r0, r0", file);
- return;
-
- case 'H':
- fprintf(file, "#%%hi16(");
- output_addr_const (file, x);
- fprintf(file, ")");
- return;
-
- case 'L':
- fprintf(file, "#%%lo16(");
- output_addr_const (file, x);
- fprintf(file, ")");
- return;
-
- case 'N':
- fprintf(file, "#%ld", ~INTVAL (x));
- return;
-
- case 'z':
- if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
- {
- fputs (reg_names[GPR_R0], file);
- return;
- }
-
- case 0:
- /* Handled below. */
- break;
-
- default:
- /* output_operand_lossage ("ms1_print_operand: unknown code"); */
- fprintf (file, "unknown code");
- return;
- }
-
- switch (GET_CODE (x))
- {
- case REG:
- fputs (reg_names [REGNO (x)], file);
- break;
-
- case CONST:
- case CONST_INT:
- fprintf(file, "#%ld", INTVAL (x));
- break;
-
- case MEM:
- ms1_print_operand_address(file, XEXP (x,0));
- break;
-
- case LABEL_REF:
- case SYMBOL_REF:
- output_addr_const (file, x);
- break;
-
- default:
- fprintf(file, "Uknown code: %d", GET_CODE (x));
- break;
- }
-
- return;
-}
-
-/* Implement INIT_CUMULATIVE_ARGS. */
-void
-ms1_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, rtx libname,
- tree fndecl ATTRIBUTE_UNUSED, int incoming)
-{
- *cum = 0;
-
- if (TARGET_DEBUG_ARG)
- {
- fprintf (stderr, "\nms1_init_cumulative_args:");
-
- if (incoming)
- fputs (" incoming", stderr);
-
- if (fntype)
- {
- tree ret_type = TREE_TYPE (fntype);
- fprintf (stderr, " return = %s,",
- tree_code_name[ (int)TREE_CODE (ret_type) ]);
- }
-
- if (libname && GET_CODE (libname) == SYMBOL_REF)
- fprintf (stderr, " libname = %s", XSTR (libname, 0));
-
- if (cfun->returns_struct)
- fprintf (stderr, " return-struct");
-
- putc ('\n', stderr);
- }
-}
-
-/* Compute the slot number to pass an argument in.
- Returns the slot number or -1 if passing on the stack.
-
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis).
- INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.
- *PREGNO records the register number to use if scalar type. */
-
-static int
-ms1_function_arg_slotno (const CUMULATIVE_ARGS * cum,
- enum machine_mode mode,
- tree type,
- int named ATTRIBUTE_UNUSED,
- int incoming_p ATTRIBUTE_UNUSED,
- int * pregno)
-{
- int regbase = MS1_INT_ARG_FIRST;
- int slotno = * cum;
-
- if (mode == VOIDmode || targetm.calls.must_pass_in_stack (mode, type))
- return -1;
-
- if (slotno >= MS1_NUM_ARG_REGS)
- return -1;
-
- * pregno = regbase + slotno;
-
- return slotno;
-}
-
-/* Implement FUNCTION_ARG. */
-rtx
-ms1_function_arg (const CUMULATIVE_ARGS * cum,
- enum machine_mode mode,
- tree type,
- int named,
- int incoming_p)
-{
- int slotno, regno;
- rtx reg;
-
- slotno = ms1_function_arg_slotno (cum, mode, type, named, incoming_p,
- & regno);
-
- if (slotno == -1)
- reg = NULL_RTX;
- else
- reg = gen_rtx_REG (mode, regno);
-
- return reg;
-}
-
-/* Implement FUNCTION_ARG_ADVANCE. */
-void
-ms1_function_arg_advance (CUMULATIVE_ARGS * cum,
- enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- int named)
-{
- int slotno, regno;
-
- /* We pass 0 for incoming_p here, it doesn't matter. */
- slotno = ms1_function_arg_slotno (cum, mode, type, named, 0, &regno);
-
- * cum += (mode != BLKmode
- ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
- : ROUND_ADVANCE (int_size_in_bytes (type)));
-
- if (TARGET_DEBUG_ARG)
- fprintf (stderr,
- "ms1_function_arg_advance: words = %2d, mode = %4s, named = %d, size = %3d\n",
- *cum, GET_MODE_NAME (mode), named,
- (*cum) * UNITS_PER_WORD);
-}
-
-/* Implement hook TARGET_ARG_PARTIAL_BYTES.
-
- Returns the number of bytes at the beginning of an argument that
- 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. */
-static int
-ms1_arg_partial_bytes (CUMULATIVE_ARGS * pcum,
- enum machine_mode mode,
- tree type,
- bool named ATTRIBUTE_UNUSED)
-{
- int cum = * pcum;
- int words;
-
- if (mode == BLKmode)
- words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
- else
- words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-
- if (! targetm.calls.pass_by_reference (& cum, mode, type, named)
- && cum < MS1_NUM_ARG_REGS
- && (cum + words) > MS1_NUM_ARG_REGS)
- {
- int bytes = (MS1_NUM_ARG_REGS - cum) * UNITS_PER_WORD;
-
- if (TARGET_DEBUG)
- fprintf (stderr, "function_arg_partial_nregs = %d\n", bytes);
- return bytes;
- }
-
- return 0;
-}
-
-
-/* Implement TARGET_PASS_BY_REFERENCE hook. */
-static bool
-ms1_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type,
- bool named ATTRIBUTE_UNUSED)
-{
- return (type && int_size_in_bytes (type) > 4 * UNITS_PER_WORD);
-}
-
-/* Implement FUNCTION_ARG_BOUNDARY. */
-int
-ms1_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED)
-{
- return BITS_PER_WORD;
-}
-
-/* Implement REG_OK_FOR_BASE_P. */
-int
-ms1_reg_ok_for_base_p (rtx x, int strict)
-{
- if (strict)
- return (((unsigned) REGNO (x)) < FIRST_PSEUDO_REGISTER);
- return 1;
-}
-
-/* Helper function of ms1_legitimate_address_p. Return true if XINSN
- is a simple address, otherwise false. */
-static bool
-ms1_legitimate_simple_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx xinsn,
- int strict)
-{
- if (TARGET_DEBUG)
- {
- fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
- strict ? "" : "not ");
- debug_rtx (xinsn);
- }
-
- if (GET_CODE (xinsn) == REG && ms1_reg_ok_for_base_p (xinsn, strict))
- return true;
-
- if (GET_CODE (xinsn) == PLUS
- && GET_CODE (XEXP (xinsn, 0)) == REG
- && ms1_reg_ok_for_base_p (XEXP (xinsn, 0), strict)
- && GET_CODE (XEXP (xinsn, 1)) == CONST_INT
- && SMALL_INT (XEXP (xinsn, 1)))
- return true;
-
- return false;
-}
-
-
-/* Helper function of GO_IF_LEGITIMATE_ADDRESS. Return non-zero if
- XINSN is a legitimate address on MS1. */
-int
-ms1_legitimate_address_p (enum machine_mode mode,
- rtx xinsn,
- int strict)
-{
- if (ms1_legitimate_simple_address_p (mode, xinsn, strict))
- return 1;
-
- if ((mode) == SImode
- && GET_CODE (xinsn) == AND
- && GET_CODE (XEXP (xinsn, 1)) == CONST_INT
- && INTVAL (XEXP (xinsn, 1)) == -3)
- return ms1_legitimate_simple_address_p (mode, XEXP (xinsn, 0), strict);
- else
- return 0;
-}
-
-/* Return truth value of whether OP can be used as an operands where a
- register or 16 bit unsigned integer is needed. */
-
-int
-uns_arith_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
- return 1;
-
- return register_operand (op, mode);
-}
-
-/* Return truth value of whether OP can be used as an operands where a
- 16 bit integer is needed. */
-
-int
-arith_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT && SMALL_INT (op))
- return 1;
-
- return register_operand (op, mode);
-}
-
-/* Return truth value of whether OP is a register or the constant 0. */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case CONST_INT:
- return INTVAL (op) == 0;
-
- case REG:
- case SUBREG:
- return register_operand (op, mode);
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* Return truth value of whether OP is a constant that requires two
- loads to put in a register. */
-
-int
-big_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
- return 1;
-
- return 0;
-}
-
-/* Return truth value of whether OP is a constant that require only
- one load to put in a register. */
-
-int
-single_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (big_const_operand (op, mode)
- || GET_CODE (op) == CONST
- || GET_CODE (op) == LABEL_REF
- || GET_CODE (op) == SYMBOL_REF)
- return 0;
-
- return 1;
-}
-
-/* True if the current function is an interrupt handler
- (either via #pragma or an attribute specification). */
-int interrupt_handler;
-enum processor_type ms1_cpu;
-
-static struct machine_function *
-ms1_init_machine_status (void)
-{
- struct machine_function *f;
-
- f = ggc_alloc_cleared (sizeof (struct machine_function));
-
- return f;
-}
-
-/* Implement OVERRIDE_OPTIONS. */
-void
-ms1_override_options (void)
-{
- if (ms1_cpu_string != NULL)
- {
- if (!strcasecmp (ms1_cpu_string, "MS1-64-001"))
- ms1_cpu = PROCESSOR_MS1_64_001;
- else if (!strcasecmp (ms1_cpu_string, "MS1-16-002"))
- ms1_cpu = PROCESSOR_MS1_16_002;
- else if (!strcasecmp (ms1_cpu_string, "MS1-16-003"))
- ms1_cpu = PROCESSOR_MS1_16_003;
- else if (!strcasecmp (ms1_cpu_string, "MS2"))
- ms1_cpu = PROCESSOR_MS2;
- else
- error ("bad value (%s) for -march= switch", ms1_cpu_string);
- }
- else
- ms1_cpu = PROCESSOR_MS2;
-
- if (flag_exceptions)
- {
- flag_omit_frame_pointer = 0;
- flag_gcse = 0;
- }
-
- /* We do delayed branch filling in machine dependent reorg */
- ms1_flag_delayed_branch = flag_delayed_branch;
- flag_delayed_branch = 0;
-
- init_machine_status = ms1_init_machine_status;
-}
-
-/* Do what is necessary for `va_start'. We look at the current function
- to determine if stdarg or varargs is used and return the address of the
- first unnamed parameter. */
-
-static rtx
-ms1_builtin_saveregs (void)
-{
- int first_reg = 0;
- rtx address;
- int regno;
-
- for (regno = first_reg; regno < MS1_NUM_ARG_REGS; regno ++)
- emit_move_insn (gen_rtx_MEM (word_mode,
- gen_rtx_PLUS (Pmode,
- gen_rtx_REG (SImode, ARG_POINTER_REGNUM),
- GEN_INT (UNITS_PER_WORD * regno))),
- gen_rtx_REG (word_mode,
- MS1_INT_ARG_FIRST + regno));
-
- address = gen_rtx_PLUS (Pmode,
- gen_rtx_REG (SImode, ARG_POINTER_REGNUM),
- GEN_INT (UNITS_PER_WORD * first_reg));
- return address;
-}
-
-/* Implement `va_start'. */
-
-void
-ms1_va_start (tree valist, rtx nextarg)
-{
- ms1_builtin_saveregs ();
- std_expand_builtin_va_start (valist, nextarg);
-}
-
-/* Returns the number of bytes offset between the frame pointer and the stack
- pointer for the current function. SIZE is the number of bytes of space
- needed for local variables. */
-
-unsigned int
-ms1_compute_frame_size (int size)
-{
- int regno;
- unsigned int total_size;
- unsigned int var_size;
- unsigned int args_size;
- unsigned int pretend_size;
- unsigned int extra_size;
- unsigned int reg_size;
- unsigned int frame_size;
- unsigned int reg_mask;
-
- var_size = size;
- args_size = current_function_outgoing_args_size;
- pretend_size = current_function_pretend_args_size;
- extra_size = FIRST_PARM_OFFSET (0);
- total_size = extra_size + pretend_size + args_size + var_size;
- reg_size = 0;
- reg_mask = 0;
-
- /* Calculate space needed for registers. */
- for (regno = GPR_R0; regno <= GPR_LAST; regno++)
- {
- if (MUST_SAVE_REGISTER (regno))
- {
- reg_size += UNITS_PER_WORD;
- reg_mask |= 1 << regno;
- }
- }
-
- current_frame_info.save_fp = (regs_ever_live [GPR_FP]
- || frame_pointer_needed
- || interrupt_handler);
- current_frame_info.save_lr = (regs_ever_live [GPR_LINK]
- || profile_flag
- || interrupt_handler);
-
- reg_size += (current_frame_info.save_fp + current_frame_info.save_lr)
- * UNITS_PER_WORD;
- total_size += reg_size;
- total_size = ((total_size + 3) & ~3);
-
- frame_size = total_size;
-
- /* Save computed information. */
- current_frame_info.pretend_size = pretend_size;
- current_frame_info.var_size = var_size;
- current_frame_info.args_size = args_size;
- current_frame_info.reg_size = reg_size;
- current_frame_info.frame_size = args_size + var_size;
- current_frame_info.total_size = total_size;
- current_frame_info.extra_size = extra_size;
- current_frame_info.reg_mask = reg_mask;
- current_frame_info.initialized = reload_completed;
-
- return total_size;
-}
-
-/* Emit code to save REG in stack offset pointed to by MEM.
- STACK_OFFSET is the offset from the SP where the save will happen.
- This function sets the REG_FRAME_RELATED_EXPR note accordingly. */
-static void
-ms1_emit_save_restore (enum save_direction direction,
- rtx reg,
- rtx mem,
- int stack_offset)
-{
- if (direction == FROM_PROCESSOR_TO_MEM)
- {
- rtx insn;
-
- insn = emit_move_insn (mem, reg);
- RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM
- (SImode,
- gen_rtx_PLUS (SImode,
- stack_pointer_rtx,
- GEN_INT (stack_offset))),
- reg),
- REG_NOTES (insn));
- }
- else
- emit_move_insn (reg, mem);
-}
-
-
-/* Emit code to save the frame pointer in the prologue and restore
- frame pointer in epilogue. */
-
-static void
-ms1_emit_save_fp (enum save_direction direction,
- struct ms1_frame_info info)
-{
- rtx base_reg;
- int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK);
- int offset = info.total_size;
- int stack_offset = info.total_size;
-
- /* If there is nothing to save, get out now. */
- if (! info.save_fp && ! info.save_lr && ! reg_mask)
- return;
-
- /* If offset doesn't fit in a 15-bit signed integer,
- uses a scratch registers to get a smaller offset. */
- if (CONST_OK_FOR_LETTER_P(offset, 'O'))
- base_reg = stack_pointer_rtx;
- else
- {
- /* Use the scratch register R9 that holds old stack pointer. */
- base_reg = gen_rtx_REG (SImode, GPR_R9);
- offset = 0;
- }
-
- if (info.save_fp)
- {
- offset -= UNITS_PER_WORD;
- stack_offset -= UNITS_PER_WORD;
- ms1_emit_save_restore (direction, gen_rtx_REG (SImode, GPR_FP),
- gen_rtx_MEM (SImode,
- gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
- stack_offset);
- }
-}
-
-/* Emit code to save registers in the prologue and restore register
- in epilogue. */
-
-static void
-ms1_emit_save_regs (enum save_direction direction,
- struct ms1_frame_info info)
-{
- rtx base_reg;
- int regno;
- int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK);
- int offset = info.total_size;
- int stack_offset = info.total_size;
-
- /* If there is nothing to save, get out now. */
- if (! info.save_fp && ! info.save_lr && ! reg_mask)
- return;
-
- /* If offset doesn't fit in a 15-bit signed integer,
- uses a scratch registers to get a smaller offset. */
- if (CONST_OK_FOR_LETTER_P(offset, 'O'))
- base_reg = stack_pointer_rtx;
- else
- {
- /* Use the scratch register R9 that holds old stack pointer. */
- base_reg = gen_rtx_REG (SImode, GPR_R9);
- offset = 0;
- }
-
- if (info.save_fp)
- {
- /* This just records the space for it, the actual move generated in
- ms1_emit_save_fp (). */
- offset -= UNITS_PER_WORD;
- stack_offset -= UNITS_PER_WORD;
- }
-
- if (info.save_lr)
- {
- offset -= UNITS_PER_WORD;
- stack_offset -= UNITS_PER_WORD;
- ms1_emit_save_restore (direction, gen_rtx_REG (SImode, GPR_LINK),
- gen_rtx_MEM (SImode,
- gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
- stack_offset);
- }
-
- /* Save any needed call-saved regs. */
- for (regno = GPR_R0; regno <= GPR_LAST; regno++)
- {
- if ((reg_mask & (1 << regno)) != 0)
- {
- offset -= UNITS_PER_WORD;
- stack_offset -= UNITS_PER_WORD;
- ms1_emit_save_restore (direction, gen_rtx_REG (SImode, regno),
- gen_rtx_MEM (SImode,
- gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
- stack_offset);
- }
- }
-}
-
-/* Return true if FUNC is a function with the 'interrupt' attribute. */
-static bool
-ms1_interrupt_function_p (tree func)
-{
- tree a;
-
- if (TREE_CODE (func) != FUNCTION_DECL)
- return false;
-
- a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
- return a != NULL_TREE;
-}
-
-/* Generate prologue code. */
-void
-ms1_expand_prologue (void)
-{
- rtx size_rtx, insn;
- unsigned int frame_size;
-
- if (ms1_interrupt_function_p (current_function_decl))
- {
- interrupt_handler = 1;
- if (cfun->machine)
- cfun->machine->interrupt_handler = 1;
- }
-
- ms1_compute_frame_size (get_frame_size ());
-
- if (TARGET_DEBUG_STACK)
- ms1_debug_stack (&current_frame_info);
-
- /* Compute size of stack adjustment. */
- frame_size = current_frame_info.total_size;
-
- /* If offset doesn't fit in a 15-bit signed integer,
- uses a scratch registers to get a smaller offset. */
- if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
- size_rtx = GEN_INT (frame_size);
- else
- {
- /* We do not have any scratch registers. */
- gcc_assert (!interrupt_handler);
-
- size_rtx = gen_rtx_REG (SImode, GPR_R9);
- insn = emit_move_insn (size_rtx, GEN_INT (frame_size & 0xffff0000));
- insn = emit_insn (gen_iorsi3 (size_rtx, size_rtx,
- GEN_INT (frame_size & 0x0000ffff)));
- }
-
- /* Allocate stack for this frame. */
- /* Make stack adjustment and use scratch register if constant too
- large to fit as immediate. */
- if (frame_size)
- {
- insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx));
- RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_MINUS (SImode,
- stack_pointer_rtx,
- GEN_INT (frame_size))),
- REG_NOTES (insn));
- }
-
- /* Set R9 to point to old sp if required for access to register save area. */
- if ( current_frame_info.reg_size != 0
- && !CONST_OK_FOR_LETTER_P (frame_size, 'O'))
- emit_insn (gen_addsi3 (size_rtx, size_rtx, stack_pointer_rtx));
-
- /* Save the frame pointer. */
- ms1_emit_save_fp (FROM_PROCESSOR_TO_MEM, current_frame_info);
-
- /* Now put the frame pointer into the frame pointer register. */
- if (frame_pointer_needed)
- {
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Save the registers. */
- ms1_emit_save_regs (FROM_PROCESSOR_TO_MEM, current_frame_info);
-
- /* If we are profiling, make sure no instructions are scheduled before
- the call to mcount. */
- if (profile_flag)
- emit_insn (gen_blockage ());
-}
-
-/* Implement EPILOGUE_USES. */
-int
-ms1_epilogue_uses (int regno)
-{
- if (cfun->machine && cfun->machine->interrupt_handler && reload_completed)
- return 1;
- return regno == GPR_LINK;
-}
-
-/* Generate epilogue. EH_MODE is NORMAL_EPILOGUE when generating a
- function epilogue, or EH_EPILOGUE when generating an EH
- epilogue. */
-void
-ms1_expand_epilogue (enum epilogue_type eh_mode)
-{
- rtx size_rtx, insn;
- unsigned frame_size;
-
- ms1_compute_frame_size (get_frame_size ());
-
- if (TARGET_DEBUG_STACK)
- ms1_debug_stack (& current_frame_info);
-
- /* Compute size of stack adjustment. */
- frame_size = current_frame_info.total_size;
-
- /* If offset doesn't fit in a 15-bit signed integer,
- uses a scratch registers to get a smaller offset. */
- if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
- size_rtx = GEN_INT (frame_size);
- else
- {
- /* We do not have any scratch registers. */
- gcc_assert (!interrupt_handler);
-
- size_rtx = gen_rtx_REG (SImode, GPR_R9);
- insn = emit_move_insn (size_rtx, GEN_INT (frame_size & 0xffff0000));
- insn = emit_insn (gen_iorsi3 (size_rtx, size_rtx,
- GEN_INT (frame_size & 0x0000ffff)));
- /* Set R9 to point to old sp if required for access to register
- save area. */
- emit_insn (gen_addsi3 (size_rtx, size_rtx, stack_pointer_rtx));
- }
-
- /* Restore sp if there was some possible change to it. */
- if (frame_pointer_needed)
- insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
-
- /* Restore the registers. */
- ms1_emit_save_fp (FROM_MEM_TO_PROCESSOR, current_frame_info);
- ms1_emit_save_regs (FROM_MEM_TO_PROCESSOR, current_frame_info);
-
- /* Make stack adjustment and use scratch register if constant too
- large to fit as immediate. */
- if (frame_size)
- {
- if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
- /* Can handle this with simple add. */
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx));
- else
- /* Scratch reg R9 has the old sp value. */
- insn = emit_move_insn (stack_pointer_rtx,
- gen_rtx_REG (SImode, GPR_R9));
-
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (SImode,
- stack_pointer_rtx,
- GEN_INT (frame_size))),
- REG_NOTES (insn));
- }
-
- if (cfun->machine && cfun->machine->eh_stack_adjust != NULL_RTX)
- /* Perform the additional bump for __throw. */
- emit_insn (gen_addsi3 (stack_pointer_rtx,
- stack_pointer_rtx,
- cfun->machine->eh_stack_adjust));
-
- /* Generate the appropriate return. */
- if (eh_mode == EH_EPILOGUE)
- {
- emit_jump_insn (gen_eh_return_internal ());
- emit_barrier ();
- }
- else if (interrupt_handler)
- emit_jump_insn (gen_return_interrupt_internal ());
- else
- emit_jump_insn (gen_return_internal ());
-
- /* Reset state info for each function. */
- interrupt_handler = 0;
- current_frame_info = zero_frame_info;
- if (cfun->machine)
- cfun->machine->eh_stack_adjust = NULL_RTX;
-}
-
-
-/* Generate code for the "eh_return" pattern. */
-void
-ms1_expand_eh_return (rtx * operands)
-{
- if (GET_CODE (operands[0]) != REG
- || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
- {
- rtx sp = EH_RETURN_STACKADJ_RTX;
-
- emit_move_insn (sp, operands[0]);
- operands[0] = sp;
- }
-
- emit_insn (gen_eh_epilogue (operands[0]));
-}
-
-/* Generate code for the "eh_epilogue" pattern. */
-void
-ms1_emit_eh_epilogue (rtx * operands ATTRIBUTE_UNUSED)
-{
- cfun->machine->eh_stack_adjust = EH_RETURN_STACKADJ_RTX; /* operands[0]; */
- ms1_expand_epilogue (EH_EPILOGUE);
-}
-
-/* Handle an "interrupt" attribute. */
-static tree
-ms1_handle_interrupt_attribute (tree * node,
- tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool * no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes,
- "%qs attribute only applies to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Table of machine attributes. */
-const struct attribute_spec ms1_attribute_table[] =
-{
- /* name, min, max, decl?, type?, func?, handler */
- { "interrupt", 0, 0, false, false, false, ms1_handle_interrupt_attribute },
- { NULL, 0, 0, false, false, false, NULL }
-};
-
-/* Implement INITIAL_ELIMINATION_OFFSET. */
-int
-ms1_initial_elimination_offset (int from, int to)
-{
- ms1_compute_frame_size (get_frame_size ());
-
- if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- return 0;
-
- else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- return current_frame_info.total_size;
-
- else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- return current_frame_info.total_size;
-
- else
- gcc_unreachable ();
-}
-
-/* Generate a compare for CODE. Return a brand-new rtx that
- represents the result of the compare. */
-
-static rtx
-ms1_generate_compare (enum rtx_code code, rtx op0, rtx op1)
-{
- rtx scratch0, scratch1, const_scratch;
-
- switch (code)
- {
- case GTU:
- case LTU:
- case GEU:
- case LEU:
- /* Need to adjust ranges for faking unsigned compares. */
- scratch0 = gen_reg_rtx (SImode);
- scratch1 = gen_reg_rtx (SImode);
- const_scratch = force_reg (SImode, GEN_INT(MS1_MIN_INT));
- emit_insn (gen_addsi3 (scratch0, const_scratch, op0));
- emit_insn (gen_addsi3 (scratch1, const_scratch, op1));
- break;
- default:
- scratch0 = op0;
- scratch1 = op1;
- break;
- }
-
- /* Adjust compare operator to fake unsigned compares. */
- switch (code)
- {
- case GTU:
- code = GT; break;
- case LTU:
- code = LT; break;
- case GEU:
- code = GE; break;
- case LEU:
- code = LE; break;
- default:
- /* do nothing */
- break;
- }
-
- /* Generate the actual compare. */
- return gen_rtx_fmt_ee (code, VOIDmode, scratch0, scratch1);
-}
-
-/* Emit a branch of kind CODE to location LOC. */
-
-void
-ms1_emit_cbranch (enum rtx_code code, rtx loc, rtx op0, rtx op1)
-{
- rtx condition_rtx, loc_ref;
-
- if (! reg_or_0_operand (op0, SImode))
- op0 = copy_to_mode_reg (SImode, op0);
-
- if (! reg_or_0_operand (op1, SImode))
- op1 = copy_to_mode_reg (SImode, op1);
-
- condition_rtx = ms1_generate_compare (code, op0, op1);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
- gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
- loc_ref, pc_rtx)));
-}
-
-/* Subfunction of the following function. Update the flags of any MEM
- found in part of X. */
-
-static void
-ms1_set_memflags_1 (rtx x, int in_struct_p, int volatile_p)
-{
- int i;
-
- switch (GET_CODE (x))
- {
- case SEQUENCE:
- case PARALLEL:
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- ms1_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p);
- break;
-
- case INSN:
- ms1_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p);
- break;
-
- case SET:
- ms1_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p);
- ms1_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p);
- break;
-
- case MEM:
- MEM_IN_STRUCT_P (x) = in_struct_p;
- MEM_VOLATILE_P (x) = volatile_p;
- /* Sadly, we cannot use alias sets because the extra aliasing
- produced by the AND interferes. Given that two-byte quantities
- are the only thing we would be able to differentiate anyway,
- there does not seem to be any point in convoluting the early
- out of the alias check. */
- /* set_mem_alias_set (x, alias_set); */
- break;
-
- default:
- break;
- }
-}
-
-/* Look for any MEMs in the current sequence of insns and set the
- in-struct, unchanging, and volatile flags from the flags in REF.
- If REF is not a MEM, don't do anything. */
-
-void
-ms1_set_memflags (rtx ref)
-{
- rtx insn;
- int in_struct_p, volatile_p;
-
- if (GET_CODE (ref) != MEM)
- return;
-
- in_struct_p = MEM_IN_STRUCT_P (ref);
- volatile_p = MEM_VOLATILE_P (ref);
-
- /* This is only called from ms1.md, after having had something
- generated from one of the insn patterns. So if everything is
- zero, the pattern is already up-to-date. */
- if (! in_struct_p && ! volatile_p)
- return;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- ms1_set_memflags_1 (insn, in_struct_p, volatile_p);
-}
-
-/* Implement SECONDARY_RELOAD_CLASS. */
-enum reg_class
-ms1_secondary_reload_class (enum reg_class class ATTRIBUTE_UNUSED,
- enum machine_mode mode,
- rtx x)
-{
- if ((mode == QImode && (!TARGET_BYTE_ACCESS)) || mode == HImode)
- {
- if (GET_CODE (x) == MEM
- || (GET_CODE (x) == REG && true_regnum (x) == -1)
- || (GET_CODE (x) == SUBREG
- && (GET_CODE (SUBREG_REG (x)) == MEM
- || (GET_CODE (SUBREG_REG (x)) == REG
- && true_regnum (SUBREG_REG (x)) == -1))))
- return GENERAL_REGS;
- }
-
- return NO_REGS;
-}
-
-/* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE
- macros. */
-rtx
-ms1_function_value (tree valtype, enum machine_mode mode, tree func_decl ATTRIBUTE_UNUSED)
-{
- if ((mode) == DImode || (mode) == DFmode)
- return gen_rtx_MEM (mode, gen_rtx_REG (mode, RETURN_VALUE_REGNUM));
-
- if (valtype)
- mode = TYPE_MODE (valtype);
-
- return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
-}
-
-/* Split a move into two smaller pieces.
- MODE indicates the reduced mode. OPERANDS[0] is the original destination
- OPERANDS[1] is the original src. The new destinations are
- OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
- and OPERANDS[5]. */
-
-void
-ms1_split_words (enum machine_mode nmode,
- enum machine_mode omode,
- rtx *operands)
-{
- rtx dl,dh; /* src/dest pieces. */
- rtx sl,sh;
- int move_high_first = 0; /* Assume no overlap. */
-
- switch (GET_CODE (operands[0])) /* Dest. */
- {
- case SUBREG:
- case REG:
- if ((GET_CODE (operands[1]) == REG
- || GET_CODE (operands[1]) == SUBREG)
- && true_regnum (operands[0]) <= true_regnum (operands[1]))
- move_high_first = 1;
-
- if (GET_CODE (operands[0]) == SUBREG)
- {
- dl = gen_rtx_SUBREG (nmode, SUBREG_REG (operands[0]),
- SUBREG_BYTE (operands[0]) + GET_MODE_SIZE (nmode));
- dh = gen_rtx_SUBREG (nmode, SUBREG_REG (operands[0]), SUBREG_BYTE (operands[0]));
- }
- else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0]))
- {
- int r = REGNO (operands[0]);
- dh = gen_rtx_REG (nmode, r);
- dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
- }
- else
- {
- dh = gen_rtx_SUBREG (nmode, operands[0], 0);
- dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode));
- }
- break;
-
- case MEM:
- switch (GET_CODE (XEXP (operands[0], 0)))
- {
- case POST_INC:
- case POST_DEC:
- gcc_unreachable ();
- default:
- dl = operand_subword (operands[0],
- GET_MODE_SIZE (nmode)/UNITS_PER_WORD,
- 0, omode);
- dh = operand_subword (operands[0], 0, 0, omode);
- }
- break;
- default:
- gcc_unreachable ();
- }
-
- switch (GET_CODE (operands[1]))
- {
- case REG:
- if (! IS_PSEUDO_P (operands[1]))
- {
- int r = REGNO (operands[1]);
-
- sh = gen_rtx_REG (nmode, r);
- sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
- }
- else
- {
- sh = gen_rtx_SUBREG (nmode, operands[1], 0);
- sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode));
- }
- break;
-
- case CONST_DOUBLE:
- if (operands[1] == const0_rtx)
- sh = sl = const0_rtx;
- else
- split_double (operands[1], & sh, & sl);
- break;
-
- case CONST_INT:
- if (operands[1] == const0_rtx)
- sh = sl = const0_rtx;
- else
- {
- int vl, vh;
-
- switch (nmode)
- {
- default:
- gcc_unreachable ();
- }
-
- sl = GEN_INT (vl);
- sh = GEN_INT (vh);
- }
- break;
-
- case SUBREG:
- sl = gen_rtx_SUBREG (nmode,
- SUBREG_REG (operands[1]),
- SUBREG_BYTE (operands[1]) + GET_MODE_SIZE (nmode));
- sh = gen_rtx_SUBREG (nmode,
- SUBREG_REG (operands[1]),
- SUBREG_BYTE (operands[1]));
- break;
-
- case MEM:
- switch (GET_CODE (XEXP (operands[1], 0)))
- {
- case POST_DEC:
- case POST_INC:
- gcc_unreachable ();
- break;
- default:
- sl = operand_subword (operands[1],
- GET_MODE_SIZE (nmode)/UNITS_PER_WORD,
- 0, omode);
- sh = operand_subword (operands[1], 0, 0, omode);
-
- /* Check if the DF load is going to clobber the register
- used for the address, and if so make sure that is going
- to be the second move. */
- if (GET_CODE (dl) == REG
- && true_regnum (dl)
- == true_regnum (XEXP (XEXP (sl, 0 ), 0)))
- move_high_first = 1;
- }
- break;
- default:
- gcc_unreachable ();
- }
-
- if (move_high_first)
- {
- operands[2] = dh;
- operands[3] = sh;
- operands[4] = dl;
- operands[5] = sl;
- }
- else
- {
- operands[2] = dl;
- operands[3] = sl;
- operands[4] = dh;
- operands[5] = sh;
- }
- return;
-}
-
-/* Implement TARGET_MUST_PASS_IN_STACK hook. */
-static bool
-ms1_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)
-{
- return (((type) != 0
- && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
- || TREE_ADDRESSABLE (type))));
-}
-
-/* Increment the counter for the number of loop instructions in the
- current function. */
-
-void ms1_add_loop (void)
-{
- cfun->machine->has_loops++;
-}
-
-
-/* Maxium loop nesting depth. */
-#define MAX_LOOP_DEPTH 4
-/* Maxium size of a loop (allows some headroom for delayed branch slot
- filling. */
-#define MAX_LOOP_LENGTH (200 * 4)
-
-/* We need to keep a vector of basic blocks */
-DEF_VEC_P (basic_block);
-DEF_VEC_ALLOC_P (basic_block,heap);
-
-/* And a vector of loops */
-typedef struct loop_info *loop_info;
-DEF_VEC_P (loop_info);
-DEF_VEC_ALLOC_P (loop_info,heap);
-
-/* Information about a loop we have found (or are in the process of
- finding). */
-struct loop_info GTY (())
-{
- /* loop number, for dumps */
- int loop_no;
-
- /* Predecessor block of the loop. This is the one that falls into
- the loop and contains the initialization instruction. */
- basic_block predecessor;
-
- /* First block in the loop. This is the one branched to by the dbnz
- insn. */
- basic_block head;
-
- /* Last block in the loop (the one with the dbnz insn */
- basic_block tail;
-
- /* The successor block of the loop. This is the one the dbnz insn
- falls into. */
- basic_block successor;
-
- /* The dbnz insn. */
- rtx dbnz;
-
- /* The initialization insn. */
- rtx init;
-
- /* The new initialization instruction. */
- rtx loop_init;
-
- /* The new ending instruction. */
- rtx loop_end;
-
- /* The new label placed at the end of the loop. */
- rtx end_label;
-
- /* The nesting depth of the loop. Set to -1 for a bad loop. */
- int depth;
-
- /* The length of the loop. */
- int length;
-
- /* Next loop in the graph. */
- struct loop_info *next;
-
- /* Vector of blocks only within the loop, (excluding those within
- inner loops). */
- VEC (basic_block,heap) *blocks;
-
- /* Vector of inner loops within this loop */
- VEC (loop_info,heap) *loops;
-};
-
-/* Information used during loop detection. */
-typedef struct loop_work GTY(())
-{
- /* Basic block to be scanned. */
- basic_block block;
-
- /* Loop it will be within. */
- loop_info loop;
-} loop_work;
-
-/* Work list. */
-DEF_VEC_O (loop_work);
-DEF_VEC_ALLOC_O (loop_work,heap);
-
-/* Determine the nesting and length of LOOP. Return false if the loop
- is bad. */
-
-static bool
-ms1_loop_nesting (loop_info loop)
-{
- loop_info inner;
- unsigned ix;
- int inner_depth = 0;
-
- if (!loop->depth)
- {
- /* Make sure we only have one entry point. */
- if (EDGE_COUNT (loop->head->preds) == 2)
- {
- loop->predecessor = EDGE_PRED (loop->head, 0)->src;
- if (loop->predecessor == loop->tail)
- /* We wanted the other predecessor. */
- loop->predecessor = EDGE_PRED (loop->head, 1)->src;
-
- /* We can only place a loop insn on a fall through edge of a
- single exit block. */
- if (EDGE_COUNT (loop->predecessor->succs) != 1
- || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU))
- loop->predecessor = NULL;
- }
-
- /* Mark this loop as bad for now. */
- loop->depth = -1;
- if (loop->predecessor)
- {
- for (ix = 0; VEC_iterate (loop_info, loop->loops, ix++, inner);)
- {
- if (!inner->depth)
- ms1_loop_nesting (inner);
-
- if (inner->depth < 0)
- {
- inner_depth = -1;
- break;
- }
-
- if (inner_depth < inner->depth)
- inner_depth = inner->depth;
- loop->length += inner->length;
- }
-
- /* Set the proper loop depth, if it was good. */
- if (inner_depth >= 0)
- loop->depth = inner_depth + 1;
- }
- }
- return (loop->depth > 0
- && loop->predecessor
- && loop->depth < MAX_LOOP_DEPTH
- && loop->length < MAX_LOOP_LENGTH);
-}
-
-/* Determine the length of block BB. */
-
-static int
-ms1_block_length (basic_block bb)
-{
- int length = 0;
- rtx insn;
-
- for (insn = BB_HEAD (bb);
- insn != NEXT_INSN (BB_END (bb));
- insn = NEXT_INSN (insn))
- {
- if (!INSN_P (insn))
- continue;
- if (CALL_P (insn))
- {
- /* Calls are not allowed in loops. */
- length = MAX_LOOP_LENGTH + 1;
- break;
- }
-
- length += get_attr_length (insn);
- }
- return length;
-}
-
-/* Scan the blocks of LOOP (and its inferiors) looking for uses of
- REG. Return true, if we find any. Don't count the loop's dbnz
- insn if it matches DBNZ. */
-
-static bool
-ms1_scan_loop (loop_info loop, rtx reg, rtx dbnz)
-{
- unsigned ix;
- loop_info inner;
- basic_block bb;
-
- for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
- {
- rtx insn;
-
- for (insn = BB_HEAD (bb);
- insn != NEXT_INSN (BB_END (bb));
- insn = NEXT_INSN (insn))
- {
- if (!INSN_P (insn))
- continue;
- if (insn == dbnz)
- continue;
- if (reg_mentioned_p (reg, PATTERN (insn)))
- return true;
- }
- }
- for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
- if (ms1_scan_loop (inner, reg, NULL_RTX))
- return true;
-
- return false;
-}
-
-/* MS2 has a loop instruction which needs to be placed just before the
- loop. It indicates the end of the loop and specifies the number of
- loop iterations. It can be nested with an automatically maintained
- stack of counter and end address registers. It's an ideal
- candidate for doloop. Unfortunately, gcc presumes that loops
- always end with an explicit instriction, and the doloop_begin
- instruction is not a flow control instruction so it can be
- scheduled earlier than just before the start of the loop. To make
- matters worse, the optimization pipeline can duplicate loop exit
- and entrance blocks and fails to track abnormally exiting loops.
- Thus we cannot simply use doloop.
-
- What we do is emit a dbnz pattern for the doloop optimization, and
- let that be optimized as normal. Then in machine dependent reorg
- we have to repeat the loop searching algorithm. We use the
- flow graph to find closed loops ending in a dbnz insn. We then try
- and convert it to use the loop instruction. The conditions are,
-
- * the loop has no abnormal exits, duplicated end conditions or
- duplicated entrance blocks
-
- * the loop counter register is only used in the dbnz instruction
- within the loop
-
- * we can find the instruction setting the initial value of the loop
- counter
-
- * the loop is not executed more than 65535 times. (This might be
- changed to 2^32-1, and would therefore allow variable initializers.)
-
- * the loop is not nested more than 4 deep 5) there are no
- subroutine calls in the loop. */
-
-static void
-ms1_reorg_loops (FILE *dump_file)
-{
- basic_block bb;
- loop_info loops = NULL;
- loop_info loop;
- int nloops = 0;
- unsigned dwork = 0;
- VEC (loop_work,heap) *works = VEC_alloc (loop_work,heap,20);
- loop_work *work;
- edge e;
- edge_iterator ei;
- bool replaced = false;
-
- /* Find all the possible loop tails. This means searching for every
- dbnz instruction. For each one found, create a loop_info
- structure and add the head block to the work list. */
- FOR_EACH_BB (bb)
- {
- rtx tail = BB_END (bb);
-
- while (GET_CODE (tail) == NOTE)
- tail = PREV_INSN (tail);
-
- bb->aux = NULL;
- if (recog_memoized (tail) == CODE_FOR_decrement_and_branch_until_zero)
- {
- /* A possible loop end */
-
- loop = XNEW (struct loop_info);
- loop->next = loops;
- loops = loop;
- loop->tail = bb;
- loop->head = BRANCH_EDGE (bb)->dest;
- loop->successor = FALLTHRU_EDGE (bb)->dest;
- loop->predecessor = NULL;
- loop->dbnz = tail;
- loop->depth = 0;
- loop->length = ms1_block_length (bb);
- loop->blocks = VEC_alloc (basic_block, heap, 20);
- VEC_quick_push (basic_block, loop->blocks, bb);
- loop->loops = NULL;
- loop->loop_no = nloops++;
-
- loop->init = loop->end_label = NULL_RTX;
- loop->loop_init = loop->loop_end = NULL_RTX;
-
- work = VEC_safe_push (loop_work, heap, works, NULL);
- work->block = loop->head;
- work->loop = loop;
-
- bb->aux = loop;
-
- if (dump_file)
- {
- fprintf (dump_file, ";; potential loop %d ending at\n",
- loop->loop_no);
- print_rtl_single (dump_file, tail);
- }
- }
- }
-
- /* Now find all the closed loops.
- until work list empty,
- if block's auxptr is set
- if != loop slot
- if block's loop's start != block
- mark loop as bad
- else
- append block's loop's fallthrough block to worklist
- increment this loop's depth
- else if block is exit block
- mark loop as bad
- else
- set auxptr
- for each target of block
- add to worklist */
- while (VEC_iterate (loop_work, works, dwork++, work))
- {
- loop = work->loop;
- bb = work->block;
- if (bb == EXIT_BLOCK_PTR)
- /* We've reached the exit block. The loop must be bad. */
- loop->depth = -1;
- else if (!bb->aux)
- {
- /* We've not seen this block before. Add it to the loop's
- list and then add each successor to the work list. */
- bb->aux = loop;
- loop->length += ms1_block_length (bb);
- VEC_safe_push (basic_block, heap, loop->blocks, bb);
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- if (!VEC_space (loop_work, works, 1))
- {
- if (dwork)
- {
- VEC_block_remove (loop_work, works, 0, dwork);
- dwork = 0;
- }
- else
- VEC_reserve (loop_work, heap, works, 1);
- }
- work = VEC_quick_push (loop_work, works, NULL);
- work->block = EDGE_SUCC (bb, ei.index)->dest;
- work->loop = loop;
- }
- }
- else if (bb->aux != loop)
- {
- /* We've seen this block in a different loop. If it's not
- the other loop's head, then this loop must be bad.
- Otherwise, the other loop might be a nested loop, so
- continue from that loop's successor. */
- loop_info other = bb->aux;
-
- if (other->head != bb)
- loop->depth = -1;
- else
- {
- VEC_safe_push (loop_info, heap, loop->loops, other);
- work = VEC_safe_push (loop_work, heap, works, NULL);
- work->loop = loop;
- work->block = other->successor;
- }
- }
- }
- VEC_free (loop_work, heap, works);
-
- /* Now optimize the loops. */
- for (loop = loops; loop; loop = loop->next)
- {
- rtx iter_reg, insn, init_insn;
- rtx init_val, loop_end, loop_init, end_label, head_label;
-
- if (!ms1_loop_nesting (loop))
- {
- if (dump_file)
- fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
- continue;
- }
-
- /* Get the loop iteration register. */
- iter_reg = SET_DEST (XVECEXP (PATTERN (loop->dbnz), 0, 1));
-
- if (!REG_P (iter_reg))
- {
- /* Spilled */
- if (dump_file)
- fprintf (dump_file, ";; loop %d has spilled iteration count\n",
- loop->loop_no);
- continue;
- }
-
- /* Look for the initializing insn */
- init_insn = NULL_RTX;
- for (insn = BB_END (loop->predecessor);
- insn != PREV_INSN (BB_HEAD (loop->predecessor));
- insn = PREV_INSN (insn))
- {
- if (!INSN_P (insn))
- continue;
- if (reg_mentioned_p (iter_reg, PATTERN (insn)))
- {
- rtx set = single_set (insn);
-
- if (set && rtx_equal_p (iter_reg, SET_DEST (set)))
- init_insn = insn;
- break;
- }
- }
-
- if (!init_insn)
- {
- if (dump_file)
- fprintf (dump_file, ";; loop %d has no initializer\n",
- loop->loop_no);
- continue;
- }
- if (dump_file)
- {
- fprintf (dump_file, ";; loop %d initialized by\n",
- loop->loop_no);
- print_rtl_single (dump_file, init_insn);
- }
-
- init_val = PATTERN (init_insn);
- if (GET_CODE (init_val) == SET)
- init_val = SET_SRC (init_val);
- if (GET_CODE (init_val) != CONST_INT || INTVAL (init_val) >= 65535)
- {
- if (dump_file)
- fprintf (dump_file, ";; loop %d has complex initializer\n",
- loop->loop_no);
- continue;
- }
-
- /* Scan all the blocks to make sure they don't use iter_reg. */
- if (ms1_scan_loop (loop, iter_reg, loop->dbnz))
- {
- if (dump_file)
- fprintf (dump_file, ";; loop %d uses iterator\n",
- loop->loop_no);
- continue;
- }
-
- /* The loop is good for replacement. */
-
- /* loop is 1 based, dbnz is zero based. */
- init_val = GEN_INT (INTVAL (init_val) + 1);
-
- iter_reg = gen_rtx_REG (SImode, LOOP_FIRST + loop->depth - 1);
- end_label = gen_label_rtx ();
- head_label = XEXP (SET_SRC (XVECEXP (PATTERN (loop->dbnz), 0, 0)), 1);
- loop_end = gen_loop_end (iter_reg, head_label);
- loop_init = gen_loop_init (iter_reg, init_val, end_label);
- loop->init = init_insn;
- loop->end_label = end_label;
- loop->loop_init = loop_init;
- loop->loop_end = loop_end;
- replaced = true;
-
- if (dump_file)
- {
- fprintf (dump_file, ";; replacing loop %d initializer with\n",
- loop->loop_no);
- print_rtl_single (dump_file, loop->loop_init);
- fprintf (dump_file, ";; replacing loop %d terminator with\n",
- loop->loop_no);
- print_rtl_single (dump_file, loop->loop_end);
- }
- }
-
- /* Now apply the optimizations. Do it this way so we don't mess up
- the flow graph half way through. */
- for (loop = loops; loop; loop = loop->next)
- if (loop->loop_init)
- {
- emit_jump_insn_after (loop->loop_init, BB_END (loop->predecessor));
- delete_insn (loop->init);
- emit_label_before (loop->end_label, loop->dbnz);
- emit_jump_insn_before (loop->loop_end, loop->dbnz);
- delete_insn (loop->dbnz);
- }
-
- /* Free up the loop structures */
- while (loops)
- {
- loop = loops;
- loops = loop->next;
- VEC_free (loop_info, heap, loop->loops);
- VEC_free (basic_block, heap, loop->blocks);
- XDELETE (loop);
- }
-
- if (replaced && dump_file)
- {
- fprintf (dump_file, ";; Replaced loops\n");
- print_rtl (dump_file, get_insns ());
- }
-}
-
-/* Structures to hold branch information during reorg. */
-typedef struct branch_info
-{
- rtx insn; /* The branch insn. */
-
- struct branch_info *next;
-} branch_info;
-
-typedef struct label_info
-{
- rtx label; /* The label. */
- branch_info *branches; /* branches to this label. */
- struct label_info *next;
-} label_info;
-
-/* Chain of labels found in current function, used during reorg. */
-static label_info *ms1_labels;
-
-/* If *X is a label, add INSN to the list of branches for that
- label. */
-
-static int
-ms1_add_branches (rtx *x, void *insn)
-{
- if (GET_CODE (*x) == LABEL_REF)
- {
- branch_info *branch = xmalloc (sizeof (*branch));
- rtx label = XEXP (*x, 0);
- label_info *info;
-
- for (info = ms1_labels; info; info = info->next)
- if (info->label == label)
- break;
-
- if (!info)
- {
- info = xmalloc (sizeof (*info));
- info->next = ms1_labels;
- ms1_labels = info;
-
- info->label = label;
- info->branches = NULL;
- }
-
- branch->next = info->branches;
- info->branches = branch;
- branch->insn = insn;
- }
- return 0;
-}
-
-/* If BRANCH has a filled delay slot, check if INSN is dependent upon
- it. If so, undo the delay slot fill. Returns the next insn, if
- we patch out the branch. Returns the branch insn, if we cannot
- patch out the branch (due to anti-dependency in the delay slot).
- In that case, the caller must insert nops at the branch target. */
-
-static rtx
-ms1_check_delay_slot (rtx branch, rtx insn)
-{
- rtx slot;
- rtx tmp;
- rtx p;
- rtx jmp;
-
- gcc_assert (GET_CODE (PATTERN (branch)) == SEQUENCE);
- if (INSN_DELETED_P (branch))
- return NULL_RTX;
- slot = XVECEXP (PATTERN (branch), 0, 1);
-
- tmp = PATTERN (insn);
- note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
- if (tmp)
- /* Not dependent. */
- return NULL_RTX;
-
- /* Undo the delay slot. */
- jmp = XVECEXP (PATTERN (branch), 0, 0);
-
- tmp = PATTERN (jmp);
- note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
- if (!tmp)
- /* Anti dependent. */
- return branch;
-
- p = PREV_INSN (branch);
- NEXT_INSN (p) = slot;
- PREV_INSN (slot) = p;
- NEXT_INSN (slot) = jmp;
- PREV_INSN (jmp) = slot;
- NEXT_INSN (jmp) = branch;
- PREV_INSN (branch) = jmp;
- XVECEXP (PATTERN (branch), 0, 0) = NULL_RTX;
- XVECEXP (PATTERN (branch), 0, 1) = NULL_RTX;
- delete_insn (branch);
- return jmp;
-}
-
-/* Insert nops to satisfy pipeline constraints. We only deal with ms2
- constraints here. Earlier CPUs are dealt with by inserting nops with
- final_prescan (but that can lead to inferior code, and is
- impractical with ms2's JAL hazard).
-
- ms2 dynamic constraints
- 1) a load and a following use must be separated by one insn
- 2) an insn and a following dependent call must be separated by two insns
-
- only arith insns are placed in delay slots so #1 cannot happen with
- a load in a delay slot. #2 can happen with an arith insn in the
- delay slot. */
-
-static void
-ms1_reorg_hazard (void)
-{
- rtx insn, next;
-
- /* Find all the branches */
- for (insn = get_insns ();
- insn;
- insn = NEXT_INSN (insn))
- {
- rtx jmp;
-
- if (!INSN_P (insn))
- continue;
-
- jmp = PATTERN (insn);
-
- if (GET_CODE (jmp) != SEQUENCE)
- /* If it's not got a filled delay slot, then it can't
- conflict. */
- continue;
-
- jmp = XVECEXP (jmp, 0, 0);
-
- if (recog_memoized (jmp) == CODE_FOR_tablejump)
- for (jmp = XEXP (XEXP (XVECEXP (PATTERN (jmp), 0, 1), 0), 0);
- !JUMP_TABLE_DATA_P (jmp);
- jmp = NEXT_INSN (jmp))
- continue;
-
- for_each_rtx (&PATTERN (jmp), ms1_add_branches, insn);
- }
-
- /* Now scan for dependencies. */
- for (insn = get_insns ();
- insn && !INSN_P (insn);
- insn = NEXT_INSN (insn))
- continue;
-
- for (;
- insn;
- insn = next)
- {
- rtx jmp, tmp;
- enum attr_type attr;
-
- gcc_assert (INSN_P (insn) && !INSN_DELETED_P (insn));
- for (next = NEXT_INSN (insn);
- next && !INSN_P (next);
- next = NEXT_INSN (next))
- continue;
-
- jmp = insn;
- if (GET_CODE (PATTERN (insn)) == SEQUENCE)
- jmp = XVECEXP (PATTERN (insn), 0, 0);
-
- attr = recog_memoized (jmp) >= 0 ? get_attr_type (jmp) : TYPE_UNKNOWN;
-
- if (next && attr == TYPE_LOAD)
- {
- /* A load. See if NEXT is dependent, and if so insert a
- nop. */
-
- tmp = PATTERN (next);
- if (GET_CODE (tmp) == SEQUENCE)
- tmp = PATTERN (XVECEXP (tmp, 0, 0));
- note_stores (PATTERN (insn), insn_dependent_p_1, &tmp);
- if (!tmp)
- emit_insn_after (gen_nop (), insn);
- }
-
- if (attr == TYPE_CALL)
- {
- /* A call. Make sure we're not dependent on either of the
- previous two dynamic instructions. */
- int nops = 0;
- int count;
- rtx prev = insn;
- rtx rescan = NULL_RTX;
-
- for (count = 2; count && !nops;)
- {
- int type;
-
- prev = PREV_INSN (prev);
- if (!prev)
- {
- /* If we reach the start of the function, we must
- presume the caller set the address in the delay
- slot of the call instruction. */
- nops = count;
- break;
- }
-
- if (BARRIER_P (prev))
- break;
- if (LABEL_P (prev))
- {
- /* Look at branches to this label. */
- label_info *label;
- branch_info *branch;
-
- for (label = ms1_labels;
- label;
- label = label->next)
- if (label->label == prev)
- {
- for (branch = label->branches;
- branch;
- branch = branch->next)
- {
- tmp = ms1_check_delay_slot (branch->insn, jmp);
-
- if (tmp == branch->insn)
- {
- nops = count;
- break;
- }
-
- if (tmp && branch->insn == next)
- rescan = tmp;
- }
- break;
- }
- continue;
- }
- if (!INSN_P (prev))
- continue;
-
- if (GET_CODE (PATTERN (prev)) == SEQUENCE)
- {
- /* Look at the delay slot. */
- tmp = ms1_check_delay_slot (prev, jmp);
- if (tmp == prev)
- nops = count;
- break;
- }
-
- type = (INSN_CODE (prev) >= 0 ? get_attr_type (prev)
- : TYPE_COMPLEX);
- if (type == TYPE_CALL || type == TYPE_BRANCH)
- break;
-
- if (type == TYPE_LOAD
- || type == TYPE_ARITH
- || type == TYPE_COMPLEX)
- {
- tmp = PATTERN (jmp);
- note_stores (PATTERN (prev), insn_dependent_p_1, &tmp);
- if (!tmp)
- {
- nops = count;
- break;
- }
- }
-
- if (INSN_CODE (prev) >= 0)
- {
- rtx set = single_set (prev);
-
- /* A noop set will get deleted in a later split pass,
- so we can't count on it for hazard avoidance. */
- if (!set || !set_noop_p (set))
- count--;
- }
- }
-
- if (rescan)
- for (next = NEXT_INSN (rescan);
- next && !INSN_P (next);
- next = NEXT_INSN (next))
- continue;
- while (nops--)
- emit_insn_before (gen_nop (), insn);
- }
- }
-
- /* Free the data structures. */
- while (ms1_labels)
- {
- label_info *label = ms1_labels;
- branch_info *branch, *next;
-
- ms1_labels = label->next;
- for (branch = label->branches; branch; branch = next)
- {
- next = branch->next;
- free (branch);
- }
- free (label);
- }
-}
-
-/* Fixup the looping instructions, do delayed branch scheduling, fixup
- scheduling hazards. */
-
-static void
-ms1_machine_reorg (void)
-{
- if (cfun->machine->has_loops)
- ms1_reorg_loops (dump_file);
-
- if (ms1_flag_delayed_branch)
- dbr_schedule (get_insns (), dump_file);
-
- if (ms1_cpu == PROCESSOR_MS2)
- ms1_reorg_hazard ();
-}
-
-/* Initialize the GCC target structure. */
-const struct attribute_spec ms1_attribute_table[];
-
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE ms1_attribute_table
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX ms1_struct_value_rtx
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
-#undef TARGET_PASS_BY_REFERENCE
-#define TARGET_PASS_BY_REFERENCE ms1_pass_by_reference
-#undef TARGET_MUST_PASS_IN_STACK
-#define TARGET_MUST_PASS_IN_STACK ms1_pass_in_stack
-#undef TARGET_ARG_PARTIAL_BYTES
-#define TARGET_ARG_PARTIAL_BYTES ms1_arg_partial_bytes
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG ms1_machine_reorg
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-#include "gt-ms1.h"
diff --git a/gcc/config/ms1/mt.h b/gcc/config/ms1/mt.h
deleted file mode 100644
index eff36c7cbaa..00000000000
--- a/gcc/config/ms1/mt.h
+++ /dev/null
@@ -1,879 +0,0 @@
-/* Target Definitions for MorphoRISC1
- Copyright (C) 2005 Free Software Foundation, Inc.
- Contributed by Red Hat, Inc.
-
- This file is part of GCC.
-
- GCC 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.
-
- GCC 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 GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-extern struct rtx_def * ms1_ucmpsi3_libcall;
-
-enum processor_type
-{
- PROCESSOR_MS1_64_001,
- PROCESSOR_MS1_16_002,
- PROCESSOR_MS1_16_003,
- PROCESSOR_MS2
-};
-
-enum epilogue_type
-{
- EH_EPILOGUE,
- NORMAL_EPILOGUE
-};
-
-extern enum processor_type ms1_cpu;
-
-
-/* A C string constant that tells the GCC driver program options to pass to
- the assembler. */
-#undef ASM_SPEC
-#define ASM_SPEC "%{march=*} %{!march=*: -march=ms2}"
-
-/* A string to pass to at the end of the command given to the linker. */
-#undef LIB_SPEC
-#define LIB_SPEC "--start-group -lc -lsim --end-group \
-%{msim: ; \
-march=ms1-64-001:-T 64-001.ld%s; \
-march=MS1-64-001:-T 64-001.ld%s; \
-march=ms1-16-002:-T 16-002.ld%s; \
-march=MS1-16-002:-T 16-002.ld%s; \
-march=ms1-16-003:-T 16-003.ld%s; \
-march=MS1-16-003:-T 16-003.ld%s; \
-march=ms2:-T ms2.ld%s; \
-march=MS2:-T ms2.ld%s; \
- : -T ms2.ld}"
-
-/* A string to pass at the very beginning of the command given to the
- linker. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{msim:crt0.o%s;\
-march=ms1-64-001:%{!mno-crt0:crt0-64-001.o%s} startup-64-001.o%s; \
-march=MS1-64-001:%{!mno-crt0:crt0-64-001.o%s} startup-64-001.o%s; \
-march=ms1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
-march=MS1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
-march=ms1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
-march=MS1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
-march=ms2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s; \
-march=MS2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s; \
- :%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s} \
-crti.o%s crtbegin.o%s"
-
-/* A string to pass at the end of the command given to the linker. */
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "%{msim:exit.o%s; \
-march=ms1-64-001:exit-64-001.o%s; \
-march=MS1-64-001:exit-64-001.o%s; \
-march=ms1-16-002:exit-16-002.o%s; \
-march=MS1-16-002:exit-16-002.o%s; \
-march=ms1-16-003:exit-16-003.o%s; \
-march=MS1-16-003:exit-16-003.o%s; \
-march=ms2:exit-ms2.o%s; \
-march=MS2:exit-ms2.o%s; \
- :exit-ms2.o%s} \
- crtend.o%s crtn.o%s"
-
-/* Run-time target specifications. */
-
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("ms1"); \
- builtin_assert ("machine=ms1"); \
- } \
- while (0)
-
-#define TARGET_MS1_64_001 (ms1_cpu == PROCESSOR_MS1_64_001)
-#define TARGET_MS1_16_002 (ms1_cpu == PROCESSOR_MS1_16_002)
-#define TARGET_MS1_16_003 (ms1_cpu == PROCESSOR_MS1_16_003)
-#define TARGET_MS2 (ms1_cpu == PROCESSOR_MS2)
-
-#define TARGET_VERSION fprintf (stderr, " (ms1)");
-
-#define OVERRIDE_OPTIONS ms1_override_options ()
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-
-/* Storage Layout. */
-
-#define BITS_BIG_ENDIAN 0
-
-#define BYTES_BIG_ENDIAN 1
-
-#define WORDS_BIG_ENDIAN 1
-
-#define UNITS_PER_WORD 4
-
-/* A macro to update MODE and UNSIGNEDP when an object whose type is TYPE and
- which has the specified mode and signedness is to be stored in a register.
- This macro is only called when TYPE is a scalar type.
-
- On most RISC machines, which only have operations that operate on a full
- register, define this macro to set M to `word_mode' if M is an integer mode
- narrower than `BITS_PER_WORD'. In most cases, only integer modes should be
- widened because wider-precision floating-point operations are usually more
- expensive than their narrower counterparts.
-
- For most machines, the macro definition does not change UNSIGNEDP. However,
- some machines, have instructions that preferentially handle either signed or
- unsigned quantities of certain modes. For example, on the DEC Alpha, 32-bit
- loads from memory and 32-bit add instructions sign-extend the result to 64
- bits. On such machines, set UNSIGNEDP according to which kind of extension
- is more efficient.
-
- Do not define this macro if it would never modify MODE. */
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
- do \
- { \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- (MODE) = SImode; \
- } \
- while (0)
-
-/* Normal alignment required for function parameters on the stack, in bits.
- All stack parameters receive at least this much alignment regardless of data
- type. On most machines, this is the same as the size of an integer. */
-#define PARM_BOUNDARY 32
-
-/* Define this macro to the minimum alignment enforced by hardware for
- the stack pointer on this machine. The definition is a C
- expression for the desired alignment (measured in bits). This
- value is used as a default if PREFERRED_STACK_BOUNDARY is not
- defined. On most machines, this should be the same as
- PARM_BOUNDARY. */
-#define STACK_BOUNDARY 32
-
-/* Alignment required for a function entry point, in bits. */
-#define FUNCTION_BOUNDARY 32
-
-/* Biggest alignment that any data type can require on this machine,
- in bits. */
-#define BIGGEST_ALIGNMENT 32
-
-/* If defined, a C expression to compute the alignment for a variable
- in the static store. TYPE is the data type, and ALIGN is the
- alignment that the object would ordinarily have. The value of this
- macro is used instead of that alignment to align the object.
-
- If this macro is not defined, then ALIGN is used. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE \
- && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-/* If defined, a C expression to compute the alignment given to a constant that
- is being placed in memory. CONSTANT is the constant and ALIGN is the
- alignment that the object would ordinarily have. The value of this macro is
- used instead of that alignment to align the object.
-
- If this macro is not defined, then ALIGN is used.
-
- The typical use of this macro is to increase alignment for string constants
- to be word aligned so that `strcpy' calls that copy constants can be done
- inline. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-/* Number of bits which any structure or union's size must be a multiple of.
- Each structure or union's size is rounded up to a multiple of this.
-
- If you do not define this macro, the default is the same as `BITS_PER_UNIT'. */
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Define this macro to be the value 1 if instructions will fail to work if
- given data not on the nominal alignment. If instructions will merely go
- slower in that case, define this macro as 0. */
-#define STRICT_ALIGNMENT 1
-
-/* Define this if you wish to imitate the way many other C compilers handle
- alignment of bitfields and the structures that contain them. */
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/* Layout of Source Language Data Types. */
-
-#define INT_TYPE_SIZE 32
-
-#define SHORT_TYPE_SIZE 16
-
-#define LONG_TYPE_SIZE 32
-
-#define LONG_LONG_TYPE_SIZE 64
-
-#define CHAR_TYPE_SIZE 8
-
-#define FLOAT_TYPE_SIZE 32
-
-#define DOUBLE_TYPE_SIZE 64
-
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-#define DEFAULT_SIGNED_CHAR 1
-
-/* Register Basics. */
-
-/* General purpose registers. */
-#define GPR_FIRST 0 /* First gpr */
-#define GPR_LAST 15 /* Last possible gpr */
-
-#define GPR_R0 0 /* Always 0 */
-#define GPR_R7 7 /* Used as a scratch register */
-#define GPR_R8 8 /* Used as a scratch register */
-#define GPR_R9 9 /* Used as a scratch register */
-#define GPR_R10 10 /* Used as a scratch register */
-#define GPR_R11 11 /* Used as a scratch register */
-#define GPR_FP 12 /* Frame pointer */
-#define GPR_SP 13 /* Stack pointer */
-#define GPR_LINK 14 /* Saved return address as
- seen by the caller */
-#define GPR_INTERRUPT_LINK 15 /* hold return addres for interrupts */
-
-#define LOOP_FIRST (GPR_LAST + 1)
-#define LOOP_LAST (LOOP_FIRST + 3)
-
-/* Argument register that is eliminated in favor of the frame and/or stack
- pointer. Also add register to point to where the return address is
- stored. */
-#define SPECIAL_REG_FIRST (LOOP_LAST + 1)
-#define SPECIAL_REG_LAST (SPECIAL_REG_FIRST)
-#define ARG_POINTER_REGNUM (SPECIAL_REG_FIRST + 0)
-#define SPECIAL_REG_P(R) ((R) == SPECIAL_REG_FIRST)
-
-/* The first/last register that can contain the arguments to a function. */
-#define FIRST_ARG_REGNUM 1
-#define LAST_ARG_REGNUM 4
-
-/* The register used to hold functions return value */
-#define RETVAL_REGNUM 11
-
-#define FIRST_PSEUDO_REGISTER (SPECIAL_REG_LAST + 1)
-
-#define IS_PSEUDO_P(R) (REGNO (R) >= FIRST_PSEUDO_REGISTER)
-
-/* R0 always has the value 0
- R10 static link
- R12 FP pointer to active frame
- R13 SP pointer to top of stack
- R14 RA return address
- R15 IRA interrupt return address. */
-#define FIXED_REGISTERS { 1, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1 \
- }
-
-/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
- general) by function calls as well as for fixed registers. This macro
- therefore identifies the registers that are not available for general
- allocation of values that must live across function calls. */
-#define CALL_USED_REGISTERS { 1, 1, 1, 1, 1, 0, 0, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1 \
- }
-
-
-/* How Values Fit in Registers. */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
-
-/* A C expression that is nonzero if a value of mode MODE1 is
- accessible in mode MODE2 without copying. */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
-/* Register Classes. */
-
-enum reg_class
-{
- NO_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
-
-#define REG_CLASS_NAMES {"NO_REGS", "ALL_REGS" }
-
-#define REG_CLASS_CONTENTS \
- { \
- { 0x0 }, \
- { 0x000fffff }, \
- }
-
-/* A C expression whose value is a register class containing hard register
- REGNO. In general there is more than one such class; choose a class which
- is "minimal", meaning that no smaller class also contains the register. */
-#define REGNO_REG_CLASS(REGNO) GENERAL_REGS
-
-#define BASE_REG_CLASS GENERAL_REGS
-
-#define INDEX_REG_CLASS NO_REGS
-
-#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
-
-#define REGNO_OK_FOR_BASE_P(NUM) 1
-
-#define REGNO_OK_FOR_INDEX_P(NUM) 1
-
-/* A C expression that places additional restrictions on the register class to
- use when it is necessary to copy value X into a register in class CLASS.
- The value is a register class; perhaps CLASS, or perhaps another, smaller
- class. On many machines, the following definition is safe:
-
- #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
-*/
-#define PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS)
-
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ms1_secondary_reload_class((CLASS), (MODE), (X))
-
-/* A C expression for the maximum number of consecutive registers of
- class CLASS needed to hold a value of mode MODE. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* For MorphoRISC1:
-
- `I' is used for the range of constants an arithmetic insn can
- actually contain (16 bits signed integers).
-
- `J' is used for the range which is just zero (ie, $r0).
-
- `K' is used for the range of constants a logical insn can actually
- contain (16 bit zero-extended integers).
-
- `L' is used for the range of constants that be loaded with lui
- (ie, the bottom 16 bits are zero).
-
- `M' is used for the range of constants that take two words to load
- (ie, not matched by `I', `K', and `L').
-
- `N' is used for negative 16 bit constants other than -65536.
-
- `O' is a 15 bit signed integer.
-
- `P' is used for positive 16 bit constants. */
-
-#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
-#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (INTVAL (X)) < 0x10000)
-
-/* A C expression that defines the machine-dependent operand
- constraint letters that specify particular ranges of integer
- values. If C is one of those letters, the expression should check
- that VALUE, an integer, is in the appropriate range and return 1 if
- so, 0 otherwise. If C is not one of those letters, the value
- should be 0 regardless of VALUE. */
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'I' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000) \
- : (C) == 'J' ? ((VALUE) == 0) \
- : (C) == 'K' ? ((unsigned HOST_WIDE_INT) (VALUE) < 0x10000) \
- : (C) == 'L' ? (((VALUE) & 0x0000ffff) == 0 \
- && (((VALUE) & ~2147483647) == 0 \
- || ((VALUE) & ~2147483647) == ~2147483647)) \
- : (C) == 'M' ? ((((VALUE) & ~0x0000ffff) != 0) \
- && (((VALUE) & ~0x0000ffff) != ~0x0000ffff) \
- && (((VALUE) & 0x0000ffff) != 0 \
- || (((VALUE) & ~2147483647) != 0 \
- && ((VALUE) & ~2147483647) != ~2147483647))) \
- : (C) == 'N' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0xffff) < 0xffff) \
- : (C) == 'O' ? ((unsigned HOST_WIDE_INT) ((VALUE) + 0x4000) < 0x8000) \
- : (C) == 'P' ? ((VALUE) != 0 && (((VALUE) & ~0x0000ffff) == 0)) \
- : 0)
-
-/* A C expression that defines the machine-dependent operand constraint letters
- (`G', `H') that specify particular ranges of `const_double' values. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
-
-/* Most negative value represent on ms1 */
-#define MS1_MIN_INT 0x80000000
-
-/* Basic Stack Layout. */
-
-enum save_direction
-{
- FROM_PROCESSOR_TO_MEM,
- FROM_MEM_TO_PROCESSOR
-};
-
-/* Tell prologue and epilogue if register REGNO should be saved / restored.
- The return address and frame pointer are treated separately.
- Don't consider them here. */
-#define MUST_SAVE_REGISTER(regno) \
- ( (regno) != GPR_LINK \
- && (regno) != GPR_FP \
- && (regno) != GPR_SP \
- && (regno) != GPR_R0 \
- && (( regs_ever_live [regno] && ! call_used_regs [regno] ) \
- /* Save ira register in an interrupt handler. */ \
- || (interrupt_handler && (regno) == GPR_INTERRUPT_LINK) \
- /* Save any register used in an interrupt handler. */ \
- || (interrupt_handler && regs_ever_live [regno]) \
- /* Save call clobbered registers in non-leaf interrupt \
- handlers. */ \
- || (interrupt_handler && call_used_regs[regno] \
- && !current_function_is_leaf) \
- ||(current_function_calls_eh_return \
- && (regno == GPR_R7 || regno == GPR_R8)) \
- ) \
- )
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* Offset from the frame pointer to the first local variable slot to be
- allocated.
-
- If `FRAME_GROWS_DOWNWARD', find the next slot's offset by
- subtracting the first slot's length from `STARTING_FRAME_OFFSET'.
- Otherwise, it is found by adding the length of the first slot to
- the value `STARTING_FRAME_OFFSET'. */
-#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
-
-/* Offset from the argument pointer register to the first argument's address.
- On some machines it may depend on the data type of the function.
-
- If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first
- argument's address. */
-#define FIRST_PARM_OFFSET(FUNDECL) 0
-
-#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \
- ms1_return_addr_rtx (COUNT)
-
-/* A C expression whose value is RTL representing the location of the incoming
- return address at the beginning of any function, before the prologue. This
- RTL is either a `REG', indicating that the return value is saved in `REG',
- or a `MEM' representing a location in the stack.
-
- You only need to define this macro if you want to support call frame
- debugging information like that provided by DWARF 2. */
-#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (SImode, GPR_LINK)
-
-/* A C expression whose value is an integer giving the offset, in bytes, from
- the value of the stack pointer register to the top of the stack frame at the
- beginning of any function, before the prologue. The top of the frame is
- defined to be the value of the stack pointer in the previous frame, just
- before the call instruction.
-
- You only need to define this macro if you want to support call frame
- debugging information like that provided by DWARF 2. */
-#define INCOMING_FRAME_SP_OFFSET 0
-
-#define STACK_POINTER_REGNUM GPR_SP
-
-#define FRAME_POINTER_REGNUM GPR_FP
-
-/* The register number of the arg pointer register, which is used to
- access the function's argument list. */
-#define ARG_POINTER_REGNUM (SPECIAL_REG_FIRST + 0)
-
-/* Register numbers used for passing a function's static chain pointer. */
-#define STATIC_CHAIN_REGNUM 10
-
-/* A C expression which is nonzero if a function must have and use a frame
- pointer. */
-#define FRAME_POINTER_REQUIRED 0
-
-/* Structure to be filled in by compute_frame_size with register
- save masks, and offsets for the current function. */
-
-struct ms1_frame_info
-{
- unsigned int total_size; /* # Bytes that the entire frame takes up. */
- unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
- unsigned int args_size; /* # Bytes that outgoing arguments take up. */
- unsigned int extra_size;
- unsigned int reg_size; /* # Bytes needed to store regs. */
- unsigned int var_size; /* # Bytes that variables take up. */
- unsigned int frame_size; /* # Bytes in current frame. */
- unsigned int reg_mask; /* Mask of saved registers. */
- unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
- unsigned int save_lr; /* Nonzero if return pointer must be saved. */
- int initialized; /* Nonzero if frame size already calculated. */
-};
-
-extern struct ms1_frame_info current_frame_info;
-
-/* If defined, this macro specifies a table of register pairs used to eliminate
- unneeded registers that point into the stack frame. */
-#define ELIMINABLE_REGS \
-{ \
- {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
-}
-
-/* A C expression that returns non-zero if the compiler is allowed to try to
- replace register number FROM with register number TO. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
- ? ! frame_pointer_needed \
- : 1)
-
-/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It
- specifies the initial difference between the specified pair of
- registers. This macro must be defined if `ELIMINABLE_REGS' is
- defined. */
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- (OFFSET) = ms1_initial_elimination_offset (FROM, TO)
-
-/* If defined, the maximum amount of space required for outgoing
- arguments will be computed and placed into the variable
- `current_function_outgoing_args_size'. */
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-/* Define this if it is the responsibility of the caller to
- allocate the area reserved for arguments passed in registers. */
-#define OUTGOING_REG_PARM_STACK_SPACE
-
-/* The number of register assigned to holding function arguments. */
-#define MS1_NUM_ARG_REGS 4
-
-/* Define this if it is the responsibility of the caller to allocate
- the area reserved for arguments passed in registers. */
-#define REG_PARM_STACK_SPACE(FNDECL) (MS1_NUM_ARG_REGS * UNITS_PER_WORD)
-
-/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the stack
- parameters don't skip the area specified by it. */
-#define STACK_PARMS_IN_REG_PARM_AREA
-
-/* A C expression that should indicate the number of bytes of its own
- arguments that a function pops on returning, or 0 if the function
- pops no arguments and the caller must therefore pop them all after
- the function returns. */
-#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ms1_function_arg (& (CUM), (MODE), (TYPE), (NAMED), FALSE)
-
-#define CUMULATIVE_ARGS int
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- ms1_init_cumulative_args (& (CUM), FNTYPE, LIBNAME, FNDECL, FALSE)
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ms1_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-
-#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
- ms1_function_arg_boundary (MODE, TYPE)
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >= FIRST_ARG_REGNUM && ((REGNO) <= LAST_ARG_REGNUM))
-
-#define RETURN_VALUE_REGNUM RETVAL_REGNUM
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- ms1_function_value (VALTYPE, TYPE_MODE(VALTYPE), FUNC)
-
-#define LIBCALL_VALUE(MODE) \
- ms1_function_value (NULL_TREE, MODE, NULL_TREE)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RETURN_VALUE_REGNUM)
-
-/* A C expression which can inhibit the returning of certain function
- values in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) (int_size_in_bytes (TYPE) > UNITS_PER_WORD)
-
-/* Define this macro to be 1 if all structure and union return values must be
- in memory. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-/* Define this macro as a C expression that is nonzero if the return
- instruction or the function epilogue ignores the value of the stack
- pointer; in other words, if it is safe to delete an instruction to
- adjust the stack pointer before a return from the function. */
-#define EXIT_IGNORE_STACK 1
-
-#define EPILOGUE_USES(REGNO) ms1_epilogue_uses(REGNO)
-
-/* Define this macro if the function epilogue contains delay slots to which
- instructions from the rest of the function can be "moved". */
-#define DELAY_SLOTS_FOR_EPILOGUE 1
-
-/* A C expression that returns 1 if INSN can be placed in delay slot number N
- of the epilogue. */
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) 0
-
-#define FUNCTION_PROFILER(FILE, LABELNO) gcc_unreachable ()
-
-#define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \
- ms1_va_start (VALIST, NEXTARG)
-
-/* Trampolines are not implemented. */
-#define TRAMPOLINE_SIZE 0
-
-#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN)
-
-/* ?? What is this -- aldyh ?? */
-#define UCMPSI3_LIBCALL "__ucmpsi3"
-
-/* Addressing Modes. */
-
-/* A C expression that is 1 if the RTX X is a constant which is a valid
- address. */
-#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
-
-/* A number, the maximum number of registers that can appear in a valid memory
- address. Note that it is up to you to specify a value equal to the maximum
- number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */
-#define MAX_REGS_PER_ADDRESS 1
-
-#ifdef REG_OK_STRICT
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (ms1_legitimate_address_p (MODE, X, 1)) \
- goto ADDR; \
-}
-#else
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (ms1_legitimate_address_p (MODE, X, 0)) \
- goto ADDR; \
-}
-#endif
-
-#ifdef REG_OK_STRICT
-#define REG_OK_FOR_BASE_P(X) ms1_reg_ok_for_base_p (X, 1)
-#else
-#define REG_OK_FOR_BASE_P(X) ms1_reg_ok_for_base_p (X, 0)
-#endif
-
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
-
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-/* A C expression for the cost of moving data of mode M between a register and
- memory. A value of 2 is the default; this cost is relative to those in
- `REGISTER_MOVE_COST'.
-
- If moving between registers and memory is more expensive than between two
- registers, you should define this macro to express the relative cost. */
-#define MEMORY_MOVE_COST(M,C,I) 10
-
-/* Define this macro as a C expression which is nonzero if accessing less than
- a word of memory (i.e. a `char' or a `short') is no faster than accessing a
- word of memory. */
-#define SLOW_BYTE_ACCESS 1
-
-#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) 1
-
-#define TEXT_SECTION_ASM_OP ".text"
-
-#define DATA_SECTION_ASM_OP ".data"
-
-#define BSS_SECTION_ASM_OP "\t.section\t.bss"
-
-/* A C string constant for text to be output before each `asm' statement or
- group of consecutive ones. Normally this is `"#APP"', which is a comment
- that has no effect on most assemblers but tells the GNU assembler that it
- must check the lines that follow for all valid assembler constructs. */
-#define ASM_APP_ON "#APP\n"
-
-/* A C string constant for text to be output after each `asm' statement or
- group of consecutive ones. Normally this is `"#NO_APP"', which tells the
- GNU assembler to resume making the time-saving assumptions that are valid
- for ordinary compiler output. */
-#define ASM_APP_OFF "#NO_APP\n"
-
-/* This is how to output an assembler line defining a `char' constant. */
-#define ASM_OUTPUT_CHAR(FILE, VALUE) \
- do \
- { \
- fprintf (FILE, "\t.byte\t"); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
- } \
- while (0)
-
-/* This is how to output an assembler line defining a `short' constant. */
-#define ASM_OUTPUT_SHORT(FILE, VALUE) \
- do \
- { \
- fprintf (FILE, "\t.hword\t"); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
- } \
- while (0)
-
-/* This is how to output an assembler line defining an `int' constant.
- We also handle symbol output here. */
-#define ASM_OUTPUT_INT(FILE, VALUE) \
- do \
- { \
- fprintf (FILE, "\t.word\t"); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
- } \
- while (0)
-
-/* A C statement to output to the stdio stream STREAM an assembler instruction
- to assemble a single byte containing the number VALUE.
-
- This declaration must be present. */
-#define ASM_OUTPUT_BYTE(STREAM, VALUE) \
- fprintf (STREAM, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE))
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.globl "
-
-#define REGISTER_NAMES \
-{ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", \
- "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", \
- "LOOP1", "LOOP2", "LOOP3", "LOOP4", "ap" }
-
-/* If defined, a C initializer for an array of structures containing a name and
- a register number. This macro defines additional names for hard registers,
- thus allowing the `asm' option in declarations to refer to registers using
- alternate names. */
-#define ADDITIONAL_REGISTER_NAMES \
-{ { "FP", 12}, {"SP", 13}, {"RA", 14}, {"IRA", 15} }
-
-/* Define this macro if you are using an unusual assembler that requires
- different names for the machine instructions.
-
- The definition is a C statement or statements which output an assembler
- instruction opcode to the stdio stream STREAM. The macro-operand PTR is a
- variable of type `char *' which points to the opcode name in its "internal"
- form--the form that is written in the machine description. The definition
- should output the opcode name to STREAM, performing any translation you
- desire, and increment the variable PTR to point at the end of the opcode so
- that it will not be output twice. */
-#define ASM_OUTPUT_OPCODE(STREAM, PTR) \
- (PTR) = ms1_asm_output_opcode (STREAM, PTR)
-
-#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
- ms1_final_prescan_insn (INSN, OPVEC, NOPERANDS)
-
-#define PRINT_OPERAND(STREAM, X, CODE) ms1_print_operand (STREAM, X, CODE)
-
-/* A C expression which evaluates to true if CODE is a valid punctuation
- character for use in the `PRINT_OPERAND' macro. */
-/* #: Print nop for delay slot. */
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#')
-
-#define PRINT_OPERAND_ADDRESS(STREAM, X) ms1_print_operand_address (STREAM, X)
-
-/* If defined, C string expressions to be used for the `%R', `%L', `%U', and
- `%I' options of `asm_fprintf' (see `final.c'). These are useful when a
- single `md' file must support multiple assembler formats. In that case, the
- various `tm.h' files can define these macros differently.
-
- USER_LABEL_PREFIX is defined in svr4.h. */
-#define REGISTER_PREFIX "%"
-#define LOCAL_LABEL_PREFIX "."
-#define USER_LABEL_PREFIX ""
-#define IMMEDIATE_PREFIX ""
-
-/* This macro should be provided on machines where the addresses in a dispatch
- table are relative to the table's own address.
-
- The definition should be a C statement to output to the stdio stream STREAM
- an assembler pseudo-instruction to generate a difference between two labels.
- VALUE and REL are the numbers of two internal labels. The definitions of
- these labels are output using `targetm.asm_out.internal_label', and they
- must be printed in the same way here. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
-fprintf (STREAM, "\t.word .L%d-.L%d\n", VALUE, REL)
-
-/* This macro should be provided on machines where the addresses in a dispatch
- table are absolute.
-
- The definition should be a C statement to output to the stdio stream STREAM
- an assembler pseudo-instruction to generate a reference to a label. VALUE
- is the number of an internal label whose definition is output using
- `targetm.asm_out.internal_label'. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
-fprintf (STREAM, "\t.word .L%d\n", VALUE)
-
-#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (GPR_LINK)
-
-#define EH_RETURN_DATA_REGNO(N) \
- ((N) == 0 ? GPR_R7 : (N) == 1 ? GPR_R8 : INVALID_REGNUM)
-
-#define EH_RETURN_STACKADJ_REGNO GPR_R11
-#define EH_RETURN_STACKADJ_RTX \
- gen_rtx_REG (SImode, EH_RETURN_STACKADJ_REGNO)
-#define EH_RETURN_HANDLER_REGNO GPR_R10
-#define EH_RETURN_HANDLER_RTX \
- gen_rtx_REG (SImode, EH_RETURN_HANDLER_REGNO)
-
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- fprintf ((STREAM), "\t.p2align %d\n", (POWER))
-
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-#ifndef DWARF2_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
-#endif
-
-/* Define this macro if GCC should produce dwarf version 2-style
- line numbers. This usually requires extending the assembler to
- support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the
- assembler configuration header files. */
-#define DWARF2_ASM_LINE_DEBUG_INFO 1
-
-/* 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 this macro if operations between registers with integral
- mode smaller than a word are always performed on the entire
- register. Most RISC machines have this property and most CISC
- machines do not. */
-#define WORD_REGISTER_OPERATIONS
-
-/* The maximum number of bytes that a single instruction can move quickly from
- memory to memory. */
-#define MOVE_MAX 4
-
-/* A C expression which is nonzero if on this machine it is safe to "convert"
- an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
- than INPREC) by merely operating on it as if it had only OUTPREC bits.
-
- On many machines, this expression can be 1.
-
- When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
- which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the
- case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
- things. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-#define Pmode SImode
-
-/* An alias for the machine mode used for memory references to functions being
- called, in `call' RTL expressions. On most machines this should be
- `QImode'. */
-#define FUNCTION_MODE QImode
-
-#define HANDLE_SYSV_PRAGMA 1
-
-/* Indicate how many instructions can be issued at the same time. */
-#define ISSUE_RATE 1
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
-extern struct rtx_def * ms1_compare_op0;
-extern struct rtx_def * ms1_compare_op1;
-
diff --git a/gcc/config/ms1/mt.md b/gcc/config/ms1/mt.md
deleted file mode 100644
index 104f2829e29..00000000000
--- a/gcc/config/ms1/mt.md
+++ /dev/null
@@ -1,1500 +0,0 @@
-;; Machine description for MorphoRISC1
-;; Copyright (C) 2005 Free Software Foundation, Inc.
-;; Contributed by Red Hat, Inc.
-
-;; This file is part of GCC.
-
-;; GCC 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.
-
-;; GCC 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 GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-;; 02110-1301, USA.
-
-;; UNSPECs
-(define_constants
- [
- (UNSPEC_BLOCKAGE 0)
- (UNSPEC_EI 1)
- (UNSPEC_DI 2)
- (UNSPEC_LOOP 3)
- ])
-
-;; Attributes
-(define_attr "type" "branch,call,load,store,io,arith,complex,unknown"
- (const_string "unknown") )
-
-;; If the attribute takes numeric values, no `enum' type will be defined and
-;; the function to obtain the attribute's value will return `int'.
-
-(define_attr "length" "" (const_int 4))
-
-
-;; DFA scheduler.
-(define_automaton "other")
-(define_cpu_unit "decode_unit" "other")
-(define_cpu_unit "memory_unit" "other")
-(define_cpu_unit "branch_unit" "other")
-
-(define_insn_reservation "mem_access" 2
- (ior (eq_attr "type" "load") (eq_attr "type" "store"))
- "decode_unit+memory_unit*2")
-
-(define_insn_reservation "io_access" 2
- (eq_attr "type" "io")
- "decode_unit+memory_unit*2")
-
-(define_insn_reservation "branch_access" 2
- (ior (eq_attr "type" "branch")
- (eq_attr "type" "call"))
- "decode_unit+branch_unit*2")
-
-(define_insn_reservation "arith_access" 1
- (eq_attr "type" "arith")
- "decode_unit")
-
-(define_bypass 2 "arith_access" "branch_access")
-(define_bypass 3 "mem_access" "branch_access")
-(define_bypass 3 "io_access" "branch_access")
-
-
-;; Delay Slots
-
-;; The ms1 does not allow branches in the delay slot.
-;; The ms1 does not allow back to back memory or io instruction.
-;; The compiler does not know what the type of instruction is at
-;; the destination of the branch. Thus, only type that will be acceptable
-;; (safe) is the arith type.
-
-(define_delay (ior (eq_attr "type" "branch")
- (eq_attr "type" "call"))
- [(eq_attr "type" "arith") (nil) (nil)])
-
-
-(define_insn "decrement_and_branch_until_zero"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 0 "nonimmediate_operand" "+r,*m")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:SI 2 "=X,&r"))]
- "TARGET_MS1_16_003 || TARGET_MS2"
- "@
- dbnz\t%0, %l1%#
- #"
- [(set_attr "length" "4,16")
- (set_attr "type" "branch,unknown")]
-)
-
-;; Split the above to handle the case where operand 0 is in memory
-;; (a register that couldn't get a hard register).
-(define_split
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 0 "memory_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:SI 2 ""))]
- "TARGET_MS1_16_003 || TARGET_MS2"
- [(set (match_dup 2) (match_dup 0))
- (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
- (set (match_dup 0) (match_dup 2))
- (set (pc)
- (if_then_else
- (ne (match_dup 2)
- (const_int 0))
- (label_ref (match_dup 1))
- (pc)))]
- "")
-
-;; This peephole is defined in the vain hope that it might actually trigger one
-;; day, although I have yet to find a test case that matches it. The normal
-;; problem is that GCC likes to move the loading of the constant value -1 out
-;; of the loop, so it is not here to be matched.
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_dup 0) (const_int -1)))
- (set (match_operand:SI 1 "register_operand" "")
- (const_int -1))
- (set (pc) (if_then_else
- (ne (match_dup 0) (match_dup 1))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- "TARGET_MS1_16_003 || TARGET_MS2"
- [(parallel [(set (pc)
- (if_then_else
- (ne (match_dup 0) (const_int 0))
- (label_ref (match_dup 2))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (const_int -1)))
- (clobber (reg:SI 0))])]
- "")
-
-
-;; Loop instructions. ms2 has a low overhead looping instructions.
-;; these take a constant or register loop count and a loop length
-;; offset. Unfortunately the loop can only be up to 256 instructions,
-;; We deal with longer loops by moving the loop end upwards. To do
-;; otherwise would force us to to be very pessimistic right up until
-;; the end.
-
-;; This instruction is a placeholder to make the control flow explicit.
-(define_insn "loop_end"
- [(set (pc) (if_then_else
- (ne (match_operand:SI 0 "register_operand" "")
- (const_int 1))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
- (unspec [(const_int 0)] UNSPEC_LOOP)]
- "TARGET_MS2"
- ";loop end %0,%l1"
- [(set_attr "length" "0")])
-
-;; This is the real looping instruction. It is placed just before the
-;; loop body. We make it a branch insn, so it stays at the end of the
-;; block it is in.
-(define_insn "loop_init"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "uns_arith_operand" "r,K"))
- (unspec [(label_ref (match_operand 2 "" ""))] UNSPEC_LOOP)]
- "TARGET_MS2"
- "@
- loop %1,%l2 ;%0%#
- loopi %1,%l2 ;%0%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-; operand 0 is the loop count pseudo register
-; operand 1 is the number of loop iterations or 0 if it is unknown
-; operand 2 is the maximum number of loop iterations
-; operand 3 is the number of levels of enclosed loops
-; operand 4 is the label to jump to at the top of the loop
-(define_expand "doloop_end"
- [(parallel [(set (pc) (if_then_else
- (ne (match_operand:SI 0 "nonimmediate_operand" "")
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:SI 5 ""))])]
- "TARGET_MS1_16_003 || TARGET_MS2"
- {ms1_add_loop ();})
-
-;; Moves
-
-(define_expand "loadqi"
- [
- ;; compute shift
- (set (match_operand:SI 2 "register_operand" "")
- (and:SI (match_dup 1) (const_int 3)))
- (set (match_dup 2) (xor:SI (match_dup 2) (const_int 3)))
- (set (match_dup 2 ) (ashift:SI (match_dup 2) (const_int 3)))
-
- ;; get word that contains byte
- (set (match_operand:SI 0 "register_operand" "")
- (mem:SI (and:SI (match_operand:SI 1 "register_operand" "")
- (const_int -3))))
-
- ;; align byte
- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))
- ]
- ""
- "")
-
-
-;; storeqi
-;; operand 0 byte value to store
-;; operand 1 address
-;; operand 2 temp, word containing byte
-;; operand 3 temp, shift count
-;; operand 4 temp, mask, aligned and masked byte
-;; operand 5 (unused)
-(define_expand "storeqi"
- [
- ;; compute shift
- (set (match_operand:SI 3 "register_operand" "")
- (and:SI (match_operand:SI 1 "register_operand" "") (const_int 3)))
- (set (match_dup 3) (xor:SI (match_dup 3) (const_int 3)))
- (set (match_dup 3) (ashift:SI (match_dup 3) (const_int 3)))
-
- ;; get word that contains byte
- (set (match_operand:SI 2 "register_operand" "")
- (mem:SI (and:SI (match_dup 1) (const_int -3))))
-
- ;; generate mask
- (set (match_operand:SI 4 "register_operand" "") (const_int 255))
- (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
- (set (match_dup 4) (not:SI (match_dup 4)))
-
- ;; clear appropriate bits
- (set (match_dup 2) (and:SI (match_dup 2) (match_dup 4)))
-
- ;; align byte
- (set (match_dup 4)
- (and:SI (match_operand:SI 0 "register_operand" "") (const_int 255)))
- (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
-
- ;; combine
- (set (match_dup 2) (ior:SI (match_dup 4) (match_dup 2)))
- ;; store updated word
- (set (mem:SI (and:SI (match_dup 1) (const_int -3))) (match_dup 2))
- ]
- ""
- "")
-
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (!reload_in_progress
- && !reload_completed
- && GET_CODE (operands[0]) == MEM
- && GET_CODE (operands[1]) == MEM)
- operands[1] = copy_to_mode_reg (QImode, operands[1]);
-
- if ( (! TARGET_BYTE_ACCESS) && GET_CODE (operands[0]) == MEM)
- {
- rtx scratch1 = gen_reg_rtx (SImode);
- rtx scratch2 = gen_reg_rtx (SImode);
- rtx scratch3 = gen_reg_rtx (SImode);
- rtx data = operands[1];
- rtx address = XEXP (operands[0], 0);
- rtx seq;
-
- if ( GET_CODE (data) != REG )
- data = copy_to_mode_reg (QImode, data);
-
- if ( GET_CODE (address) != REG )
- address = copy_to_mode_reg (SImode, address);
-
- start_sequence ();
- emit_insn (gen_storeqi (gen_lowpart (SImode, data), address,
- scratch1, scratch2, scratch3));
- ms1_set_memflags (operands[0]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-
- if ( (! TARGET_BYTE_ACCESS) && GET_CODE (operands[1]) == MEM)
- {
- rtx scratch1 = gen_reg_rtx (SImode);
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx seq;
-
- if ( GET_CODE (address) != REG )
- address = copy_to_mode_reg (SImode, address);
-
- start_sequence ();
- emit_insn (gen_loadqi (gen_lowpart (SImode, data), address, scratch1));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-
- /* If the load is a pseudo register in a stack slot, some simplification
- can be made because the loads are aligned */
- if ( (! TARGET_BYTE_ACCESS)
- && (reload_in_progress && GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == REG
- && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
- {
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx seq;
-
- start_sequence ();
- emit_insn (gen_movsi (gen_lowpart (SImode, data), address));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-}")
-
-(define_insn "*movqi_internal"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r")
- (match_operand:QI 1 "general_operand" "r,m,r,I"))]
- "TARGET_BYTE_ACCESS
- && (!memory_operand (operands[0], QImode)
- || !memory_operand (operands[1], QImode))"
- "@
- or %0, %1, %1
- ldb %0, %1
- stb %1, %0
- addi %0, r0, %1"
- [(set_attr "length" "4,4,4,4")
- (set_attr "type" "arith,load,store,arith")])
-
-(define_insn "*movqi_internal_nobyte"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (match_operand:QI 1 "arith_operand" "r,I"))]
- "!TARGET_BYTE_ACCESS
- && (!memory_operand (operands[0], QImode)
- || !memory_operand (operands[1], QImode))"
- "@
- or %0, %1, %1
- addi %0, r0, %1"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-
-;; The MorphoRISC does not have 16-bit loads and stores.
-;; These operations must be synthesized. Note that the code
-;; for loadhi and storehi assumes that the least significant bits
-;; is ignored.
-
-;; loadhi
-;; operand 0 location of result
-;; operand 1 memory address
-;; operand 2 temp
-(define_expand "loadhi"
- [
- ;; compute shift
- (set (match_operand:SI 2 "register_operand" "")
- (and:SI (match_dup 1) (const_int 2)))
- (set (match_dup 2) (xor:SI (match_dup 2) (const_int 2)))
- (set (match_dup 2 ) (ashift:SI (match_dup 2) (const_int 3)))
-
- ;; get word that contains the 16-bits
- (set (match_operand:SI 0 "register_operand" "")
- (mem:SI (and:SI (match_operand:SI 1 "register_operand" "")
- (const_int -3))))
-
- ;; align 16-bit value
- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))
- ]
- ""
- "")
-
-;; storehi
-;; operand 0 byte value to store
-;; operand 1 address
-;; operand 2 temp, word containing byte
-;; operand 3 temp, shift count
-;; operand 4 temp, mask, aligned and masked byte
-;; operand 5 (unused)
-(define_expand "storehi"
- [
- ;; compute shift
- (set (match_operand:SI 3 "register_operand" "")
- (and:SI (match_operand:SI 1 "register_operand" "") (const_int 2)))
- (set (match_dup 3) (xor:SI (match_dup 3) (const_int 2)))
- (set (match_dup 3) (ashift:SI (match_dup 3) (const_int 3)))
-
- ;; get word that contains the 16-bits
- (set (match_operand:SI 2 "register_operand" "")
- (mem:SI (and:SI (match_dup 1) (const_int -3))))
-
- ;; generate mask
- (set (match_operand:SI 4 "register_operand" "") (const_int 65535))
- (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
- (set (match_dup 4) (not:SI (match_dup 4)))
-
- ;; clear appropriate bits
- (set (match_dup 2) (and:SI (match_dup 2) (match_dup 4)))
-
- ;; align 16-bit value
- (set (match_dup 4)
- (and:SI (match_operand:SI 0 "register_operand" "") (const_int 65535)))
- (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
-
- ;; combine
- (set (match_dup 2) (ior:SI (match_dup 4) (match_dup 2)))
- ;; store updated word
- (set (mem:SI (and:SI (match_dup 1) (const_int -3))) (match_dup 2))
- ]
- ""
- "")
-
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (!reload_in_progress
- && !reload_completed
- && GET_CODE (operands[0]) == MEM
- && GET_CODE (operands[1]) == MEM)
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
-
- if ( GET_CODE (operands[0]) == MEM)
- {
- rtx scratch1 = gen_reg_rtx (SImode);
- rtx scratch2 = gen_reg_rtx (SImode);
- rtx scratch3 = gen_reg_rtx (SImode);
- rtx data = operands[1];
- rtx address = XEXP (operands[0], 0);
- rtx seq;
-
- if (GET_CODE (data) != REG)
- data = copy_to_mode_reg (HImode, data);
-
- if (GET_CODE (address) != REG)
- address = copy_to_mode_reg (SImode, address);
-
- start_sequence ();
- emit_insn (gen_storehi (gen_lowpart (SImode, data), address,
- scratch1, scratch2, scratch3));
- ms1_set_memflags (operands[0]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-
- if ( GET_CODE (operands[1]) == MEM)
- {
- rtx scratch1 = gen_reg_rtx (SImode);
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx seq;
-
- if (GET_CODE (address) != REG)
- address = copy_to_mode_reg (SImode, address);
-
- start_sequence ();
- emit_insn (gen_loadhi (gen_lowpart (SImode, data), address,
- scratch1));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-
- /* If the load is a pseudo register in a stack slot, some simplification
- can be made because the loads are aligned */
- if ( (reload_in_progress && GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == REG
- && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
- {
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx seq;
-
- start_sequence ();
- emit_insn (gen_movsi (gen_lowpart (SImode, data), address));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
- }
-}")
-
-(define_insn "*movhi_internal"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (match_operand:HI 1 "arith_operand" "r,I"))]
- "!memory_operand (operands[0], HImode) || !memory_operand (operands[1], HImode)"
- "@
- or %0, %1, %1
- addi %0, r0, %1"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
-{
- if (!reload_in_progress && !reload_completed
- && !register_operand (operands[0], SImode)
- && !register_operand (operands[1], SImode))
- operands[1] = copy_to_mode_reg (SImode, operands[1]);
-
- /* Take care of constants that don't fit in single instruction */
- if ( (reload_in_progress || reload_completed)
- && !single_const_operand (operands[1], SImode))
- {
- emit_insn (gen_movsi_high (operands[0], operands[1]));
- emit_insn (gen_movsi_lo_sum (operands[0], operands[0], operands[1]));
- DONE;
- }
-
-}")
-
-(define_insn "movsi_high"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand:SI 1 "general_operand" "i")))]
- ""
- "*
-{
- return \"ldui\\t%0, %H1\";
-}"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-
-(define_insn "movsi_lo_sum"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "general_operand" "i")))]
- ""
- "*
-{
- return \"addui\\t%0, %1, %L2\";
-}"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-/* Take care of constants that don't fit in single instruction */
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- "(reload_in_progress || reload_completed)
- && !single_const_operand (operands[1], SImode)"
-
- [(set (match_dup 0 )
- (high:SI (match_dup 1)))
- (set (match_dup 0 )
- (lo_sum:SI (match_dup 0)
- (match_dup 1)))]
-)
-
-
-;; The last pattern in movsi (with two instructions)
-;; is really handled by the emit_insn's in movsi
-;; and the define_split above. This provides additional
-;; instructions to fill delay slots.
-
-;; Note - it is best to only have one movsi pattern and to handle
-;; all the various contingencies by the use of alternatives. This
-;; allows reload the greatest amount of flexibility (since reload will
-;; only choose amoungst alternatives for a selected insn, it will not
-;; replace the insn with another one).
-(define_insn "*movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,r")
- (match_operand:SI 1 "general_operand" "r,m,r,I,P,L,N,i"))]
- "(!memory_operand (operands[0], SImode) || !memory_operand (operands[1], SImode))
- && !((reload_in_progress || reload_completed)
- && !single_const_operand (operands[1], SImode))"
- "@
- or %0, %1, %1
- ldw %0, %1
- stw %1, %0
- addi %0, r0, %1
- addui %0, r0, %1
- ldui %0, %H1
- nori %0, r0, %N1
- ldui %0, %H1\;addui %0, %0, %L1"
- [(set_attr "length" "4,4,4,4,4,4,4,8")
- (set_attr "type" "arith,load,store,arith,arith,arith,arith,complex")]
-)
-
-;; Floating Point Moves
-;;
-;; Note - Patterns for SF mode moves are compulsory, but
-;; patterns for DF are optional, as GCC can synthesize them.
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
-{
- if (!reload_in_progress
- && !reload_completed
- && GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM
- || GET_CODE (operands[1]) == CONST_DOUBLE))
- operands[1] = copy_to_mode_reg (SFmode, operands[1]);
-
- /* Take care of reg <- SF constant */
- if ( const_double_operand (operands[1], GET_MODE (operands[1]) ) )
- {
- emit_insn (gen_movsf_high (operands[0], operands[1]));
- emit_insn (gen_movsf_lo_sum (operands[0], operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "movsf_lo_sum"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
- (match_operand:SF 2 "const_double_operand" "")))]
- ""
- "*
-{
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[2] = GEN_INT (i);
- return \"addui\\t%0, %1, %L2\";
-}"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-(define_insn "movsf_high"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (high:SF (match_operand:SF 1 "const_double_operand" "")))]
- ""
- "*
-{
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = GEN_INT (i);
- return \"ldui\\t%0, %H1\";
-}"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-
-(define_insn "*movsf_internal"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))]
- "!memory_operand (operands[0], SFmode) || !memory_operand (operands[1], SFmode)"
- "@
- or %0, %1, %1
- ldw %0, %1
- stw %1, %0"
- [(set_attr "length" "4,4,4")
- (set_attr "type" "arith,load,store")]
-)
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register or 0 */
- if (!register_operand (operand0, DFmode)
- && !reg_or_0_operand (operand1, DFmode))
- operands[1] = copy_to_mode_reg (DFmode, operand1);
-}")
-
-(define_insn_and_split "*movdf_internal"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,o")
- (match_operand:DF 1 "general_operand" "rim,r"))]
- "! (memory_operand (operands[0], DFmode)
- && memory_operand (operands[1], DFmode))"
- "#"
-
- "(reload_completed || reload_in_progress)"
-
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))
- ]
-
- "{
- /* figure out what precisely to put into operands 2, 3, 4, and 5 */
- ms1_split_words (SImode, DFmode, operands);
- }"
-)
-
-
-;; Reloads
-
-;; Like `movM', but used when a scratch register is required to move between
-;; operand 0 and operand 1. Operand 2 describes the scratch register. See the
-;; discussion of the `SECONDARY_RELOAD_CLASS' macro.
-
-(define_expand "reload_inqi"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (match_operand:QI 1 "memory_operand" "m"))
- (clobber (match_operand:DI 2 "register_operand" "=&r"))]
- "! TARGET_BYTE_ACCESS"
- "
-{
- rtx scratch1 = gen_rtx_REG (SImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (SImode, REGNO (operands[2])+1);
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx swap, seq;
-
- /* It is possible that the registers we got for scratch1
- might coincide with that of operands[0]. gen_loadqi
- requires operand0 and operand2 to be different registers.
- The following statement ensure that is always the case. */
- if (REGNO(operands[0]) == REGNO(scratch1))
- {
- swap = scratch1;
- scratch1 = scratch2;
- scratch2 = swap;
- }
-
- /* need to make sure address is already in register */
- if ( GET_CODE (address) != REG )
- address = force_operand (address, scratch2);
-
- start_sequence ();
- emit_insn (gen_loadqi (gen_lowpart (SImode, data), address, scratch1));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
-}")
-
-(define_expand "reload_outqi"
- [(set (match_operand:QI 0 "memory_operand" "=m")
- (match_operand:QI 1 "register_operand" "r"))
- (clobber (match_operand:TI 2 "register_operand" "=&r"))]
- "! TARGET_BYTE_ACCESS"
- "
-{
- rtx scratch1 = gen_rtx_REG (SImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (SImode, REGNO (operands[2])+1);
- rtx scratch3 = gen_rtx_REG (SImode, REGNO (operands[2])+2);
- rtx scratch4 = gen_rtx_REG (SImode, REGNO (operands[2])+3);
- rtx data = operands[1];
- rtx address = XEXP (operands[0], 0);
- rtx seq;
-
- /* need to make sure address is already in register */
- if ( GET_CODE (address) != REG )
- address = force_operand (address, scratch4);
-
- start_sequence ();
- emit_insn (gen_storeqi (gen_lowpart (SImode, data), address,
- scratch1, scratch2, scratch3));
- ms1_set_memflags (operands[0]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
-}")
-
-(define_expand "reload_inhi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "memory_operand" "m"))
- (clobber (match_operand:DI 2 "register_operand" "=&r"))]
- ""
- "
-{
- rtx scratch1 = gen_rtx_REG (SImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (SImode, REGNO (operands[2])+1);
- rtx data = operands[0];
- rtx address = XEXP (operands[1], 0);
- rtx swap, seq;
-
- /* It is possible that the registers we got for scratch1
- might coincide with that of operands[0]. gen_loadqi
- requires operand0 and operand2 to be different registers.
- The following statement ensure that is always the case. */
- if (REGNO(operands[0]) == REGNO(scratch1))
- {
- swap = scratch1;
- scratch1 = scratch2;
- scratch2 = swap;
- }
-
- /* need to make sure address is already in register */
- if ( GET_CODE (address) != REG )
- address = force_operand (address, scratch2);
-
- start_sequence ();
- emit_insn (gen_loadhi (gen_lowpart (SImode, data), address,
- scratch1));
- ms1_set_memflags (operands[1]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
-}")
-
-(define_expand "reload_outhi"
- [(set (match_operand:HI 0 "memory_operand" "=m")
- (match_operand:HI 1 "register_operand" "r"))
- (clobber (match_operand:TI 2 "register_operand" "=&r"))]
- ""
- "
-{
- rtx scratch1 = gen_rtx_REG (SImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (SImode, REGNO (operands[2])+1);
- rtx scratch3 = gen_rtx_REG (SImode, REGNO (operands[2])+2);
- rtx scratch4 = gen_rtx_REG (SImode, REGNO (operands[2])+3);
- rtx data = operands[1];
- rtx address = XEXP (operands[0], 0);
- rtx seq;
-
- /* need to make sure address is already in register */
- if ( GET_CODE (address) != REG )
- address = force_operand (address, scratch4);
-
- start_sequence ();
- emit_insn (gen_storehi (gen_lowpart (SImode, data), address,
- scratch1, scratch2, scratch3));
- ms1_set_memflags (operands[0]);
- seq = get_insns ();
- end_sequence ();
- emit_insn (seq);
- DONE;
-}")
-
-
-;; 32 bit Integer arithmetic
-
-;; Addition
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
- (match_operand:SI 2 "arith_operand" "r,I")))]
- ""
- "@
- add %0, %1, %2
- addi %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Subtraction
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ")
- (match_operand:SI 2 "arith_operand" "rJ,I")))]
- ""
- "@
- sub %0, %z1, %z2
- subi %0, %z1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Negation
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (neg:SI (match_operand:SI 1 "arith_operand" "r,I")))]
- ""
- "@
- sub %0, r0, %1
- subi %0, r0, %1"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-
-;; 32 bit Integer Shifts and Rotates
-
-;; Arithmetic Shift Left
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "arith_operand" "r,K")))]
- ""
- "@
- lsl %0, %1, %2
- lsli %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Arithmetic Shift Right
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "uns_arith_operand" "r,K")))]
- ""
- "@
- asr %0, %1, %2
- asri %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Logical Shift Right
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "uns_arith_operand" "r,K")))]
- ""
- "@
- lsr %0, %1, %2
- lsri %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-
-;; 32 Bit Integer Logical operations
-
-;; Logical AND, 32 bit integers
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (and:SI (match_operand:SI 1 "register_operand" "%r,r")
- (match_operand:SI 2 "uns_arith_operand" "r,K")))]
- ""
- "@
- and %0, %1, %2
- andi %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Inclusive OR, 32 bit integers
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (ior:SI (match_operand:SI 1 "register_operand" "%r,r")
- (match_operand:SI 2 "uns_arith_operand" "r,K")))]
- ""
- "@
- or %0, %1, %2
- ori %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-;; Exclusive OR, 32 bit integers
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (xor:SI (match_operand:SI 1 "register_operand" "%r,r")
- (match_operand:SI 2 "uns_arith_operand" "r,K")))]
- ""
- "@
- xor %0, %1, %2
- xori %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-
-;; One's complement, 32 bit integers
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "nor %0, %1, %1"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-
-;; Multiply
-
-(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r,r"))
- (sign_extend:SI (match_operand:HI 2 "arith_operand" "r,I"))))]
- "TARGET_MS1_16_003 || TARGET_MS2"
- "@
- mul %0, %1, %2
- muli %0, %1, %2"
- [(set_attr "length" "4,4")
- (set_attr "type" "arith,arith")])
-
-
-;; Comparisons
-
-;; Note, we store the operands in the comparison insns, and use them later
-;; when generating the branch or scc operation.
-
-;; First the routines called by the machine independent part of the compiler
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "arith_operand" "")))]
- ""
- "
-{
- ms1_compare_op0 = operands[0];
- ms1_compare_op1 = operands[1];
- DONE;
-}")
-
-
-;; Branches
-
-(define_expand "beq"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (EQ, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bne"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (NE, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bge"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (GE, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bgt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (GT, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "ble"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (LE, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "blt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (LT, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bgeu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (GEU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bgtu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (GTU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bleu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (LEU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bltu"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (LTU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bunge"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{ ms1_emit_cbranch (GEU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bungt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- ms1_emit_cbranch (GTU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bunle"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- ms1_emit_cbranch (LEU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_expand "bunlt"
- [(use (match_operand 0 "" ""))]
- ""
- "
-{
- ms1_emit_cbranch (LTU, operands[0],
- ms1_compare_op0, ms1_compare_op1);
- DONE;
-}")
-
-(define_insn "*beq_true"
- [(set (pc)
- (if_then_else (eq (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "breq %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*beq_false"
- [(set (pc)
- (if_then_else (eq (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "brne %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-
-(define_insn "*bne_true"
- [(set (pc)
- (if_then_else (ne (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "brne %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*bne_false"
- [(set (pc)
- (if_then_else (ne (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "breq %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*blt_true"
- [(set (pc)
- (if_then_else (lt (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "brlt %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*blt_false"
- [(set (pc)
- (if_then_else (lt (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "brle %z1, %z0,%l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*ble_true"
- [(set (pc)
- (if_then_else (le (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "brle %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*ble_false"
- [(set (pc)
- (if_then_else (le (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "brlt %z1, %z0,%l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*bgt_true"
- [(set (pc)
- (if_then_else (gt (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "brlt %z1, %z0, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*bgt_false"
- [(set (pc)
- (if_then_else (gt (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "brle %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*bge_true"
- [(set (pc)
- (if_then_else (ge (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (label_ref (match_operand 2 "" ""))
- (pc)))]
- ""
- "brle %z1, %z0,%l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_insn "*bge_false"
- [(set (pc)
- (if_then_else (ge (match_operand:SI 0 "reg_or_0_operand" "rJ")
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (pc)
- (label_ref (match_operand 2 "" ""))))]
- ""
- "brlt %z0, %z1, %l2%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-;; No unsigned operators on Morpho ms1. All the unsigned operations are
-;; converted to the signed operations above.
-
-
-;; Set flag operations
-
-;; "seq", "sne", "slt", "sle", "sgt", "sge", "sltu", "sleu",
-;; "sgtu", and "sgeu" don't exist as regular instruction on the
-;; ms1, so these are not defined
-
-;; Call and branch instructions
-
-(define_expand "call"
- [(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" ""))
- (match_operand 1 "" ""))
- (clobber (reg:SI 14))])]
- ""
- "
-{
- operands[0] = force_reg (SImode, XEXP (operands[0], 0));
-}")
-
-(define_insn "call_internal"
- [(call (mem:SI (match_operand 0 "register_operand" "r"))
- (match_operand 1 "" ""))
- ;; possibly add a clobber of the reg that gets the return address
- (clobber (reg:SI 14))]
- ""
- "jal r14, %0%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-(define_expand "call_value"
- [(parallel [(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" ""))
- (match_operand 2 "general_operand" "")))
- (clobber (reg:SI 14))])]
- ""
- "
-{
- operands[1] = force_reg (SImode, XEXP (operands[1], 0));
-}")
-
-
-(define_insn "call_value_internal"
- [(set (match_operand 0 "register_operand" "=r")
- (call (mem:SI (match_operand 1 "register_operand" "r"))
- (match_operand 2 "" "")))
- ;; possibly add a clobber of the reg that gets the return address
- (clobber (reg:SI 14))]
- ""
- "jal r14, %1%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-;; Subroutine return
-(define_insn "return_internal"
- [(const_int 2)
- (return)
- (use (reg:SI 14))]
- ""
- "jal r0, r14%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-;; Interrupt return
-(define_insn "return_interrupt_internal"
- [(const_int 3)
- (return)
- (use (reg:SI 15))]
- ""
- "reti r15%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-;; Subroutine return
-(define_insn "eh_return_internal"
- [(return)
- (use (reg:SI 7))
- (use (reg:SI 8))
- (use (reg:SI 11))
- (use (reg:SI 10))]
- ""
- "jal r0, r11%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-
-;; Normal unconditional jump
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "jmp %l0%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-;; Indirect jump through a register
-(define_insn "indirect_jump"
- [(set (pc) (match_operand 0 "register_operand" "r"))]
- ""
- "jal r0,%0%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "register_operand" "r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "jal r0, %0%#"
- [(set_attr "length" "4")
- (set_attr "type" "call")])
-
-
-(define_expand "prologue"
- [(const_int 1)]
- ""
- "
-{
- ms1_expand_prologue ();
- DONE;
-}")
-
-(define_expand "epilogue"
- [(const_int 2)]
- ""
- "
-{
- ms1_expand_epilogue (NORMAL_EPILOGUE);
- DONE;
-}")
-
-
-(define_expand "eh_return"
- [(use (match_operand:SI 0 "register_operand" "r"))]
- ""
- "
-{
- ms1_expand_eh_return (operands);
- DONE;
-}")
-
-
-(define_insn_and_split "eh_epilogue"
- [(unspec [(match_operand 0 "register_operand" "r")] 6)]
- ""
- "#"
- "reload_completed"
- [(const_int 1)]
- "ms1_emit_eh_epilogue (operands); DONE;"
-)
-
-;; No operation, needed in case the user uses -g but not -O.
-(define_insn "nop"
- [(const_int 0)]
- ""
- "or r0,r0,r0"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
-
-;; ::::::::::::::::::::
-;; ::
-;; :: UNSPEC_VOLATILE usage
-;; ::
-;; ::::::::::::::::::::
-;;
-;; 0 blockage
-;; 1 Enable interrupts
-;; 2 Disable interrupts
-;;
-
-;; Pseudo instruction that prevents the scheduler from moving code above this
-;; point.
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
- ""
- ""
- [(set_attr "length" "0")])
-
-;; Trap instruction to allow usage of the __builtin_trap function
-(define_insn "trap"
- [(trap_if (const_int 1) (const_int 0))
- (clobber (reg:SI 14))]
- ""
- "si r14%#"
- [(set_attr "length" "4")
- (set_attr "type" "branch")])
-
-(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "comparison_operator"
- [(match_dup 2)
- (match_dup 3)])
- (match_operand 1 "const_int_operand" ""))]
- ""
- "
-{
- operands[2] = ms1_compare_op0;
- operands[3] = ms1_compare_op1;
-}")
-
-;; Templates to control handling of interrupts
-
-;; Enable interrupts template
-(define_insn "ei"
- [(unspec_volatile [(const_int 0)] UNSPEC_EI)]
- ""
- "ei"
- [(set_attr "length" "4")])
-
-;; Enable interrupts template
-(define_insn "di"
- [(unspec_volatile [(const_int 0)] UNSPEC_DI)]
- ""
- "di"
- [(set_attr "length" "4")])
diff --git a/gcc/config/ms1/mt.opt b/gcc/config/ms1/mt.opt
deleted file mode 100644
index eba1eeabeeb..00000000000
--- a/gcc/config/ms1/mt.opt
+++ /dev/null
@@ -1,56 +0,0 @@
-; Options for the ms1 port of the compiler
-;
-; Copyright (C) 2005 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC 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.
-;
-; GCC 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 GCC; see the file COPYING. If not, write to the Free
-; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-; 02110-1301, USA.
-
-mbacc
-Target Report Mask(BYTE_ACCESS)
-Use byte loads and stores when generating code.
-
-msim
-Target RejectNegative
-Use simulator runtime
-
-mno-crt0
-Target RejectNegative
-Do not include crt0.o in the startup files
-
-mdebug-arg
-Target RejectNegative Mask(DEBUG_ARG)
-Internal debug switch
-
-mdebug-addr
-Target RejectNegative Mask(DEBUG_ADDR)
-Internal debug switch
-
-mdebug-stack
-Target RejectNegative Mask(DEBUG_STACK)
-Internal debug switch
-
-mdebug-loc
-Target RejectNegative Mask(DEBUG_LOC)
-Internal debug switch
-
-mdebug
-Target RejectNegative Mask(DEBUG)
-Internal debug switch
-
-march=
-Target RejectNegative Joined Var(ms1_cpu_string)
-Specify CPU for code generation purposes
diff --git a/gcc/config/ms1/t-mt b/gcc/config/ms1/t-mt
deleted file mode 100644
index 3093fc445db..00000000000
--- a/gcc/config/ms1/t-mt
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC 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.
-#
-# GCC 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 GCC; see the file COPYING. If not, write to the Free
-# Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-# Name of assembly file containing libgcc1 functions.
-# This entry must be present, but it can be empty if the target does
-# not need any assembler functions to support its code generation.
-CROSS_LIBGCC1 =
-#
-# Alternatively if assembler functions *are* needed then define the
-# entries below:
-# CROSS_LIBGCC1 = libgcc1-asm.a
-# LIB1ASMSRC = ms1/lib1funcs.asm
-# LIB1ASMFUNCS = _udivsi3 etc...
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/ms1/lib2extra-funcs.c
-
-# If any special flags are necessary when building libgcc2 put them here.
-#
-# TARGET_LIBGCC2_CFLAGS =
-
-EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- cat $(srcdir)/config/fp-bit.c > dp-bit.c
-
-# Assemble startup files.
-crti.o: $(srcdir)/config/ms1/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/ms1/crti.asm
-
-crtn.o: $(srcdir)/config/ms1/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtn.o -x assembler $(srcdir)/config/ms1/crtn.asm
-
-# Enable the following if multilibs are needed.
-# See gcc/genmultilib, gcc/gcc.texi and gcc/tm.texi for a
-# description of the options and their values.
-#
-MULTILIB_OPTIONS = march=ms1-64-001/march=ms1-16-002/march=ms1-16-003
-MULTILIB_DIRNAMES = 64-001 16-002 16-003
-# MULTILIB_MATCHES =
-# MULTILIB_EXCEPTIONS =
-# MULTILIB_EXTRA_OPTS =
-#
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
-