diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-20 06:39:38 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-20 06:39:38 +0000 |
commit | 1850ee7af3e9566308981ded3aa10f50479ebaa2 (patch) | |
tree | 2b9e6529be54223bc03b5573062543f617b7d081 | |
parent | b9a602c6ab145acee918376ac1aa0b569222ca5d (diff) | |
download | gcc-1850ee7af3e9566308981ded3aa10f50479ebaa2.tar.gz |
gcc/
* config.gcc: Remove support for sparc-*-openbsd*,
i860-*-sysv4*, ip2k-*-elf, ns32k-*-netbsdelf*,
ns32k-*-netbsd*.
* config.host: Remove support for i860-*-sysv4* as a host.
* config/i860/*, config/ip2k/*, config/ns32k/*,
config/sparc/openbsd.h, config/sparc/t-openbsd: Remove.
* doc/install.texi, doc/invoke.texi, doc/md.texi: Don't
mention obsolete ports.
testsuite/
* gcc.dg/20020312-2.c, gcc.dg/sibcall-3.c, gcc.dg/sibcall-4.c,
gcc.dg/cpp/assert4.c: Don't mention obsolete ports.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102189 138bc75d-0d04-0410-961f-82ee72b054a4
40 files changed, 19 insertions, 28579 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 97bd21cd8e8..61dbaef78e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-07-20 Kazu Hirata <kazu@codesourcery.com> + + * config.gcc: Remove support for sparc-*-openbsd*, + i860-*-sysv4*, ip2k-*-elf, ns32k-*-netbsdelf*, + ns32k-*-netbsd*. + * config.host: Remove support for i860-*-sysv4* as a host. + * config/i860/*, config/ip2k/*, config/ns32k/*, + config/sparc/openbsd.h, config/sparc/t-openbsd: Remove. + * doc/install.texi, doc/invoke.texi, doc/md.texi: Don't + mention obsolete ports. + 2005-07-20 Kaz Kojima <kkojima@gcc.gnu.org> * config/sh/sh.c (regno_reg_class): Add GENERAL_REGS for diff --git a/gcc/config.gcc b/gcc/config.gcc index beefc954621..c33b491acd5 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -184,12 +184,7 @@ md_file= # Obsolete configurations. case ${target} in - sparc-*-openbsd* \ - | i860-*-sysv4* \ - | ip2k-*-elf \ - | ns32k-*-netbsdelf* \ - | ns32k-*-netbsd* \ - | c4x-* \ + c4x-* \ | tic4x-* \ ) if test "x$enable_obsolete" != xyes; then @@ -1226,12 +1221,6 @@ i[34567]86-*-kaos*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h kaos.h i386/kaos-i386.h" tmake_file="i386/t-i386elf t-svr4" ;; -i860-*-sysv4*) - tm_file="${tm_file} elfos.h svr4.h i860/sysv4.h" - tmake_file="i860/t-i860 i860/t-svr4" - extra_parts="crtbegin.o crtend.o" - use_fixproto=yes - ;; ia64*-*-elf*) tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/elf.h" tmake_file="ia64/t-ia64" @@ -1279,10 +1268,6 @@ ia64*-*-hpux*) # in ia64/t-hpux, and also fix the definition of putenv in # sys-protos.h (const char not char). ;; -ip2k-*-elf) - tm_file="elfos.h ${tm_file}" - use_fixproto=yes - ;; iq2000*-*-elf*) tm_file="svr4.h elfos.h iq2000/iq2000.h" tmake_file=iq2000/t-iq2000 @@ -1557,16 +1542,6 @@ mn10300-*-*) use_collect2=no use_fixproto=yes ;; -ns32k-*-netbsdelf*) - echo "GCC does not yet support the ${target} target"; exit 1 - ;; -ns32k-*-netbsd*) - tm_file="${tm_file} netbsd.h netbsd-aout.h ns32k/netbsd.h" - # On NetBSD, the headers are already okay, except for math.h. - tmake_file="t-netbsd ns32k/t-ns32k" - extra_parts="" - use_collect2=yes - ;; pdp11-*-bsd) tm_file="${tm_file} pdp11/2bsd.h" use_fixproto=yes @@ -1995,14 +1970,6 @@ sparc-*-netbsdelf*) tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h netbsd.h netbsd-elf.h sparc/netbsd-elf.h" extra_options="${extra_options} sparc/long-double-switch.opt" ;; -sparc-*-openbsd*) - tm_defines=OBSD_OLD_GAS - tm_file="sparc/sparc.h openbsd.h sparc/openbsd.h" - # needed to unconfuse gdb - tmake_file="t-libc-ok t-openbsd sparc/t-openbsd" - # we need collect2 until our bug is fixed... - use_collect2=yes - ;; sparc64-*-openbsd*) tm_file="sparc/openbsd1-64.h ${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sp64-elf.h openbsd.h sparc/openbsd64.h" extra_options="${extra_options} sparc/little-endian.opt" diff --git a/gcc/config.host b/gcc/config.host index 2927ddd29f7..0f804aa543c 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -177,9 +177,6 @@ case ${host} in out_host_hook_obj="${out_host_hook_obj} host-i386-darwin.o" host_xmake_file="${host_xmake_file} i386/x-darwin" ;; - i860-*-sysv4*) - host_xmake_file=i860/x-sysv4 - ;; powerpc-*-beos*) host_can_use_collect2=no ;; diff --git a/gcc/config/i860/i860-protos.h b/gcc/config/i860/i860-protos.h deleted file mode 100644 index af5dfda84db..00000000000 --- a/gcc/config/i860/i860-protos.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Intel 860. - Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. - Hacked substantially by Ron Guilmette (rfg@monkeys.com) to cater to - the whims of the System V Release 4 assembler. - -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. */ - -/* Declare things which are defined in i860.c but called from - insn-output.c. */ - -#ifdef RTX_CODE -extern unsigned long sfmode_constant_to_ulong (rtx); -extern const char *output_load (rtx *); -extern const char *output_store (rtx *); -extern const char *output_move_double (rtx *); -extern const char *output_fp_move_double (rtx *); -extern const char *output_block_move (rtx *); -extern void output_load_address (rtx *); -extern int safe_insn_src_p (rtx, enum machine_mode); -extern int operand_clobbered_before_used_after (rtx, rtx); -extern int reg_or_0_operand (rtx, enum machine_mode); -extern int arith_operand (rtx, enum machine_mode); -extern int logic_operand (rtx, enum machine_mode); -extern int shift_operand (rtx, enum machine_mode); -extern int compare_operand (rtx, enum machine_mode); -extern int bte_operand (rtx, enum machine_mode); -extern int indexed_operand (rtx, enum machine_mode); -extern int load_operand (rtx, enum machine_mode); -extern int small_int (rtx, enum machine_mode); -extern int logic_int (rtx, enum machine_mode); -extern int call_insn_operand (rtx, enum machine_mode); -#ifdef TREE_CODE -extern void i860_va_start (tree, rtx); -#endif /* TREE_CODE */ -#endif /* RTX_CODE */ - -extern void tdesc_section (void); - diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c deleted file mode 100644 index bcc6477990d..00000000000 --- a/gcc/config/i860/i860.c +++ /dev/null @@ -1,2127 +0,0 @@ -/* Subroutines for insn-output.c for Intel i860 - Copyright (C) 1989, 1991, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005 - Free Software Foundation, Inc. - Derived from sparc.c. - - Written by Richard Stallman (rms@ai.mit.edu). - - Hacked substantially by Ron Guilmette (rfg@netcom.com) to cater - to the whims of the System V Release 4 assembler. - -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 "flags.h" -#include "rtl.h" -#include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "recog.h" -#include "insn-attr.h" -#include "function.h" -#include "expr.h" -#include "optabs.h" -#include "toplev.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" -#include "langhooks.h" -#include "tree-gimple.h" - -static rtx find_addr_reg (rtx); - -#ifndef I860_REG_PREFIX -#define I860_REG_PREFIX "" -#endif - -const char *i860_reg_prefix = I860_REG_PREFIX; - -/* Save information from a "cmpxx" operation until the branch is emitted. */ - -rtx i860_compare_op0, i860_compare_op1; - -/* Return nonzero if this pattern, can be evaluated safely, even if it - was not asked for. */ -int -safe_insn_src_p (rtx op, enum machine_mode mode) -{ - /* Just experimenting. */ - - /* No floating point source is safe if it contains an arithmetic - operation, since that operation may trap. */ - switch (GET_CODE (op)) - { - case CONST_INT: - case LABEL_REF: - case SYMBOL_REF: - case CONST: - return 1; - - case REG: - return 1; - - case MEM: - return CONSTANT_ADDRESS_P (XEXP (op, 0)); - - /* We never need to negate or complement constants. */ - case NEG: - return (mode != SFmode && mode != DFmode); - case NOT: - case ZERO_EXTEND: - return 1; - - case EQ: - case NE: - case LT: - case GT: - case LE: - case GE: - case LTU: - case GTU: - case LEU: - case GEU: - case MINUS: - case PLUS: - return (mode != SFmode && mode != DFmode); - case AND: - case IOR: - case XOR: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0))) - || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1)))) - return 0; - return 1; - - default: - return 0; - } -} - -/* Return 1 if REG is clobbered in IN. - Return 2 if REG is used in IN. - Return 3 if REG is both used and clobbered in IN. - Return 0 if none of the above. */ - -static int -reg_clobbered_p (rtx reg, rtx in) -{ - register enum rtx_code code; - - if (in == 0) - return 0; - - code = GET_CODE (in); - - if (code == SET || code == CLOBBER) - { - rtx dest = SET_DEST (in); - int set = 0; - int used = 0; - - while (GET_CODE (dest) == STRICT_LOW_PART - || GET_CODE (dest) == SUBREG - || GET_CODE (dest) == ZERO_EXTRACT) - dest = XEXP (dest, 0); - - if (dest == reg) - set = 1; - else if (GET_CODE (dest) == REG - && refers_to_regno_p (REGNO (reg), - REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), - SET_DEST (in), 0)) - { - set = 1; - /* Anything that sets just part of the register - is considered using as well as setting it. - But note that a straight SUBREG of a single-word value - clobbers the entire value. */ - if (dest != SET_DEST (in) - && ! (GET_CODE (SET_DEST (in)) == SUBREG - || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest)))) - used = 1; - } - - if (code == SET) - { - if (set) - used = refers_to_regno_p (REGNO (reg), - REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), - SET_SRC (in), 0); - else - used = refers_to_regno_p (REGNO (reg), - REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), - in, 0); - } - - return set + used * 2; - } - - if (refers_to_regno_p (REGNO (reg), - REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)), - in, 0)) - return 2; - return 0; -} - -/* Return nonzero if OP can be written to without screwing up - GCC's model of what's going on. It is assumed that this operand - appears in the dest position of a SET insn in a conditional - branch's delay slot. AFTER is the label to start looking from. */ -int -operand_clobbered_before_used_after (rtx op, rtx after) -{ - /* Just experimenting. */ - if (GET_CODE (op) == CC0) - return 1; - if (GET_CODE (op) == REG) - { - rtx insn; - - if (op == stack_pointer_rtx) - return 0; - - /* Scan forward from the label, to see if the value of OP - is clobbered before the first use. */ - - for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == NOTE) - continue; - if (GET_CODE (insn) == INSN - || GET_CODE (insn) == JUMP_INSN - || GET_CODE (insn) == CALL_INSN) - { - switch (reg_clobbered_p (op, PATTERN (insn))) - { - default: - return 0; - case 1: - return 1; - case 0: - break; - } - } - /* If we reach another label without clobbering OP, - then we cannot safely write it here. */ - else if (GET_CODE (insn) == CODE_LABEL) - return 0; - if (GET_CODE (insn) == JUMP_INSN) - { - if (condjump_p (insn)) - return 0; - /* This is a jump insn which has already - been mangled. We can't tell what it does. */ - if (GET_CODE (PATTERN (insn)) == PARALLEL) - return 0; - if (! JUMP_LABEL (insn)) - return 0; - /* Keep following jumps. */ - insn = JUMP_LABEL (insn); - } - } - return 1; - } - - /* In both of these cases, the first insn executed - for this op will be a orh whatever%h,%r0,%r31, - which is tolerable. */ - if (GET_CODE (op) == MEM) - return (CONSTANT_ADDRESS_P (XEXP (op, 0))); - - return 0; -} - - -/* Return nonzero only if OP is a register of mode MODE, - or const0_rtx. */ -int -reg_or_0_operand (rtx op, enum machine_mode mode) -{ - return (op == const0_rtx || register_operand (op, mode) - || op == CONST0_RTX (mode)); -} - -/* Return truth value of whether OP can be used as an operands in a three - address add/subtract insn (such as add %o1,7,%l2) of mode MODE. */ - -int -arith_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); -} - -/* Return 1 if OP is a valid first operand for a logical insn of mode MODE. */ - -int -logic_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && LOGIC_INT (op))); -} - -/* Return 1 if OP is a valid first operand for a shift insn of mode MODE. */ - -int -shift_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT)); -} - -/* Return 1 if OP is a valid first operand for either a logical insn - or an add insn of mode MODE. */ - -int -compare_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op))); -} - -/* Return truth value of whether OP can be used as the 5-bit immediate - operand of a bte or btne insn. */ - -int -bte_operand (rtx op, enum machine_mode mode) -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && (unsigned) INTVAL (op) < 0x20)); -} - -/* Return 1 if OP is an indexed memory reference of mode MODE. */ - -int -indexed_operand (rtx op, enum machine_mode mode) -{ - return (GET_CODE (op) == MEM && GET_MODE (op) == mode - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_MODE (XEXP (op, 0)) == SImode - && register_operand (XEXP (XEXP (op, 0), 0), SImode) - && register_operand (XEXP (XEXP (op, 0), 1), SImode)); -} - -/* Return 1 if OP is a suitable source operand for a load insn - with mode MODE. */ - -int -load_operand (rtx op, enum machine_mode mode) -{ - return (memory_operand (op, mode) || indexed_operand (op, mode)); -} - -/* Return truth value of whether OP is an integer which fits the - range constraining immediate operands in add/subtract insns. */ - -int -small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && SMALL_INT (op)); -} - -/* Return truth value of whether OP is an integer which fits the - range constraining immediate operands in logic insns. */ - -int -logic_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && LOGIC_INT (op)); -} - -/* Test for a valid operand for a call instruction. - Don't allow the arg pointer register or virtual regs - since they may change into reg + const, which the patterns - can't handle yet. */ - -int -call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == MEM - && (CONSTANT_ADDRESS_P (XEXP (op, 0)) - || (GET_CODE (XEXP (op, 0)) == REG - && XEXP (op, 0) != arg_pointer_rtx - && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER - && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) - return 1; - return 0; -} - -/* Return the best assembler insn template - for moving operands[1] into operands[0] as a fullword. */ - -static const char * -singlemove_string (rtx *operands) -{ - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (operands[1]) != MEM) - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && cc_prev_status.mdep == XEXP (operands[0], 0))) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h0,%?r0,%?r31", operands); - } - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - return "st.l %r1,%L0(%?r31)"; - } - else - return "st.l %r1,%0"; - else - abort (); -#if 0 - { - rtx xoperands[2]; - - cc_status.flags &= ~CC_F0_IS_0; - xoperands[0] = gen_rtx_REG (SFmode, 32); - xoperands[1] = operands[1]; - output_asm_insn (singlemove_string (xoperands), xoperands); - xoperands[1] = xoperands[0]; - xoperands[0] = operands[0]; - output_asm_insn (singlemove_string (xoperands), xoperands); - return ""; - } -#endif - } - if (GET_CODE (operands[1]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && cc_prev_status.mdep == XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h1,%?r0,%?r31", operands); - } - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return "ld.l %L1(%?r31),%0"; - } - return "ld.l %m1,%0"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - if (operands[1] == const0_rtx) - return "mov %?r0,%0"; - if((INTVAL (operands[1]) & 0xffff0000) == 0) - return "or %L1,%?r0,%0"; - if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000) - return "adds %1,%?r0,%0"; - if((INTVAL (operands[1]) & 0x0000ffff) == 0) - return "orh %H1,%?r0,%0"; - - return "orh %H1,%?r0,%0\n\tor %L1,%0,%0"; - } - return "mov %1,%0"; -} - -/* Output assembler code to perform a doubleword move insn - with operands OPERANDS. */ - -const char * -output_move_double (rtx *operands) -{ - enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; - rtx latehalf[2]; - rtx addreg0 = 0, addreg1 = 0; - int highest_first = 0; - int no_addreg1_decrement = 0; - - /* First classify both operands. */ - - if (REG_P (operands[0])) - optype0 = REGOP; - else if (offsettable_memref_p (operands[0])) - optype0 = OFFSOP; - else if (GET_CODE (operands[0]) == MEM) - optype0 = MEMOP; - else - optype0 = RNDOP; - - if (REG_P (operands[1])) - optype1 = REGOP; - else if (CONSTANT_P (operands[1])) - optype1 = CNSTOP; - else if (offsettable_memref_p (operands[1])) - optype1 = OFFSOP; - else if (GET_CODE (operands[1]) == MEM) - optype1 = MEMOP; - else - optype1 = RNDOP; - - /* Check for the cases that the operand constraints are not - supposed to allow to happen. Abort if we get one, - because generating code for these cases is painful. */ - - if (optype0 == RNDOP || optype1 == RNDOP) - abort (); - - /* If an operand is an unoffsettable memory reference, find a register - we can increment temporarily to make it refer to the second word. */ - - if (optype0 == MEMOP) - addreg0 = find_addr_reg (XEXP (operands[0], 0)); - - if (optype1 == MEMOP) - addreg1 = find_addr_reg (XEXP (operands[1], 0)); - -/* ??? Perhaps in some cases move double words - if there is a spare pair of floating regs. */ - - /* Ok, we can do one word at a time. - Normally we do the low-numbered word first, - but if either operand is autodecrementing then we - do the high-numbered word first. - - In either case, set up in LATEHALF the operands to use - for the high-numbered word and in some cases alter the - operands in OPERANDS to be suitable for the low-numbered word. */ - - if (optype0 == REGOP) - latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else if (optype0 == OFFSOP) - latehalf[0] = adjust_address (operands[0], SImode, 4); - else - latehalf[0] = operands[0]; - - if (optype1 == REGOP) - latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); - else if (optype1 == OFFSOP) - latehalf[1] = adjust_address (operands[1], SImode, 4); - else if (optype1 == CNSTOP) - { - if (GET_CODE (operands[1]) == CONST_DOUBLE) - split_double (operands[1], &operands[1], &latehalf[1]); -#if 0 - else if (CONSTANT_P (operands[1])) - latehalf[1] = const0_rtx; -#else - else if (CONSTANT_P (operands[1])) - split_double (operands[1], &operands[1], &latehalf[1]); -#endif - } - else - latehalf[1] = operands[1]; - - /* If the first move would clobber the source of the second one, - do them in the other order. - - RMS says "This happens only for registers; - such overlap can't happen in memory unless the user explicitly - sets it up, and that is an undefined circumstance." - - But it happens on the sparc when loading parameter registers, - so I am going to define that circumstance, and make it work - as expected. */ - - if (optype0 == REGOP && optype1 == REGOP - && REGNO (operands[0]) == REGNO (latehalf[1])) - { - CC_STATUS_PARTIAL_INIT; - /* Make any unoffsettable addresses point at high-numbered word. */ - if (addreg0) - output_asm_insn ("adds 0x4,%0,%0", &addreg0); - if (addreg1) - output_asm_insn ("adds 0x4,%0,%0", &addreg1); - - /* Do that word. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - - /* Undo the adds we just did. */ - if (addreg0) - output_asm_insn ("adds -0x4,%0,%0", &addreg0); - if (addreg1) - output_asm_insn ("adds -0x4,%0,%0", &addreg1); - - /* Do low-numbered word. */ - return singlemove_string (operands); - } - else if (optype0 == REGOP && optype1 != REGOP - && reg_overlap_mentioned_p (operands[0], operands[1])) - { - /* If both halves of dest are used in the src memory address, - add the two regs and put them in the low reg (operands[0]). - Then it works to load latehalf first. */ - if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) - && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) - { - rtx xops[2]; - xops[0] = latehalf[0]; - xops[1] = operands[0]; - output_asm_insn ("adds %1,%0,%1", xops); - operands[1] = gen_rtx_MEM (DImode, operands[0]); - latehalf[1] = adjust_address (operands[1], SImode, 4); - addreg1 = 0; - highest_first = 1; - } - /* Only one register in the dest is used in the src memory address, - and this is the first register of the dest, so we want to do - the late half first here also. */ - else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) - highest_first = 1; - /* Only one register in the dest is used in the src memory address, - and this is the second register of the dest, so we want to do - the late half last. If addreg1 is set, and addreg1 is the same - register as latehalf, then we must suppress the trailing decrement, - because it would clobber the value just loaded. */ - else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0])) - no_addreg1_decrement = 1; - } - - /* Normal case: do the two words, low-numbered first. - Overlap case (highest_first set): do high-numbered word first. */ - - if (! highest_first) - output_asm_insn (singlemove_string (operands), operands); - - CC_STATUS_PARTIAL_INIT; - /* Make any unoffsettable addresses point at high-numbered word. */ - if (addreg0) - output_asm_insn ("adds 0x4,%0,%0", &addreg0); - if (addreg1) - output_asm_insn ("adds 0x4,%0,%0", &addreg1); - - /* Do that word. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - - /* Undo the adds we just did. */ - if (addreg0) - output_asm_insn ("adds -0x4,%0,%0", &addreg0); - if (addreg1 && !no_addreg1_decrement) - output_asm_insn ("adds -0x4,%0,%0", &addreg1); - - if (highest_first) - output_asm_insn (singlemove_string (operands), operands); - - return ""; -} - -const char * -output_fp_move_double (rtx *operands) -{ - /* If the source operand is any sort of zero, use f0 instead. */ - - if (operands[1] == CONST0_RTX (GET_MODE (operands[1]))) - operands[1] = gen_rtx_REG (DFmode, F0_REGNUM); - - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return "fmov.dd %1,%0"; - if (GET_CODE (operands[1]) == REG) - { - output_asm_insn ("ixfr %1,%0", operands); - operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1); - operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1); - return "ixfr %1,%0"; - } - if (operands[1] == CONST0_RTX (DFmode)) - return "fmov.dd f0,%0"; - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && cc_prev_status.mdep == XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h1,%?r0,%?r31", operands); - } - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return "fld.d %L1(%?r31),%0"; - } - return "fld.d %1,%0"; - } - else if (FP_REG_P (operands[1])) - { - if (GET_CODE (operands[0]) == REG) - { - output_asm_insn ("fxfr %1,%0", operands); - operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1); - operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1); - return "fxfr %1,%0"; - } - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && cc_prev_status.mdep == XEXP (operands[0], 0))) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h0,%?r0,%?r31", operands); - } - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - return "fst.d %1,%L0(%?r31)"; - } - return "fst.d %1,%0"; - } - else - abort (); - /* NOTREACHED */ - return NULL; -} - -/* Return a REG that occurs in ADDR with coefficient 1. - ADDR can be effectively incremented by incrementing REG. */ - -static rtx -find_addr_reg (rtx addr) -{ - while (GET_CODE (addr) == PLUS) - { - if (GET_CODE (XEXP (addr, 0)) == REG) - addr = XEXP (addr, 0); - else if (GET_CODE (XEXP (addr, 1)) == REG) - addr = XEXP (addr, 1); - else if (CONSTANT_P (XEXP (addr, 0))) - addr = XEXP (addr, 1); - else if (CONSTANT_P (XEXP (addr, 1))) - addr = XEXP (addr, 0); - else - abort (); - } - if (GET_CODE (addr) == REG) - return addr; - abort (); - /* NOTREACHED */ - return NULL; -} - -/* Return a template for a load instruction with mode MODE and - arguments from the string ARGS. - - This string is in static storage. */ - -static const char * -load_opcode (enum machine_mode mode, const char *args, rtx reg) -{ - static char buf[30]; - const char *opcode; - - switch (mode) - { - case QImode: - opcode = "ld.b"; - break; - - case HImode: - opcode = "ld.s"; - break; - - case SImode: - case SFmode: - if (FP_REG_P (reg)) - opcode = "fld.l"; - else - opcode = "ld.l"; - break; - - case DImode: - if (!FP_REG_P (reg)) - abort (); - case DFmode: - opcode = "fld.d"; - break; - - default: - abort (); - } - - sprintf (buf, "%s %s", opcode, args); - return buf; -} - -/* Return a template for a store instruction with mode MODE and - arguments from the string ARGS. - - This string is in static storage. */ - -static const char * -store_opcode (enum machine_mode mode, const char *args, rtx reg) -{ - static char buf[30]; - const char *opcode; - - switch (mode) - { - case QImode: - opcode = "st.b"; - break; - - case HImode: - opcode = "st.s"; - break; - - case SImode: - case SFmode: - if (FP_REG_P (reg)) - opcode = "fst.l"; - else - opcode = "st.l"; - break; - - case DImode: - if (!FP_REG_P (reg)) - abort (); - case DFmode: - opcode = "fst.d"; - break; - - default: - abort (); - } - - sprintf (buf, "%s %s", opcode, args); - return buf; -} - -/* Output a store-in-memory whose operands are OPERANDS[0,1]. - OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero. - - This function returns a template for an insn. - This is in static storage. - - It may also output some insns directly. - It may alter the values of operands[0] and operands[1]. */ - -const char * -output_store (rtx *operands) -{ - enum machine_mode mode = GET_MODE (operands[0]); - rtx address = XEXP (operands[0], 0); - - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = address; - - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && address == cc_prev_status.mdep)) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h0,%?r0,%?r31", operands); - cc_prev_status.mdep = address; - } - - /* Store zero in two parts when appropriate. */ - if (mode == DFmode && operands[1] == CONST0_RTX (DFmode)) - return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]); - - /* Code below isn't smart enough to move a doubleword in two parts, - so use output_move_double to do that in the cases that require it. */ - if ((mode == DImode || mode == DFmode) - && ! FP_REG_P (operands[1])) - return output_move_double (operands); - - return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]); -} - -/* Output a load-from-memory whose operands are OPERANDS[0,1]. - OPERANDS[0] is a reg, and OPERANDS[1] is a mem. - - This function returns a template for an insn. - This is in static storage. - - It may also output some insns directly. - It may alter the values of operands[0] and operands[1]. */ - -const char * -output_load (rtx *operands) -{ - enum machine_mode mode = GET_MODE (operands[0]); - rtx address = XEXP (operands[1], 0); - - /* We don't bother trying to see if we know %hi(address). - This is because we are doing a load, and if we know the - %hi value, we probably also know that value in memory. */ - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = address; - - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && address == cc_prev_status.mdep - && cc_prev_status.mdep == cc_status.mdep)) - { - CC_STATUS_INIT; - output_asm_insn ("orh %h1,%?r0,%?r31", operands); - cc_prev_status.mdep = address; - } - - /* Code below isn't smart enough to move a doubleword in two parts, - so use output_move_double to do that in the cases that require it. */ - if ((mode == DImode || mode == DFmode) - && ! FP_REG_P (operands[0])) - return output_move_double (operands); - - return load_opcode (mode, "%L1(%?r31),%0", operands[0]); -} - -#if 0 -/* Load the address specified by OPERANDS[3] into the register - specified by OPERANDS[0]. - - OPERANDS[3] may be the result of a sum, hence it could either be: - - (1) CONST - (2) REG - (2) REG + CONST_INT - (3) REG + REG + CONST_INT - (4) REG + REG (special case of 3). - - Note that (3) is not a legitimate address. - All cases are handled here. */ - -void -output_load_address (rtx *operands) -{ - rtx base, offset; - - if (CONSTANT_P (operands[3])) - { - output_asm_insn ("mov %3,%0", operands); - return; - } - - if (REG_P (operands[3])) - { - if (REGNO (operands[0]) != REGNO (operands[3])) - output_asm_insn ("shl %?r0,%3,%0", operands); - return; - } - - if (GET_CODE (operands[3]) != PLUS) - abort (); - - base = XEXP (operands[3], 0); - offset = XEXP (operands[3], 1); - - if (GET_CODE (base) == CONST_INT) - { - rtx tmp = base; - base = offset; - offset = tmp; - } - - if (GET_CODE (offset) != CONST_INT) - { - /* Operand is (PLUS (REG) (REG)). */ - base = operands[3]; - offset = const0_rtx; - } - - if (REG_P (base)) - { - operands[6] = base; - operands[7] = offset; - CC_STATUS_PARTIAL_INIT; - if (SMALL_INT (offset)) - output_asm_insn ("adds %7,%6,%0", operands); - else - output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands); - } - else if (GET_CODE (base) == PLUS) - { - operands[6] = XEXP (base, 0); - operands[7] = XEXP (base, 1); - operands[8] = offset; - - CC_STATUS_PARTIAL_INIT; - if (SMALL_INT (offset)) - output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands); - else - output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands); - } - else - abort (); -} -#endif - -/* Output code to place a size count SIZE in register REG. - Because block moves are pipelined, we don't include the - first element in the transfer of SIZE to REG. - For this, we subtract ALIGN. (Actually, I think it is not - right to subtract on this machine, so right now we don't.) */ - -static void -output_size_for_block_move (rtx size, rtx reg, rtx align) -{ - rtx xoperands[3]; - - xoperands[0] = reg; - xoperands[1] = size; - xoperands[2] = align; - -#if 1 - cc_status.flags &= ~ CC_KNOW_HI_R31; - output_asm_insn (singlemove_string (xoperands), xoperands); -#else - if (GET_CODE (size) == REG) - output_asm_insn ("sub %2,%1,%0", xoperands); - else - { - xoperands[1] = GEN_INT (INTVAL (size) - INTVAL (align)); - cc_status.flags &= ~ CC_KNOW_HI_R31; - output_asm_insn ("mov %1,%0", xoperands); - } -#endif -} - -/* Emit code to perform a block move. - - OPERANDS[0] is the destination. - OPERANDS[1] is the source. - OPERANDS[2] is the size. - OPERANDS[3] is the known safe alignment. - OPERANDS[4..6] are pseudos we can safely clobber as temps. */ - -const char * -output_block_move (rtx *operands) -{ - /* A vector for our computed operands. Note that load_output_address - makes use of (and can clobber) up to the 8th element of this vector. */ - rtx xoperands[10]; -#if 0 - rtx zoperands[10]; -#endif - static int movmemsi_label = 0; - int i; - rtx temp1 = operands[4]; - rtx alignrtx = operands[3]; - int align = INTVAL (alignrtx); - int chunk_size; - - xoperands[0] = operands[0]; - xoperands[1] = operands[1]; - xoperands[2] = temp1; - - /* We can't move more than four bytes at a time - because we have only one register to move them through. */ - if (align > 4) - { - align = 4; - alignrtx = GEN_INT (4); - } - - /* Recognize special cases of block moves. These occur - when GNU C++ is forced to treat something as BLKmode - to keep it in memory, when its mode could be represented - with something smaller. - - We cannot do this for global variables, since we don't know - what pages they don't cross. Sigh. */ - if (GET_CODE (operands[2]) == CONST_INT - && ! CONSTANT_ADDRESS_P (operands[0]) - && ! CONSTANT_ADDRESS_P (operands[1])) - { - int size = INTVAL (operands[2]); - rtx op0 = xoperands[0]; - rtx op1 = xoperands[1]; - - if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16) - { - if (memory_address_p (SImode, plus_constant (op0, size)) - && memory_address_p (SImode, plus_constant (op1, size))) - { - cc_status.flags &= ~CC_KNOW_HI_R31; - for (i = (size>>2)-1; i >= 0; i--) - { - xoperands[0] = plus_constant (op0, i * 4); - xoperands[1] = plus_constant (op1, i * 4); - output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0", - xoperands); - } - return ""; - } - } - else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16) - { - if (memory_address_p (HImode, plus_constant (op0, size)) - && memory_address_p (HImode, plus_constant (op1, size))) - { - cc_status.flags &= ~CC_KNOW_HI_R31; - for (i = (size>>1)-1; i >= 0; i--) - { - xoperands[0] = plus_constant (op0, i * 2); - xoperands[1] = plus_constant (op1, i * 2); - output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0", - xoperands); - } - return ""; - } - } - else if (size <= 16) - { - if (memory_address_p (QImode, plus_constant (op0, size)) - && memory_address_p (QImode, plus_constant (op1, size))) - { - cc_status.flags &= ~CC_KNOW_HI_R31; - for (i = size-1; i >= 0; i--) - { - xoperands[0] = plus_constant (op0, i); - xoperands[1] = plus_constant (op1, i); - output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0", - xoperands); - } - return ""; - } - } - } - - /* Since we clobber untold things, nix the condition codes. */ - CC_STATUS_INIT; - - /* This is the size of the transfer. - Either use the register which already contains the size, - or use a free register (used by no operands). */ - output_size_for_block_move (operands[2], operands[4], alignrtx); - -#if 0 - /* Also emit code to decrement the size value by ALIGN. */ - zoperands[0] = operands[0]; - zoperands[3] = plus_constant (operands[0], align); - output_load_address (zoperands); -#endif - - /* Generate number for unique label. */ - - xoperands[3] = GEN_INT (movmemsi_label++); - - /* Calculate the size of the chunks we will be trying to move first. */ - -#if 0 - if ((align & 3) == 0) - chunk_size = 4; - else if ((align & 1) == 0) - chunk_size = 2; - else -#endif - chunk_size = 1; - - /* Copy the increment (negative) to a register for bla insn. */ - - xoperands[4] = GEN_INT (- chunk_size); - xoperands[5] = operands[5]; - output_asm_insn ("adds %4,%?r0,%5", xoperands); - - /* Predecrement the loop counter. This happens again also in the `bla' - instruction which precedes the loop, but we need to have it done - two times before we enter the loop because of the bizarre semantics - of the bla instruction. */ - - output_asm_insn ("adds %5,%2,%2", xoperands); - - /* Check for the case where the original count was less than or equal to - zero. Avoid going through the loop at all if the original count was - indeed less than or equal to zero. Note that we treat the count as - if it were a signed 32-bit quantity here, rather than an unsigned one, - even though we really shouldn't. We have to do this because of the - semantics of the `ble' instruction, which assume that the count is - a signed 32-bit value. Anyway, in practice it won't matter because - nobody is going to try to do a memcpy() of more than half of the - entire address space (i.e. 2 gigabytes) anyway. */ - - output_asm_insn ("bc .Le%3", xoperands); - - /* Make available a register which is a temporary. */ - - xoperands[6] = operands[6]; - - /* Now the actual loop. - In xoperands, elements 1 and 0 are the input and output vectors. - Element 2 is the loop index. Element 5 is the increment. */ - - output_asm_insn ("subs %1,%5,%1", xoperands); - output_asm_insn ("bla %5,%2,.Lm%3", xoperands); - output_asm_insn ("adds %0,%2,%6", xoperands); - output_asm_insn ("\n.Lm%3:", xoperands); /* Label for bla above. */ - output_asm_insn ("\n.Ls%3:", xoperands); /* Loop start label. */ - output_asm_insn ("adds %5,%6,%6", xoperands); - - /* NOTE: The code here which is supposed to handle the cases where the - sources and destinations are known to start on a 4 or 2 byte boundary - are currently broken. They fail to do anything about the overflow - bytes which might still need to be copied even after we have copied - some number of words or halfwords. Thus, for now we use the lowest - common denominator, i.e. the code which just copies some number of - totally unaligned individual bytes. (See the calculation of - chunk_size above. */ - - if (chunk_size == 4) - { - output_asm_insn ("ld.l %2(%1),%?r31", xoperands); - output_asm_insn ("bla %5,%2,.Ls%3", xoperands); - output_asm_insn ("st.l %?r31,8(%6)", xoperands); - } - else if (chunk_size == 2) - { - output_asm_insn ("ld.s %2(%1),%?r31", xoperands); - output_asm_insn ("bla %5,%2,.Ls%3", xoperands); - output_asm_insn ("st.s %?r31,4(%6)", xoperands); - } - else /* chunk_size == 1 */ - { - output_asm_insn ("ld.b %2(%1),%?r31", xoperands); - output_asm_insn ("bla %5,%2,.Ls%3", xoperands); - output_asm_insn ("st.b %?r31,2(%6)", xoperands); - } - output_asm_insn ("\n.Le%3:", xoperands); /* Here if count <= 0. */ - - return ""; -} - -/* Special routine to convert an SFmode value represented as a - CONST_DOUBLE into its equivalent unsigned long bit pattern. - We convert the value from a double precision floating-point - value to single precision first, and thence to a bit-wise - equivalent unsigned long value. This routine is used when - generating an immediate move of an SFmode value directly - into a general register because the SVR4 assembler doesn't - grok floating literals in instruction operand contexts. */ - -unsigned long -sfmode_constant_to_ulong (rtx x) -{ - REAL_VALUE_TYPE d; - unsigned long l; - - if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode) - abort (); - - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - REAL_VALUE_TO_TARGET_SINGLE (d, l); - return l; -} - -/* This function generates the assembly code for function entry. - - ASM_FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - - Refer to the array `regs_ever_live' to determine which registers - to save; `regs_ever_live[I]' is nonzero if register number I - is ever used in the function. This macro is responsible for - knowing which registers should not be saved even if used. - - NOTE: `frame_lower_bytes' is the count of bytes which will lie - between the new `fp' value and the new `sp' value after the - prologue is done. `frame_upper_bytes' is the count of bytes - that will lie between the new `fp' and the *old* `sp' value - after the new `fp' is setup (in the prologue). The upper - part of each frame always includes at least 2 words (8 bytes) - to hold the saved frame pointer and the saved return address. - - The SVR4 ABI for the i860 now requires that the values of the - stack pointer and frame pointer registers be kept aligned to - 16-byte boundaries at all times. We obey that restriction here. - - The SVR4 ABI for the i860 is entirely vague when it comes to specifying - exactly where the "preserved" registers should be saved. The native - SVR4 C compiler I now have doesn't help to clarify the requirements - very much because it is plainly out-of-date and non-ABI-compliant - (in at least one important way, i.e. how it generates function - epilogues). - - The native SVR4 C compiler saves the "preserved" registers (i.e. - r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative - offsets from the frame pointer). - - Previous versions of GCC also saved the "preserved" registers in the - "negative" part of the frame, but they saved them using positive - offsets from the (adjusted) stack pointer (after it had been adjusted - to allocate space for the new frame). That's just plain wrong - because if the current function calls alloca(), the stack pointer - will get moved, and it will be impossible to restore the registers - properly again after that. - - Both compilers handled parameter registers (i.e. r16-r27 and f8-f15) - by copying their values either into various "preserved" registers or - into stack slots in the lower part of the current frame (as seemed - appropriate, depending upon subsequent usage of these values). - - Here we want to save the preserved registers at some offset from the - frame pointer register so as to avoid any possible problems arising - from calls to alloca(). We can either save them at small positive - offsets from the frame pointer, or at small negative offsets from - the frame pointer. If we save them at small negative offsets from - the frame pointer (i.e. in the lower part of the frame) then we - must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how - many bytes of space we plan to use in the lower part of the frame - for this purpose. Since other parts of the compiler reference the - value of STARTING_FRAME_OFFSET long before final() calls this function, - we would have to go ahead and assume the worst-case storage requirements - for saving all of the "preserved" registers (and use that number, i.e. - `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in - the lower part of the frame. That could potentially be very wasteful, - and that wastefulness could really hamper people compiling for embedded - i860 targets with very tight limits on stack space. Thus, we choose - here to save the preserved registers in the upper part of the - frame, so that we can decide at the very last minute how much (or how - little) space we must allocate for this purpose. - - To satisfy the needs of the SVR4 ABI "tdesc" scheme, preserved - registers must always be saved so that the saved values of registers - with higher numbers are at higher addresses. We obey that restriction - here. - - There are two somewhat different ways that you can generate prologues - here... i.e. pedantically ABI-compliant, and the "other" way. The - "other" way is more consistent with what is currently generated by the - "native" SVR4 C compiler for the i860. That's important if you want - to use the current (as of 8/91) incarnation of SVR4 SDB for the i860. - The SVR4 SDB for the i860 insists on having function prologues be - non-ABI-compliant! - - To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES - in the i860/sysv4.h file. (By default this is *not* defined). - - The differences between the ABI-compliant and non-ABI-compliant prologues - are that (a) the ABI version seems to require the use of *signed* - (rather than unsigned) adds and subtracts, and (b) the ordering of - the various steps (e.g. saving preserved registers, saving the - return address, setting up the new frame pointer value) is different. - - For strict ABI compliance, it seems to be the case that the very last - thing that is supposed to happen in the prologue is getting the frame - pointer set to its new value (but only after everything else has - already been properly setup). We do that here, but only if the symbol - I860_STRICT_ABI_PROLOGUES is defined. */ - -#ifndef STACK_ALIGNMENT -#define STACK_ALIGNMENT 16 -#endif - -const char *current_function_original_name; - -static int must_preserve_r1; -static unsigned must_preserve_bytes; - -static void -i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes) -{ - register HOST_WIDE_INT frame_lower_bytes; - register HOST_WIDE_INT frame_upper_bytes; - register HOST_WIDE_INT total_fsize; - register unsigned preserved_reg_bytes = 0; - register unsigned i; - register unsigned preserved_so_far = 0; - - must_preserve_r1 = (optimize < 2 || ! leaf_function_p ()); - must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0); - - /* Count registers that need preserving. Ignore r0. It never needs - preserving. */ - - for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) - { - if (regs_ever_live[i] && ! call_used_regs[i]) - preserved_reg_bytes += 4; - } - - /* Round-up the frame_lower_bytes so that it's a multiple of 16. */ - - frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT; - - /* The upper part of each frame will contain the saved fp, - the saved r1, and stack slots for all of the other "preserved" - registers that we find we will need to save & restore. */ - - frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes; - - /* Round-up the frame_upper_bytes so that it's a multiple of 16. */ - - frame_upper_bytes - = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT; - - total_fsize = frame_upper_bytes + frame_lower_bytes; - -#ifndef I860_STRICT_ABI_PROLOGUES - - /* There are two kinds of function prologues. - You use the "small" version if the total frame size is - small enough so that it can fit into an immediate 16-bit - value in one instruction. Otherwise, you use the "large" - version of the function prologue. */ - - if (total_fsize > 0x7fff) - { - /* Adjust the stack pointer. The ABI specifies using `adds' for - this, but the native C compiler on SVR4 uses `addu'. */ - - fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n", - frame_upper_bytes, i860_reg_prefix, i860_reg_prefix); - - /* Save the old frame pointer. */ - - fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n", - i860_reg_prefix, i860_reg_prefix); - - /* Setup the new frame pointer. The ABI specifies that this is to - be done after preserving registers (using `adds'), but that's not - what the native C compiler on SVR4 does. */ - - fprintf (asm_file, "\taddu 0,%ssp,%sfp\n", - i860_reg_prefix, i860_reg_prefix); - - /* Get the value of frame_lower_bytes into r31. */ - - fprintf (asm_file, "\torh " HOST_WIDE_INT_PRINT_DEC ",%sr0,%sr31\n", - frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix); - fprintf (asm_file, "\tor " HOST_WIDE_INT_PRINT_DEC ",%sr31,%sr31\n", - frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix); - - /* Now re-adjust the stack pointer using the value in r31. - The ABI specifies that this is done with `subs' but SDB may - prefer `subu'. */ - - fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n", - i860_reg_prefix, i860_reg_prefix, i860_reg_prefix); - - /* Preserve registers. The ABI specifies that this is to be done - before setting up the new frame pointer, but that's not what the - native C compiler on SVR4 does. */ - - for (i = 1; i < 32; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - for (i = 32; i < 64; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - /* Save the return address. */ - - if (must_preserve_r1) - fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n", - i860_reg_prefix, i860_reg_prefix); - } - else - { - /* Adjust the stack pointer. The ABI specifies using `adds' for this, - but the native C compiler on SVR4 uses `addu'. */ - - fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n", - total_fsize, i860_reg_prefix, i860_reg_prefix); - - /* Save the old frame pointer. */ - - fprintf (asm_file, "\tst.l %sfp," HOST_WIDE_INT_PRINT_DEC "(%ssp)\n", - i860_reg_prefix, frame_lower_bytes, i860_reg_prefix); - - /* Setup the new frame pointer. The ABI specifies that this is to be - done after preserving registers and after saving the return address, - (and to do it using `adds'), but that's not what the native C - compiler on SVR4 does. */ - - fprintf (asm_file, "\taddu " HOST_WIDE_INT_PRINT_DEC ",%ssp,%sfp\n", - frame_lower_bytes, i860_reg_prefix, i860_reg_prefix); - - /* Preserve registers. The ABI specifies that this is to be done - before setting up the new frame pointer, but that's not what the - native compiler on SVR4 does. */ - - for (i = 1; i < 32; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - for (i = 32; i < 64; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - /* Save the return address. The ABI specifies that this is to be - done earlier, and also via an offset from %sp, but the native C - compiler on SVR4 does it later (i.e. now) and uses an offset from - %fp. */ - - if (must_preserve_r1) - fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n", - i860_reg_prefix, i860_reg_prefix); - } - -#else /* defined(I860_STRICT_ABI_PROLOGUES) */ - - /* There are two kinds of function prologues. - You use the "small" version if the total frame size is - small enough so that it can fit into an immediate 16-bit - value in one instruction. Otherwise, you use the "large" - version of the function prologue. */ - - if (total_fsize > 0x7fff) - { - /* Adjust the stack pointer (thereby allocating a new frame). */ - - fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n", - frame_upper_bytes, i860_reg_prefix, i860_reg_prefix); - - /* Save the caller's frame pointer. */ - - fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n", - i860_reg_prefix, i860_reg_prefix); - - /* Save return address. */ - - if (must_preserve_r1) - fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n", - i860_reg_prefix, i860_reg_prefix); - - /* Get the value of frame_lower_bytes into r31 for later use. */ - - fprintf (asm_file, "\torh %d,%sr0,%sr31\n", - frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix); - fprintf (asm_file, "\tor %d,%sr31,%sr31\n", - frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix); - - /* Now re-adjust the stack pointer using the value in r31. */ - - fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n", - i860_reg_prefix, i860_reg_prefix, i860_reg_prefix); - - /* Pre-compute value to be used as the new frame pointer. */ - - fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n", - i860_reg_prefix, i860_reg_prefix, i860_reg_prefix); - - /* Preserve registers. */ - - for (i = 1; i < 32; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - for (i = 32; i < 64; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n", - i860_reg_prefix, reg_names[i], - must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - /* Actually set the new value of the frame pointer. */ - - fprintf (asm_file, "\tmov %sr31,%sfp\n", - i860_reg_prefix, i860_reg_prefix); - } - else - { - /* Adjust the stack pointer. */ - - fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n", - total_fsize, i860_reg_prefix, i860_reg_prefix); - - /* Save the caller's frame pointer. */ - - fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n", - i860_reg_prefix, frame_lower_bytes, i860_reg_prefix); - - /* Save the return address. */ - - if (must_preserve_r1) - fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n", - i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix); - - /* Preserve registers. */ - - for (i = 1; i < 32; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n", - i860_reg_prefix, reg_names[i], - frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - for (i = 32; i < 64; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) - fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n", - i860_reg_prefix, reg_names[i], - frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++), - i860_reg_prefix); - - /* Setup the new frame pointer. */ - - fprintf (asm_file, "\tadds %d,%ssp,%sfp\n", - frame_lower_bytes, i860_reg_prefix, i860_reg_prefix); - } -#endif /* defined(I860_STRICT_ABI_PROLOGUES) */ - -#ifdef ASM_OUTPUT_PROLOGUE_SUFFIX - ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file); -#endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */ -} - -/* This function generates the assembly code for function exit. - - ASM_FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. - - Note that when we go to restore the preserved register values we must - not try to address their slots by using offsets from the stack pointer. - That's because the stack pointer may have been moved during the function - execution due to a call to alloca(). Rather, we must restore all - preserved registers via offsets from the frame pointer value. - - Note also that when the current frame is being "popped" (by adjusting - the value of the stack pointer) on function exit, we must (for the - sake of alloca) set the new value of the stack pointer based upon - the current value of the frame pointer. We can't just add what we - believe to be the (static) frame size to the stack pointer because - if we did that, and alloca() had been called during this function, - we would end up returning *without* having fully deallocated all of - the space grabbed by alloca. If that happened, and a function - containing one or more alloca() calls was called over and over again, - then the stack would grow without limit! - - Finally note that the epilogues generated here are completely ABI - compliant. They go out of their way to insure that the value in - the frame pointer register is never less than the value in the stack - pointer register. It's not clear why this relationship needs to be - maintained at all times, but maintaining it only costs one extra - instruction, so what the hell. */ - -/* This corresponds to a version 4 TDESC structure. Lower numbered - versions successively omit the last word of the structure. We - don't try to handle version 5 here. */ - -typedef struct TDESC_flags { - int version:4; - int reg_packing:1; - int callable_block:1; - int reserved:4; - int fregs:6; /* fp regs 2-7 */ - int iregs:16; /* regs 0-15 */ -} TDESC_flags; - -typedef struct TDESC { - TDESC_flags flags; - int integer_reg_offset; /* same as must_preserve_bytes */ - int floating_point_reg_offset; - unsigned int positive_frame_size; /* same as frame_upper_bytes */ - unsigned int negative_frame_size; /* same as frame_lower_bytes */ -} TDESC; - -static void -i860_output_function_epilogue (FILE *asm_file, HOST_WIDE_INT local_bytes) -{ - register HOST_WIDE_INT frame_upper_bytes; - register HOST_WIDE_INT frame_lower_bytes; - register HOST_WIDE_INT preserved_reg_bytes = 0; - register unsigned i; - register unsigned restored_so_far = 0; - register unsigned int_restored; - register unsigned mask; - unsigned intflags=0; - register TDESC_flags *flags = (TDESC_flags *) &intflags; -#ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */ - const char *long_op = integer_asm_op (4, TRUE); -#endif - - flags->version = 4; - flags->reg_packing = 1; - flags->iregs = 8; /* old fp always gets saved */ - - /* Round-up the frame_lower_bytes so that it's a multiple of 16. */ - - frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT; - - /* Count the number of registers that were preserved in the prologue. - Ignore r0. It is never preserved. */ - - for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) - { - if (regs_ever_live[i] && ! call_used_regs[i]) - preserved_reg_bytes += 4; - } - - /* The upper part of each frame will contain only saved fp, - the saved r1, and stack slots for all of the other "preserved" - registers that we find we will need to save & restore. */ - - frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes; - - /* Round-up frame_upper_bytes so that t is a multiple of 16. */ - - frame_upper_bytes - = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT; - - /* Restore all of the "preserved" registers that need restoring. */ - - mask = 2; - - for (i = 1; i < 32; i++, mask<<=1) - if (regs_ever_live[i] && ! call_used_regs[i]) { - fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n", - must_preserve_bytes + (4 * restored_so_far++), - i860_reg_prefix, i860_reg_prefix, reg_names[i]); - if (i > 3 && i < 16) - flags->iregs |= mask; - } - - int_restored = restored_so_far; - mask = 1; - - for (i = 32; i < 64; i++) { - if (regs_ever_live[i] && ! call_used_regs[i]) { - fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n", - must_preserve_bytes + (4 * restored_so_far++), - i860_reg_prefix, i860_reg_prefix, reg_names[i]); - if (i > 33 && i < 40) - flags->fregs |= mask; - } - if (i > 33 && i < 40) - mask<<=1; - } - - /* Get the value we plan to use to restore the stack pointer into r31. */ - - fprintf (asm_file, "\tadds " HOST_WIDE_INT_PRINT_DEC ",%sfp,%sr31\n", - frame_upper_bytes, i860_reg_prefix, i860_reg_prefix); - - /* Restore the return address and the old frame pointer. */ - - if (must_preserve_r1) { - fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n", - i860_reg_prefix, i860_reg_prefix); - flags->iregs |= 2; - } - - fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n", - i860_reg_prefix, i860_reg_prefix); - - /* Return and restore the old stack pointer value. */ - - fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n", - i860_reg_prefix, i860_reg_prefix, i860_reg_prefix); - -#ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry. */ - if (! frame_lower_bytes) { - flags->version--; - if (! frame_upper_bytes) { - flags->version--; - if (restored_so_far == int_restored) /* No FP saves. */ - flags->version--; - } - } - assemble_name(asm_file,current_function_original_name); - fputs(".TDESC:\n", asm_file); - fprintf(asm_file, "%s 0x%0x\n", long_op, intflags); - fprintf(asm_file, "%s %d\n", long_op, - int_restored ? must_preserve_bytes : 0); - if (flags->version > 1) { - fprintf(asm_file, "%s %d\n", long_op, - (restored_so_far == int_restored) ? 0 : must_preserve_bytes + - (4 * int_restored)); - if (flags->version > 2) { - fprintf(asm_file, "%s %d\n", long_op, frame_upper_bytes); - if (flags->version > 3) - fprintf(asm_file, "%s %d\n", long_op, frame_lower_bytes); - } - } - tdesc_section(); - fprintf(asm_file, "%s ", long_op); - assemble_name(asm_file, current_function_original_name); - fprintf(asm_file, "\n%s ", long_op); - assemble_name(asm_file, current_function_original_name); - fputs(".TDESC\n", asm_file); - text_section(); -#endif -} - - -/* Expand a library call to __builtin_saveregs. */ - -static rtx -i860_saveregs (void) -{ - rtx fn = gen_rtx_SYMBOL_REF (Pmode, "__builtin_saveregs"); - rtx save = gen_reg_rtx (Pmode); - rtx valreg = LIBCALL_VALUE (Pmode); - rtx ret; - - /* The return value register overlaps the first argument register. - Save and restore it around the call. */ - emit_move_insn (save, valreg); - ret = emit_library_call_value (fn, NULL_RTX, 1, Pmode, 0); - if (GET_CODE (ret) != REG || REGNO (ret) < FIRST_PSEUDO_REGISTER) - ret = copy_to_reg (ret); - emit_move_insn (valreg, save); - - return ret; -} - -/* Create the va_list data type. - The SVR4 ABI requires the following structure: - typedef struct { - unsigned long ireg_used; - unsigned long freg_used; - long *reg_base; - long *mem_ptr; - } va_list; - - Otherwise, this structure is used: - typedef struct { - long *reg_base; - long *mem_ptr; - unsigned long ireg_used; - unsigned long freg_used; - } va_list; - - The tree representing the va_list declaration is returned. */ - -static tree -i860_build_builtin_va_list (void) -{ - tree f_gpr, f_fpr, f_mem, f_sav, record, type_decl; - - record = (*lang_hooks.types.make_type) (RECORD_TYPE); - type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); - - f_gpr = build_decl (FIELD_DECL, get_identifier ("__ireg_used"), - unsigned_type_node); - f_fpr = build_decl (FIELD_DECL, get_identifier ("__freg_used"), - unsigned_type_node); - f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_base"), - ptr_type_node); - f_mem = build_decl (FIELD_DECL, get_identifier ("__mem_ptr"), - ptr_type_node); - - DECL_FIELD_CONTEXT (f_gpr) = record; - DECL_FIELD_CONTEXT (f_fpr) = record; - DECL_FIELD_CONTEXT (f_sav) = record; - DECL_FIELD_CONTEXT (f_mem) = record; - - TREE_CHAIN (record) = type_decl; - TYPE_NAME (record) = type_decl; - -#ifdef I860_SVR4_VA_LIST - TYPE_FIELDS (record) = f_gpr; - TREE_CHAIN (f_gpr) = f_fpr; - TREE_CHAIN (f_fpr) = f_sav; - TREE_CHAIN (f_sav) = f_mem; -#else - TYPE_FIELDS (record) = f_sav; - TREE_CHAIN (f_sav) = f_mem; - TREE_CHAIN (f_mem) = f_gpr; - TREE_CHAIN (f_gpr) = f_fpr; -#endif - - layout_type (record); - return record; -} - -/* Initialize the va_list structure. */ - -void -i860_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) -{ - tree saveregs, t; - tree f_gpr, f_fpr, f_mem, f_sav; - tree gpr, fpr, mem, sav; - int off = 0; - saveregs = make_tree (ptr_type_node, expand_builtin_saveregs ()); - -#ifdef I860_SVR4_VA_LIST - f_gpr = TYPE_FIELDS (va_list_type_node); - f_fpr = TREE_CHAIN (f_gpr); - f_sav = TREE_CHAIN (f_fpr); - f_mem = TREE_CHAIN (f_sav); -#else - f_sav = TYPE_FIELDS (va_list_type_node); - f_mem = TREE_CHAIN (f_sav); - f_gpr = TREE_CHAIN (f_mem); - f_fpr = TREE_CHAIN (f_gpr); -#endif - - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); - mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE); - - /* Initialize the `mem_ptr' field to the address of the first anonymous - stack argument. */ - t = make_tree (TREE_TYPE (mem), virtual_incoming_args_rtx); - off = INTVAL (current_function_arg_offset_rtx); - off = off < 0 ? 0 : off; - t = build (PLUS_EXPR, TREE_TYPE (mem), t, build_int_cst (NULL_TREE, off, 0)); - t = build (MODIFY_EXPR, TREE_TYPE (mem), mem, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - /* Initialize the `ireg_used' field. */ - t = build_int_cst (NULL_TREE, - current_function_args_info.ints / UNITS_PER_WORD, 0); - t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - /* Initialize the `freg_used' field. */ - t = build_int_cst (NULL_TREE, - current_function_args_info.floats / UNITS_PER_WORD, 0); - t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - /* Initialize the `reg_base' field. */ - t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, saveregs); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); -} - -#define NUM_PARM_FREGS 8 -#define NUM_PARM_IREGS 12 -#ifdef I860_SVR4_VA_LIST -#define FREG_OFFSET 0 -#define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD) -#else -#define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD) -#define IREG_OFFSET 0 -#endif - -/* Update the VALIST structure as necessary for an - argument of the given TYPE, and return the argument. */ - -static tree -i860_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p) -{ - tree f_gpr, f_fpr, f_mem, f_sav; - tree gpr, fpr, mem, sav; - tree size, t, u, addr, type_ptr; - tree reg, n_reg, sav_ofs, lim_reg; - HOST_WIDE_INT isize; - bool indirect; - -#ifdef I860_SVR4_VA_LIST - f_gpr = TYPE_FIELDS (va_list_type_node); - f_fpr = TREE_CHAIN (f_gpr); - f_sav = TREE_CHAIN (f_fpr); - f_mem = TREE_CHAIN (f_sav); -#else - f_sav = TYPE_FIELDS (va_list_type_node); - f_mem = TREE_CHAIN (f_sav); - f_gpr = TREE_CHAIN (f_mem); - f_fpr = TREE_CHAIN (f_gpr); -#endif - - gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); - fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE); - mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE); - sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE); - - indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); - if (indirect) - type = build_pointer_type (type); - size = size_in_bytes (type); - type_ptr = build_pointer_type (type); - - if (AGGREGATE_TYPE_P (type)) - { - /* Aggregates are passed on the stack. */ - HOST_WIDE_INT align; - - align = TYPE_ALIGN (type); - if (align < BITS_PER_WORD) - align = BITS_PER_WORD; - align /= BITS_PER_UNIT; - - u = fold_convert (ptr_type_node, size_int (align - 1)); - t = build (PLUS_EXPR, ptr_type_node, mem, u); - u = fold (build (BIT_NOT_EXPR, ptr_type_node, u)); - t = build (BIT_AND_EXPR, ptr_type_node, t, u); - addr = get_initialized_tmp_var (t, pre_p, post_p); - - u = fold_convert (ptr_type_node, size); - t = build (PLUS_EXPR, ptr_type_node, addr, size); - t = build (MODIFY_EXPR, ptr_type_node, mem, t); - gimplify_and_add (t, pre_p); - } - else - { - isize = tree_low_cst (size, 0); - - if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && isize == 8)) - { - /* Floats and long longs are passed in the fp registers. */ - reg = fpr; - n_reg = size_int (isize / UNITS_PER_WORD); - n_reg = fold_convert (unsigned_type_node, n_reg); - lim_reg = size_int (NUM_PARM_FREGS - (isize / UNITS_PER_WORD)); - lim_reg = fold_convert (unsigned_type_node, lim_reg); - sav_ofs = size_int (FREG_OFFSET); - } - else - { - /* Everything else is passed in general registers. */ - reg = gpr; - if ((isize + UNITS_PER_WORD - 1) / UNITS_PER_WORD > 1) - abort (); - n_reg = fold_convert (unsigned_type_node, integer_one_node); - lim_reg = size_int (NUM_PARM_IREGS - 1); - lim_reg = fold_convert (unsigned_type_node, lim_reg); - sav_ofs = size_int (IREG_OFFSET); - } - - u = build (LE_EXPR, boolean_type_node, reg, lim_reg); - addr = build (COND_EXPR, ptr_type_node, u, NULL, NULL); - - /* The value was passed in a register, so read it from the register - save area initialized by __builtin_saveregs. */ - - sav_ofs = fold_convert (ptr_type_node, sav_ofs); - sav_ofs = fold (build (PLUS_EXPR, ptr_type_node, sav, sav_ofs)); - - u = fold_convert (unsigned_type_node, size_int (UNITS_PER_WORD)); - u = build (MULT_EXPR, unsigned_type_node, reg, u); - u = fold_convert (ptr_type_node, u); - u = build (PLUS_EXPR, ptr_type_node, sav_ofs, u); - COND_EXPR_THEN (addr) = u; - - /* The value was passed in memory, so read it from the overflow area. */ - - t = fold_convert (ptr_type_node, size); - u = build (POSTINCREMENT_EXPR, ptr_type_node, mem, t); - COND_EXPR_ELSE (addr) = u; - - /* Increment either the ireg_used or freg_used field. */ - - t = build (PLUS_EXPR, unsigned_type_node, reg, n_reg); - t = build (MODIFY_EXPR, unsigned_type_node, reg, t); - gimplify_and_add (t, post_p); - } - - addr = fold_convert (type_ptr, addr); - if (indirect) - addr = build_va_arg_indirect_ref (addr); - return build_va_arg_indirect_ref (addr); -} - -/* Compute a (partial) cost for rtx X. Return true if the complete - cost has been computed, and false if subexpressions should be - scanned. In either case, *TOTAL contains the cost result. */ - -static bool -i860_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total) -{ - switch (code) - { - case CONST_INT: - if (INTVAL (x) == 0) - *total = 0; - else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000) - *total = 1; - return true; - case CONST: - case LABEL_REF: - case SYMBOL_REF: - *total = 4; - return true; - case CONST_DOUBLE: - *total = 6; - return true; - default: - return false; - } -} - -static void -i860_internal_label (FILE *stream, const char *prefix, unsigned long labelno) -{ - fprintf (stream, ".%s%ld:\n", prefix, labelno); -} - -static void -i860_file_start (void) -{ - output_file_directive (asm_out_file, main_input_filename); - fprintf (asm_out_file, "\t.version\t\"01.01\"\n"); -} - -static void -i860_init_libfuncs (void) -{ - set_optab_libfunc (sdiv_optab, SImode, "*.div"); - set_optab_libfunc (udiv_optab, SImode, "*.udiv"); - set_optab_libfunc (smod_optab, SImode, "*.rem"); - set_optab_libfunc (umod_optab, SImode, "*.urem"); -} - -static rtx -i860_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, - int incoming ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (Pmode, I860_STRUCT_VALUE_REGNUM); -} - -/* Initialize the GCC target structure. */ -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS i860_rtx_costs - -#undef TARGET_ASM_INTERNAL_LABEL -#define TARGET_ASM_INTERNAL_LABEL i860_internal_label - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE i860_output_function_prologue - -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE i860_output_function_epilogue - -#undef TARGET_INIT_LIBFUNCS -#define TARGET_INIT_LIBFUNCS i860_init_libfuncs - -#undef TARGET_BUILD_BUILTIN_VA_LIST -#define TARGET_BUILD_BUILTIN_VA_LIST i860_build_builtin_va_list -#undef TARGET_GIMPLIFY_VA_ARG_EXPR -#define TARGET_GIMPLIFY_VA_ARG_EXPR i860_gimplify_va_arg_expr - -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX i860_struct_value_rtx - -#undef TARGET_EXPAND_BUILTIN_SAVEREGS -#define TARGET_EXPAND_BUILTIN_SAVEREGS i860_saveregs - -struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/i860/i860.h b/gcc/config/i860/i860.h deleted file mode 100644 index 07da9b9311a..00000000000 --- a/gcc/config/i860/i860.h +++ /dev/null @@ -1,1217 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Intel 860. - Copyright (C) 1989, 1991, 1993, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - Hacked substantially by Ron Guilmette (rfg@monkeys.com) to cater to - the whims of the System V Release 4 assembler. - -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. */ - - -/* Note that some other tm.h files include this one and then override - many of the definitions that relate to assembler syntax. */ - - -/* Names to predefine in the preprocessor for this target machine. */ -#define TARGET_CPU_CPP_BUILTINS() \ -do { \ - builtin_define ("i860"); \ - builtin_assert ("cpu=i860"); \ - builtin_assert ("machine=i860"); \ -} while (0) - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION fprintf (stderr, " (i860)"); - -/* target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - This is a moot question on the i860 due to the lack of bit-field insns. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. */ -/* That is not true on i860 in the mode we will use. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is the lowest - numbered. */ -/* For the i860 this goes with BYTES_BIG_ENDIAN. */ -/* NOTE: GCC probably cannot support a big-endian i860 - because GCC fundamentally assumes that the order of words - in memory as the same as the order in registers. - That's not true for the big-endian i860. - The big-endian i860 isn't important enough to - justify the trouble of changing this assumption. */ -#define WORDS_BIG_ENDIAN 0 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 128 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 64 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* Minimum size in bits of the largest boundary to which any - and all fundamental data types supported by the hardware - might need to be aligned. No data type wants to be aligned - rounder than this. The i860 supports 128-bit (long double) - floating point quantities, and the System V Release 4 i860 - ABI requires these to be aligned to 16-byte (128-bit) - boundaries. */ -#define BIGGEST_ALIGNMENT 128 - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* If bit field type is int, don't let it cross an int, - and give entire struct the alignment of an int. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. - - i860 has 32 fullword registers and 32 floating point registers. */ - -#define FIRST_PSEUDO_REGISTER 64 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - On the i860, this includes the always-0 registers - and fp, sp, arg pointer, and the return address. - Also r31, used for special purposes for constant addresses. */ -#define FIXED_REGISTERS \ - {1, 1, 1, 1, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 1, \ - 1, 1, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - On the i860, these are r0-r3, r16-r31, f0, f1, and f16-f31. */ -#define CALL_USED_REGISTERS \ - {1, 1, 1, 1, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1} - -/* Try to get a non-preserved register before trying to get one we will - have to preserve. Try to get an FP register only *after* trying to - get a general register, because it is relatively expensive to move - into or out of an FP register. */ - -#define REG_ALLOC_ORDER \ - {31, 30, 29, 28, 27, 26, 25, 24, \ - 23, 22, 21, 20, 19, 18, 17, 16, \ - 15, 14, 13, 12, 11, 10, 9, 8, \ - 7, 6, 5, 4, 3, 2, 1, 0, \ - 63, 62, 61, 60, 59, 58, 57, 56, \ - 55, 54, 53, 52, 51, 50, 49, 48, \ - 47, 46, 45, 44, 43, 42, 41, 40, \ - 39, 38, 37, 36, 35, 34, 33, 32} - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - - On the i860, all registers hold 32 bits worth. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -#define REGNO_MODE_ALIGNED(REGNO, MODE) \ - (((REGNO) % ((GET_MODE_UNIT_SIZE (MODE) + 3) / 4)) == 0) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - - On the i860, we allow anything to go into any registers, but we require - any sort of value going into the FP registers to be properly aligned - (based on its size) within the FP register set. -*/ -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - (((REGNO) < 32) \ - || (MODE) == VOIDmode || (MODE) == BLKmode \ - || REGNO_MODE_ALIGNED (REGNO, MODE)) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ -/* I think that is not always true; alignment restrictions for doubles - should not prevent tying them with singles. So try allowing that. - On the other hand, don't let fixed and floating be tied; - this restriction is not necessary, but may make better code. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((GET_MODE_CLASS (MODE1) == MODE_FLOAT \ - || GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \ - == (GET_MODE_CLASS (MODE2) == MODE_FLOAT \ - || GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* i860 pc isn't overloaded on a register that the compiler knows about. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 2 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 3 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 1 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 28 - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 29 - -/* Register in which address to store a structure value - is passed to a function. */ -#define I860_STRUCT_VALUE_REGNUM 16 - -/* Register to use when a source of a floating-point zero is needed. */ -#define F0_REGNUM 32 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* The i860 has two kinds of registers, hence four classes. */ - -enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ - {{0, 0}, {0xffffffff, 0}, \ - {0, 0xffffffff}, {0xffffffff, 0xffffffff}} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) >= 32 ? FP_REGS : GENERAL_REGS) - -/* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'f' ? FP_REGS : NO_REGS) - -/* The letters I, J, K, L and M in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - For the i860, `I' is used for the range of constants - an add/subtract insn can actually contain. - But not including -0x8000, since we need - to negate the constant sometimes. - `J' is used for the range which is just zero (since that is R0). - `K' is used for the range allowed in bte. - `L' is used for the range allowed in logical insns. */ - -#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x7fff) < 0xffff) - -#define LOGIC_INT(X) ((unsigned) INTVAL (X) < 0x10000) - -#define SMALL_INTVAL(X) ((unsigned) ((X) + 0x7fff) < 0xffff) - -#define LOGIC_INTVAL(X) ((unsigned) (X) < 0x10000) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? ((unsigned) (VALUE) + 0x7fff) < 0xffff \ - : (C) == 'J' ? (VALUE) == 0 \ - : (C) == 'K' ? (unsigned) (VALUE) < 0x20 \ - : (C) == 'L' ? (unsigned) (VALUE) < 0x10000 \ - : 0) - -/* Return nonzero if the given VALUE is acceptable for the - constraint letter C. For the i860, constraint letter 'G' - permits only a floating-point zero value. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' && CONST_DOUBLE_LOW ((VALUE)) == 0 \ - && CONST_DOUBLE_HIGH ((VALUE)) == 0) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - - If we are trying to put an integer constant into some register, prefer an - integer register to an FP register. If we are trying to put a - nonzero floating-point constant into some register, use an integer - register if the constant is SFmode and GENERAL_REGS is one of our options. - Otherwise, put the constant into memory. - - When reloading something smaller than a word, use a general reg - rather than an FP reg. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - ((CLASS) == ALL_REGS && GET_CODE (X) == CONST_INT ? GENERAL_REGS \ - : ((GET_MODE (X) == HImode || GET_MODE (X) == QImode) \ - && (CLASS) == ALL_REGS) \ - ? GENERAL_REGS \ - : (GET_CODE (X) == CONST_DOUBLE \ - && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - && ! CONST_DOUBLE_OK_FOR_LETTER_P (X, 'G')) \ - ? ((CLASS) == ALL_REGS && GET_MODE (X) == SFmode ? GENERAL_REGS \ - : (CLASS) == GENERAL_REGS && GET_MODE (X) == SFmode ? (CLASS) \ - : NO_REGS) \ - : (CLASS)) - -/* Return the register class of a scratch register needed to copy IN into - a register in CLASS in MODE. If it can be done directly, NO_REGS is - returned. */ - -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \ - ((CLASS) == FP_REGS && CONSTANT_P (IN) ? GENERAL_REGS : NO_REGS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -/* On the i860, this is the size of MODE in words. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this to non-zero if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD 1 - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On the i860, don't define this because there are no push insns. */ -/* #define PUSH_ROUNDING(BYTES) */ - -/* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -/* On the i860, the value register depends on the mode. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), \ - (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT \ - ? 40 : 16)) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx_REG (MODE, \ - (GET_MODE_CLASS ((MODE)) == MODE_FLOAT \ - ? 40 : 16)) - -/* 1 if N is a possible register number for a function value - as seen by the caller. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 40 || (N) == 16) - -/* 1 if N is a possible register number for function argument passing. - On the i860, these are r16-r27 and f8-f15. */ - -#define FUNCTION_ARG_REGNO_P(N) \ - (((N) < 28 && (N) > 15) || ((N) < 48 && (N) >= 40)) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On the i860, we must count separately the number of general registers used - and the number of float registers used. */ - -struct cumulative_args { int ints, floats; }; -#define CUMULATIVE_ARGS struct cumulative_args - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - On the i860, the general-reg offset normally starts at 0, - but starts at 4 bytes - when the function gets a structure-value-address as an - invisible first argument. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - ((CUM).ints = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE ((FNTYPE)), 0) \ - ? 4 : 0), \ - (CUM).floats = 0) - -/* Machine-specific subroutines of the following macros. */ -#define CEILING(X,Y) (((X) + (Y) - 1) / (Y)) -#define ROUNDUP(X,Y) (CEILING ((X), (Y)) * (Y)) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) - Floats, and doubleword ints, are returned in f regs; - other ints, in r regs. - Aggregates, even short ones, are passed in memory. */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((TYPE) != 0 && (TREE_CODE ((TYPE)) == RECORD_TYPE \ - || TREE_CODE ((TYPE)) == UNION_TYPE) \ - ? 0 \ - : GET_MODE_CLASS ((MODE)) == MODE_FLOAT || (MODE) == DImode \ - ? ((CUM).floats = (ROUNDUP ((CUM).floats, GET_MODE_SIZE ((MODE))) \ - + ROUNDUP (GET_MODE_SIZE (MODE), 4))) \ - : GET_MODE_CLASS ((MODE)) == MODE_INT \ - ? ((CUM).ints = (ROUNDUP ((CUM).ints, GET_MODE_SIZE ((MODE))) \ - + ROUNDUP (GET_MODE_SIZE (MODE), 4))) \ - : 0) - -/* Determine where to put an argument to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -/* On the i860, the first 12 words of integer arguments go in r16-r27, - and the first 8 words of floating arguments go in f8-f15. - DImode values are treated as floats. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - ((TYPE) != 0 && (TREE_CODE ((TYPE)) == RECORD_TYPE \ - || TREE_CODE ((TYPE)) == UNION_TYPE) \ - ? 0 \ - : GET_MODE_CLASS ((MODE)) == MODE_FLOAT || (MODE) == DImode \ - ? (ROUNDUP ((CUM).floats, GET_MODE_SIZE ((MODE))) < 32 \ - ? gen_rtx_REG ((MODE), \ - 40 + (ROUNDUP ((CUM).floats, \ - GET_MODE_SIZE ((MODE))) \ - / 4)) \ - : 0) \ - : GET_MODE_CLASS ((MODE)) == MODE_INT \ - ? (ROUNDUP ((CUM).ints, GET_MODE_SIZE ((MODE))) < 48 \ - ? gen_rtx_REG ((MODE), \ - 16 + (ROUNDUP ((CUM).ints, \ - GET_MODE_SIZE ((MODE))) \ - / 4)) \ - : 0) \ - : 0) - -/* If defined, a C expression that gives the alignment boundary, in - bits, of an argument with the specified mode and type. If it is - not defined, `PARM_BOUNDARY' is used for all arguments. */ - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) != 0) \ - ? ((TYPE_ALIGN(TYPE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : TYPE_ALIGN(TYPE)) \ - : ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : GET_MODE_ALIGNMENT(MODE))) - -/* Output a no-op just before the beginning of the function, - to ensure that there does not appear to be a delayed branch there. - Such a thing would confuse interrupt recovery. */ -#define ASM_OUTPUT_FUNCTION_PREFIX(FILE,NAME) \ - fprintf (FILE, "\tnop\n") - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - abort (); - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 1 - -/* Implement `va_start' for varargs and stdarg. */ -#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ - i860_va_start (valist, nextarg) - -/* Store in the variable DEPTH the initial difference between the - frame pointer reg contents and the stack pointer reg contents, - as of the start of the function body. This depends on the layout - of the fixed parts of the stack frame and on how registers are saved. - - On the i860, FRAME_POINTER_REQUIRED is always 1, so the definition of this - macro doesn't matter. But it must be defined. */ - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ - do { (DEPTH) = 0; } while (0) - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -/* On the i860, the trampoline contains five instructions: - orh #TOP_OF_FUNCTION,r0,r31 - or #BOTTOM_OF_FUNCTION,r31,r31 - orh #TOP_OF_STATIC,r0,r29 - bri r31 - or #BOTTOM_OF_STATIC,r29,r29 */ -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0xec1f0000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0xe7ff0000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0xec1d0000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x4000f800)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0xe7bd0000)); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. - - Store hi function at +0, low function at +4, - hi static at +8, low static at +16 */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - rtx cxt = force_reg (Pmode, CXT); \ - rtx fn = force_reg (Pmode, FNADDR); \ - rtx hi_cxt = expand_shift (RSHIFT_EXPR, SImode, cxt, \ - size_int (16), 0, 0); \ - rtx hi_fn = expand_shift (RSHIFT_EXPR, SImode, fn, \ - size_int (16), 0, 0); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 16)), \ - gen_lowpart (HImode, cxt)); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 4)), \ - gen_lowpart (HImode, fn)); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 8)), \ - gen_lowpart (HImode, hi_cxt)); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 0)), \ - gen_lowpart (HImode, hi_fn)); \ -} - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(REGNO) \ -((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) -#define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) -#define REGNO_OK_FOR_FP_P(REGNO) \ -(((REGNO) ^ 0x20) < 32 || (unsigned) (reg_renumber[REGNO] ^ 0x20) < 32) - -/* Now macros that check whether X is a register and also, - strictly, whether it is in a specified class. - - These macros are specific to the i860, and may be used only - in code for printing assembler insns and in conditions for - define_optimization. */ - -/* 1 if X is an fp register. */ - -#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* Recognize any constant value that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. - - On the Sparc, this is anything but a CONST_DOUBLE. - Let's try permitting CONST_DOUBLEs and see what happens. */ - -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) (((unsigned) REGNO (X)) - 32 >= 14) -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) (((unsigned) REGNO (X)) - 32 >= 14) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On the i860, the actual addresses must be REG+REG or REG+SMALLINT. - But we can treat a SYMBOL_REF as legitimate if it is part of this - function's constant-pool, because such addresses can actually - be output as REG+SMALLINT. - - The displacement in an address must be a multiple of the alignment. - - Try making SYMBOL_REF (and other things which are CONSTANT_ADDRESS_P) - a legitimate address, regardless. Because the only insns which can use - memory are load or store insns, the added hair in the machine description - is not that bad. It should also speed up the compiler by halving the number - of insns it must manage for each (MEM (SYMBOL_REF ...)) involved. */ - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (GET_CODE (X) == REG) \ - { if (REG_OK_FOR_BASE_P (X)) goto ADDR; } \ - else if (GET_CODE (X) == PLUS) \ - { \ - if (GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ - { \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) >= -0x8000 \ - && INTVAL (XEXP (X, 1)) < 0x8000 \ - && (INTVAL (XEXP (X, 1)) & (GET_MODE_SIZE (MODE) - 1)) == 0) \ - goto ADDR; \ - } \ - else if (GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ - { \ - if (GET_CODE (XEXP (X, 0)) == CONST_INT \ - && INTVAL (XEXP (X, 0)) >= -0x8000 \ - && INTVAL (XEXP (X, 0)) < 0x8000 \ - && (INTVAL (XEXP (X, 0)) & (GET_MODE_SIZE (MODE) - 1)) == 0) \ - goto ADDR; \ - } \ - } \ - else if (CONSTANT_ADDRESS_P (X)) \ - goto ADDR; \ -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ - -/* On the i860, change COMPLICATED + CONSTANT to REG+CONSTANT. - Also change a symbolic constant to a REG, - though that may not be necessary. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ - force_operand (XEXP (X, 0), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ - force_operand (XEXP (X, 0), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) != REG \ - && GET_CODE (XEXP (X, 0)) != CONST_INT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ - copy_to_mode_reg (SImode, XEXP (X, 0))); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) != REG \ - && GET_CODE (XEXP (X, 1)) != CONST_INT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ - copy_to_mode_reg (SImode, XEXP (X, 1))); \ - if (GET_CODE (x) == SYMBOL_REF) \ - (X) = copy_to_reg (X); \ - if (GET_CODE (x) == CONST) \ - (X) = copy_to_reg (X); \ - if (memory_address_p (MODE, X)) \ - goto WIN; } - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the i860 this is never true. - There are some addresses that are invalid in wide modes - but valid for narrower modes, but they shouldn't affect - the places that use this macro. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 16 - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Value is 1 if it generates better code to perform an unsigned comparison - on the given literal integer value in the given mode when we are only - looking for an equal/non-equal result. */ -/* For the i860, if the immediate value has its high-order 27 bits zero, - then we want to engineer an unsigned comparison for EQ/NE because - such values can fit in the 5-bit immediate field of a bte or btne - instruction (which gets zero extended before comparing). For all - other immediate values on the i860, we will use signed compares - because that avoids the need for doing explicit xor's to zero_extend - the non-constant operand in cases where it was (mem:QI ...) or a - (mem:HI ...) which always gets automatically sign-extended by the - hardware upon loading. */ - -#define LITERAL_COMPARE_BETTER_UNSIGNED(intval, mode) \ - (((unsigned) (intval) & 0x1f) == (unsigned) (intval)) - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE SImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. */ -#define NO_FUNCTION_CSE - -/* Specify the cost of a branch insn; roughly the number of extra insns that - should be added to avoid a branch. - - Set this to 3 on the i860 since branches may often take three cycles. */ - -#define BRANCH_COST 3 - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). */ - -/* This holds the value sourcing h%r31. We keep this info - around so that mem/mem ops, such as increment and decrement, - etc, can be performed reasonably. */ -#define CC_STATUS_MDEP rtx - -#define CC_STATUS_MDEP_INIT (cc_status.mdep = 0) - -#define CC_NEGATED 01000 - -/* We use this macro in those places in the i860.md file where we would - normally just do a CC_STATUS_INIT (for other machines). This macro - differs from CC_STATUS_INIT in that it doesn't mess with the special - bits or fields which describe what is currently in the special r31 - scratch register, but it does clear out everything that actually - relates to the condition code bit of the i860. */ - -#define CC_STATUS_PARTIAL_INIT \ - (cc_status.flags &= (CC_KNOW_HI_R31 | CC_HI_R31_ADJ), \ - cc_status.value1 = 0, \ - cc_status.value2 = 0) - -/* Nonzero if we know the value of h%r31. */ -#define CC_KNOW_HI_R31 0100000 - -/* Nonzero if h%r31 is actually ha%something, rather than h%something. */ -#define CC_HI_R31_ADJ 0200000 - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -/* On the i860, only compare insns set a useful condition code. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ -{ cc_status.flags &= (CC_KNOW_HI_R31 | CC_HI_R31_ADJ); \ - cc_status.value1 = 0; cc_status.value2 = 0; } - -/* Control the assembler format that we output. */ - -/* Assembler pseudos to introduce constants of various size. */ - -#define ASM_DOUBLE "\t.double" - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP "\t.data" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7", "r8", "r9", \ - "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", \ - "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \ - "r30", "r31", \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", \ - "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", \ - "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", \ - "f30", "f31" } - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* The prefix to add to user-visible assembler symbols. - - This definition is overridden in i860/sysv4.h because under System V - Release 4, user-level symbols are *not* prefixed with underscores in - the generated assembly code. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to output an internal numbered label which - labels a jump table. */ - -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \ -do { ASM_OUTPUT_ALIGN ((FILE), 2); \ - (*targetm.asm_out.internal_label) ((FILE), PREFIX, NUM); \ - } while (0) - -/* Output at the end of a jump table. */ - -#define ASM_OUTPUT_CASE_END(FILE,NUM,INSN) \ - fprintf (FILE, ".text\n") - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*.%s%d", PREFIX, NUM) - -/* This is how to output code to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\taddu -16,%ssp,%ssp\n\t%sst.l %s%s,0(%ssp)\n", \ - i860_reg_prefix, i860_reg_prefix, \ - ((REGNO) < 32 ? "" : "f"), \ - i860_reg_prefix, reg_names[REGNO], \ - i860_reg_prefix) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\t%sld.l 0(%ssp),%s%s\n\taddu 16,%ssp,%ssp\n", \ - ((REGNO) < 32 ? "" : "f"), \ - i860_reg_prefix, \ - i860_reg_prefix, reg_names[REGNO], \ - i860_reg_prefix, i860_reg_prefix) - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long .L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. - (The i860 does not use such vectors, - but we must define this macro anyway.) */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align %d\n", 1 << (LOG)) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.blkb %u\n", (SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (ROUNDED))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".lcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (ROUNDED))) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. - - In the following comments, the term "constant address" is used frequently. - For an exact definition of what constitutes a "constant address" see the - output_addr_const routine in final.c - - On the i860, the following target-specific special codes are recognized: - - `r' The operand can be anything, but if it is an immediate zero - value (either integer or floating point) then it will be - represented as `r0' or as `f0' (respectively). - - `m' The operand is a memory ref (to a constant address) but print - its address as a constant. - - `L' The operand is a numeric constant, a constant address, or - a memory ref to a constant address. Print the correct - notation to yield the low part of the given value or - address or the low part of the address of the referred - to memory object. - - `H' The operand is a numeric constant, a constant address, or - a memory ref to a constant address. Print the correct - notation to yield the high part of the given value or - address or the high part of the address of the referred - to memory object. - - `h' The operand is a numeric constant, a constant address, or - a memory ref to a constant address. Either print the - correct notation to yield the plain high part of the - given value or address (or the plain high part of the - address of the memory object) or else print the correct - notation to yield the "adjusted" high part of the given - address (or of the address of the referred to memory object). - - The choice of what to print depends upon whether the address - in question is relocatable or not. If it is relocatable, - print the notation to get the adjusted high part. Otherwise - just print the notation to get the plain high part. Note - that "adjusted" high parts are generally used *only* when - the next following instruction uses the low part of the - address as an offset, as in `offset(reg)'. - - `R' The operand is a floating-pointer register. Print the - name of the next following (32-bit) floating-point register. - (This is used when moving a value into just the most - significant part of a floating-point register pair.) - - `?' (takes no operand) Substitute the value of i860_reg_prefix - at this point. The value of i860_reg_prefix is typically - a null string for most i860 targets, but for System V - Release 4 the i860 assembler syntax requires that all - names of registers be prefixed with a percent-sign, so - for SVR4, the value of i860_reg_prefix is initialized to - "%" in i860.c. -*/ - -extern const char *i860_reg_prefix; - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '?') - -/* The following macro definition is overridden in i860v4.h - because the svr4 i860 assembler required a different syntax - for getting parts of constant/relocatable values. */ - -#define PRINT_OPERAND_PART(FILE, X, PART_CODE) \ - do { fprintf (FILE, "%s%%", PART_CODE); \ - output_address (X); \ - } while (0) - -#define OPERAND_LOW_PART "l" -#define OPERAND_HIGH_PART "h" -/* NOTE: All documentation available for the i860 sez that you must - use "ha" to get the relocated high part of a relocatable, but - reality sez different. */ -#define OPERAND_HIGH_ADJ_PART "ha" - -#define PRINT_OPERAND(FILE, X, CODE) \ -{ if ((CODE) == '?') \ - fprintf (FILE, "%s", i860_reg_prefix); \ - else if (CODE == 'R') \ - fprintf (FILE, "%s%s", i860_reg_prefix, reg_names[REGNO (X) + 1]); \ - else if (GET_CODE (X) == REG) \ - fprintf (FILE, "%s%s", i860_reg_prefix, reg_names[REGNO (X)]); \ - else if ((CODE) == 'm') \ - output_address (XEXP (X, 0)); \ - else if ((CODE) == 'L') \ - { \ - if (GET_CODE (X) == MEM) \ - PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_LOW_PART); \ - else \ - PRINT_OPERAND_PART (FILE, X, OPERAND_LOW_PART); \ - } \ - else if ((CODE) == 'H') \ - { \ - if (GET_CODE (X) == MEM) \ - PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_HIGH_PART); \ - else \ - PRINT_OPERAND_PART (FILE, X, OPERAND_HIGH_PART); \ - } \ - else if ((CODE) == 'h') \ - { \ - if (GET_CODE (X) == MEM) \ - PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_HIGH_ADJ_PART); \ - else \ - PRINT_OPERAND_PART (FILE, X, OPERAND_HIGH_ADJ_PART); \ - } \ - else if (GET_CODE (X) == MEM) \ - output_address (XEXP (X, 0)); \ - else if ((CODE) == 'r' && (X) == const0_rtx) \ - fprintf (FILE, "%sr0", i860_reg_prefix); \ - else if ((CODE) == 'r' && (X) == CONST0_RTX (GET_MODE (X))) \ - fprintf (FILE, "%sf0", i860_reg_prefix); \ - else if (GET_CODE (X) == CONST_DOUBLE) \ - fprintf (FILE, "0x%lx", sfmode_constant_to_ulong (X)); \ - else \ - output_addr_const (FILE, X); } - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ register rtx addr = ADDR; \ - if (GET_CODE (addr) == REG) \ - { \ - fprintf (FILE, "0(%s%s)", \ - i860_reg_prefix, reg_names[REGNO (addr)]); \ - } \ - else if (GET_CODE (addr) == CONST_DOUBLE \ - && GET_MODE (addr) == SFmode) \ - fprintf (FILE, "0x%lx", sfmode_constant_to_ulong (addr)); \ - else if (GET_CODE (addr) == PLUS) \ - { \ - if ((GET_CODE (XEXP (addr, 0)) == CONST_INT) \ - && (GET_CODE (XEXP (addr, 1)) == REG)) \ - fprintf (FILE, "%d(%s%s)", INTVAL (XEXP (addr, 0)), \ - i860_reg_prefix, reg_names[REGNO (XEXP (addr, 1))]);\ - else if ((GET_CODE (XEXP (addr, 1)) == CONST_INT) \ - && (GET_CODE (XEXP (addr, 0)) == REG)) \ - fprintf (FILE, "%d(%s%s)", INTVAL (XEXP (addr, 1)), \ - i860_reg_prefix, reg_names[REGNO (XEXP (addr, 0))]);\ - else if ((GET_CODE (XEXP (addr, 0)) == REG) \ - && (GET_CODE (XEXP (addr, 1)) == REG)) \ - fprintf (FILE, "%s%s(%s%s)", \ - i860_reg_prefix, reg_names[REGNO (XEXP (addr, 0))], \ - i860_reg_prefix, reg_names[REGNO (XEXP (addr, 1))]);\ - else \ - output_addr_const (FILE, addr); \ - } \ - else \ - { \ - output_addr_const (FILE, addr); \ - } \ -} - -/* Optionally define this if you have added predicates to - `MACHINE.c'. This macro is called within an initializer of an - array of structures. The first field in the structure is the - name of a predicate and the second field is an array of rtl - codes. For each predicate, list all rtl codes that can be in - expressions matched by the predicate. The list should have a - trailing comma. Here is an example of two entries in the list - for a typical RISC machine: - - #define PREDICATE_CODES \ - {"gen_reg_rtx_operand", {SUBREG, REG}}, \ - {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}}, - - Defining this macro does not affect the generated code (however, - incorrect definitions that omit an rtl code that may be matched - by the predicate can cause the compiler to malfunction). - Instead, it allows the table built by `genrecog' to be more - compact and efficient, thus speeding up the compiler. The most - important predicates to include in the list specified by this - macro are thoses used in the most insn patterns. */ - -#define PREDICATE_CODES \ - {"reg_or_0_operand", {REG, SUBREG, CONST_INT}}, \ - {"arith_operand", {REG, SUBREG, CONST_INT}}, \ - {"logic_operand", {REG, SUBREG, CONST_INT}}, \ - {"shift_operand", {REG, SUBREG, CONST_INT}}, \ - {"compare_operand", {REG, SUBREG, CONST_INT}}, \ - {"bte_operand", {REG, SUBREG, CONST_INT}}, \ - {"indexed_operand", {MEM}}, \ - {"load_operand", {MEM}}, \ - {"small_int", {CONST_INT}}, \ - {"logic_int", {CONST_INT}}, \ - {"call_insn_operand", {MEM}}, - -/* Define the information needed to generate branch 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 *i860_compare_op0, *i860_compare_op1; diff --git a/gcc/config/i860/i860.md b/gcc/config/i860/i860.md deleted file mode 100644 index 385d369d9bc..00000000000 --- a/gcc/config/i860/i860.md +++ /dev/null @@ -1,2231 +0,0 @@ -;; GCC Machine description for the Intel i860 microprocessor -;; Copyright (C) 1989, 1990, 1997, 1998, 1999, 2000, 2003, 2004 -;; 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. - - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - -;; -;; UNSPEC_VOLATILE usage -;; - -(define_constants - [; Blockage - (UNSPECV_BLOCKAGE 0) - ]) - -;;- Operand classes for the register allocator: - -/* Bit-test instructions. */ - -(define_insn "" - [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "logic_operand" "rL")) - (const_int 0)))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and %1,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "logic_operand" "rL")) - (const_int 0)))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"and %1,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i")) - (const_int 0)))] - "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"andh %H1,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i")) - (const_int 0)))] - "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"andh %H1,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) (eq (ashiftrt:SI - (sign_extend:SI - (ashift:QI (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "logic_int" "n"))) - (match_operand:SI 2 "logic_int" "n")) - (const_int 0)))] - "" - "* -{ - int width = 8 - INTVAL (operands[2]); - int pos = 8 - width - INTVAL (operands[1]); - - CC_STATUS_PARTIAL_INIT; - operands[2] = GEN_INT (~((-1) << width) << pos); - return \"and %2,%0,%?r0\"; -}") - -;; ------------------------------------------------------------------------- -;; SImode signed integer comparisons -;; ------------------------------------------------------------------------- - -(define_insn "cmpeqsi" - [(set (cc0) (eq (match_operand:SI 0 "logic_operand" "r,rL") - (match_operand:SI 1 "logic_operand" "L,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[0])) - return \"xor %1,%0,%?r0\"; - else - return \"xor %0,%1,%?r0\"; -}") - -(define_insn "cmpnesi" - [(set (cc0) (ne (match_operand:SI 0 "logic_operand" "r,rL") - (match_operand:SI 1 "logic_operand" "L,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - if (REG_P (operands[0])) - return \"xor %1,%0,%?r0\"; - else - return \"xor %0,%1,%?r0\"; -}") - -(define_insn "cmpltsi" - [(set (cc0) (lt (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[1])) - return \"subs %0,%1,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[1] = GEN_INT (- INTVAL (operands[1])); - return \"adds %1,%0,%?r0\"; - } -}") - -(define_insn "cmpgtsi" - [(set (cc0) (gt (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[0])) - return \"subs %1,%0,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[0] = GEN_INT (- INTVAL (operands[0])); - return \"adds %0,%1,%?r0\"; - } -}") - -(define_insn "cmplesi" - [(set (cc0) (le (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - if (REG_P (operands[0])) - return \"subs %1,%0,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[0] = GEN_INT (- INTVAL (operands[0])); - return \"adds %0,%1,%?r0\"; - } -}") - -(define_insn "cmpgesi" - [(set (cc0) (ge (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - if (REG_P (operands[1])) - return \"subs %0,%1,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[1] = GEN_INT (- INTVAL (operands[1])); - return \"adds %1,%0,%?r0\"; - } -}") - -;; ------------------------------------------------------------------------- -;; SImode unsigned integer comparisons -;; ------------------------------------------------------------------------- - -;; WARNING! There is a small i860 hardware limitation (bug?) which we -;; may run up against (if we are not careful) when we are trying to do -;; unsigned comparisons like (x >= 0), (x < 0), (0 <= x), and (0 > x). -;; Specifically, we must avoid using an `addu' instruction to perform -;; such comparisons because the result (in the CC bit register) will -;; come out wrong. (This fact is documented in a footnote on page 7-10 -;; of the 1991 version of the i860 Microprocessor Family Programmer's -;; Reference Manual). Note that unsigned comparisons of this sort are -;; always redundant anyway, because an unsigned quantity can never be -;; less than zero. When we see cases like this, we generate an -;; `or K,%r0,%r0' instruction instead (where K is a constant 0 or -1) -;; so as to get the CC bit register set properly for any subsequent -;; conditional jump instruction. - -(define_insn "cmpgeusi" - [(set (cc0) (geu (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[1])) - return \"subu %0,%1,%?r0\"; - else - { - if (INTVAL (operands[1]) == 0) - return \"or 0,%?r0,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[1] = GEN_INT (- INTVAL (operands[1])); - return \"addu %1,%0,%?r0\"; - } - } -}") - -(define_insn "cmpleusi" - [(set (cc0) (leu (match_operand:SI 0 "arith_operand" "r,rI") - (match_operand:SI 1 "arith_operand" "I,r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[0])) - return \"subu %1,%0,%?r0\"; - else - { - if (INTVAL (operands[0]) == 0) - return \"or 0,%?r0,%?r0\"; - else - { - cc_status.flags |= CC_REVERSED; - operands[0] = GEN_INT (- INTVAL (operands[0])); - return \"addu %0,%1,%?r0\"; - } - } -}") - -;; ------------------------------------------------------------------------- -;; SFmode floating-point comparisons -;; ------------------------------------------------------------------------- - -(define_insn "cmpeqsf" - [(set (cc0) (eq (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfeq.ss %r0,%r1,%?f0\"; -}") - -(define_insn "cmpnesf" - [(set (cc0) (ne (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfeq.ss %r1,%r0,%?f0\"; -}") - -;; NOTE: The i860 Programmer's Reference Manual says that when we are -;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these -;; in order to be IEEE compliant (in case a trap occurs during these -;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we -;; must use pfle to be IEEE compliant. - -(define_insn "cmpltsf" - [(set (cc0) (lt (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfgt.ss %r1,%r0,%?f0\"; -}") - -(define_insn "cmpgtsf" - [(set (cc0) (gt (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfgt.ss %r0,%r1,%?f0\"; -}") - -;; NOTE: The pfle opcode *clears* the CC flag if the first operand is -;; less than or equal to the second. Thus, we have to set CC_NEGATED -;; for the following two patterns. - -(define_insn "cmplesf" - [(set (cc0) (le (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfle.ss %r0,%r1,%?f0\"; -}") - -(define_insn "cmpgesf" - [(set (cc0) (ge (match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfle.ss %r1,%r0,%?f0\"; -}") - -;; ------------------------------------------------------------------------- -;; DFmode floating-point comparisons -;; ------------------------------------------------------------------------- - -(define_insn "cmpeqdf" - [(set (cc0) (eq (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfeq.dd %r0,%r1,%?f0\"; -}") - -(define_insn "cmpnedf" - [(set (cc0) (ne (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfeq.dd %r1,%r0,%?f0\"; -}") - -;; NOTE: The i860 Programmer's Reference Manual says that when we are -;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these -;; in order to be IEEE compliant (in case a trap occurs during these -;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we -;; must use pfle to be IEEE compliant. - -(define_insn "cmpltdf" - [(set (cc0) (lt (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfgt.dd %r1,%r0,%?f0\"; -}") - -(define_insn "cmpgtdf" - [(set (cc0) (gt (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"pfgt.dd %r0,%r1,%?f0\"; -}") - -;; NOTE: The pfle opcode *clears* the CC flag if the first operand is -;; less than or equal to the second. Thus, we have to set CC_NEGATED -;; for the following two patterns. - -(define_insn "cmpledf" - [(set (cc0) (le (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfle.dd %r0,%r1,%?f0\"; -}") - -(define_insn "cmpgedf" - [(set (cc0) (ge (match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - cc_status.flags |= CC_NEGATED; - return \"pfle.dd %r1,%r0,%?f0\"; -}") - -;; ------------------------------------------------------------------------ -;; Integer EQ/NE comparisons against constant values which will fit in the -;; 16-bit immediate field of an instruction. These are made by combining. -;; ------------------------------------------------------------------------ - -(define_insn "" - [(set (cc0) (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m")) - (match_operand:SI 1 "small_int" "I")))] - "INTVAL (operands[1]) >= 0" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"ld.s %0,%?r31\;xor %1,%?r31,%?r0\"; -}") - -(define_insn "" - [(set (cc0) (eq (match_operand:SI 0 "small_int" "I") - (zero_extend:SI (match_operand:HI 1 "load_operand" "m"))))] - "INTVAL (operands[0]) >= 0" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"ld.s %1,%?r31\;xor %0,%?r31,%?r0\"; -}") - -;; ------------------------------------------------------------------------ -;; Define the real conditional branch instructions. -;; ------------------------------------------------------------------------ - -(define_insn "cbranch" - [(set (pc) (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if ((cc_prev_status.flags & CC_NEGATED) == 0) - return \"bnc %l0\"; - else - return \"bc %l0\"; -}") - -(define_insn "flipped_cbranch" - [(set (pc) (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if ((cc_prev_status.flags & CC_NEGATED) == 0) - return \"bnc %l0\"; - else - return \"bc %l0\"; -}") - -(define_insn "inverse_cbranch" - [(set (pc) (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if ((cc_prev_status.flags & CC_NEGATED) == 0) - return \"bc %l0\"; - else - return \"bnc %l0\"; -}") - - -(define_insn "flipped_inverse_cbranch" - [(set (pc) (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if ((cc_prev_status.flags & CC_NEGATED) == 0) - return \"bc %l0\"; - else - return \"bnc %l0\"; -}") - -;; Simple BTE/BTNE compare-and-branch insns made by combining. -;; Note that it is wrong to add similar patterns for QI or HImode -;; because bte/btne always compare the whole register. - -(define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bte %1,%0,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "btne %1,%0,%2") - -(define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "btne %1,%0,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "bte %1,%0,%2") - -;; Load byte/halfword, zero-extend, & compare-and-branch insns. -;; These are made by combining. - -(define_insn "" - [(set (pc) - (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (label_ref (match_operand 2 "" "")) - (pc))) - (match_scratch:SI 3 "=r")] - "" - "ld.b %0,%3;bte %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (label_ref (match_operand 2 "" "")) - (pc))) - (match_scratch:SI 3 "=r")] - "" - "ld.b %0,%3;btne %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (pc) - (label_ref (match_operand 2 "" "")))) - (match_scratch:SI 3 "=r")] - "" - "ld.b %0,%3;btne %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (pc) - (label_ref (match_operand 2 "" "")))) - (match_scratch:SI 3 "=r")] - "" - "ld.b %0,%3;bte %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (label_ref (match_operand 2 "" "")) - (pc))) - (match_scratch:SI 3 "=r")] - "" - "ld.s %0,%3;bte %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (label_ref (match_operand 2 "" "")) - (pc))) - (match_scratch:SI 3 "=r")] - "" - "ld.s %0,%3;btne %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (pc) - (label_ref (match_operand 2 "" "")))) - (match_scratch:SI 3 "=r")] - "" - "ld.s %0,%3;btne %1,%3,%2") - -(define_insn "" - [(set (pc) - (if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) - (match_operand:SI 1 "bte_operand" "K")) - (pc) - (label_ref (match_operand 2 "" "")))) - (match_scratch:SI 3 "=r")] - "" - "ld.s %0,%3;bte %1,%3,%2") - - -;; Generation of conditionals. - -;; We save the compare operands in the cmpxx patterns and use then when -;; we generate the branch. - -(define_expand "cmpsi" - [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "compare_operand" "")))] - "" - " -{ i860_compare_op0 = operands[0]; - i860_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpsf" - [(set (cc0) (compare (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] - "" - " -{ i860_compare_op0 = operands[0]; - i860_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (cc0) (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] - "" - " -{ i860_compare_op0 = operands[0]; - i860_compare_op1 = operands[1]; - DONE; -}") - -;; These are the standard-named conditional branch patterns. -;; Detailed comments are found in the first one only. - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - /* Emit a single-condition compare insn according to - the type of operands and the condition to be tested. */ - - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - emit_insn (gen_cmpeqsi (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmpeqsf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpeqdf (i860_compare_op0, i860_compare_op1)); - else - abort (); - - /* Emit branch-if-true. */ - - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - DONE; -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - emit_insn (gen_cmpeqsi (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmpeqsf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpeqdf (i860_compare_op0, i860_compare_op1)); - else - abort (); - - emit_jump_insn (gen_flipped_cbranch (operands[0])); - - DONE; -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - emit_insn (gen_cmpgtsi (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmpgtsf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpgtdf (i860_compare_op0, i860_compare_op1)); - else - abort (); - - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - DONE; -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - emit_insn (gen_cmpltsi (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmpltsf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpltdf (i860_compare_op0, i860_compare_op1)); - else - abort (); - - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - DONE; -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - { - emit_insn (gen_cmpgtsi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_cbranch (operands[0])); - } - else - { - if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmplesf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpledf (i860_compare_op0, i860_compare_op1)); - else - abort (); - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - } - DONE; -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT) - { - emit_insn (gen_cmpltsi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_cbranch (operands[0])); - } - else - { - if (GET_MODE (i860_compare_op0) == SFmode) - emit_insn (gen_cmpgesf (i860_compare_op0, i860_compare_op1)); - else if (GET_MODE (i860_compare_op0) == DFmode) - emit_insn (gen_cmpgedf (i860_compare_op0, i860_compare_op1)); - else - abort (); - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - } - DONE; -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT) - abort (); - - emit_insn (gen_cmpleusi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_cbranch (operands[0])); - DONE; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT) - abort (); - - emit_insn (gen_cmpgeusi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_cbranch (operands[0])); - DONE; -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT) - abort (); - - emit_insn (gen_cmpgeusi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - DONE; -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT) - abort (); - - emit_insn (gen_cmpleusi (i860_compare_op0, i860_compare_op1)); - emit_jump_insn (gen_flipped_inverse_cbranch (operands[0])); - DONE; -}") - -;; Move instructions - -;; Note that source operands for `mov' pseudo-instructions are no longer -;; allowed (by the SVR4 assembler) to be "big" things, i.e. constants that -;; won't fit in 16-bits. (This includes any sort of a relocatable address -;; also.) Thus, we must use an explicit orh/or pair of instructions if -;; the source operand is something "big". - -(define_insn "movsi" - [(set (match_operand:SI 0 "general_operand" "=r,m,f") - (match_operand:SI 1 "general_operand" "rmif,rfJ,rmfJ"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - if (FP_REG_P (operands[1])) - return \"fst.l %1,%0\"; - return \"st.l %r1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - if (FP_REG_P (operands[0])) - return \"fld.l %1,%0\"; - return \"ld.l %1,%0\"; - } - if (FP_REG_P (operands[1]) && FP_REG_P (operands[0])) - return \"fmov.ss %1,%0\"; - if (FP_REG_P (operands[1])) - return \"fxfr %1,%0\"; - if (FP_REG_P (operands[0]) && operands[1] == const0_rtx) - return \"fmov.ss %?f0,%0\"; - if (FP_REG_P (operands[0])) - return \"ixfr %1,%0\"; - - if (GET_CODE (operands[1]) == REG) - return \"shl %?r0,%1,%0\"; - - CC_STATUS_PARTIAL_INIT; - - if (GET_CODE (operands[1]) == CONST_INT) - { - if((INTVAL (operands[1]) & 0xffff0000) == 0) - return \"or %L1,%?r0,%0\"; - if((INTVAL (operands[1]) & 0x0000ffff) == 0) - return \"orh %H1,%?r0,%0\"; - } - return \"orh %H1,%?r0,%0\;or %L1,%0,%0\"; -}") - -(define_insn "movhi" - [(set (match_operand:HI 0 "general_operand" "=r,m,!*f,!r") - (match_operand:HI 1 "general_operand" "rmi,rJ,rJ*f,*f"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - return \"st.s %r1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - return \"ld.s %1,%0\"; - } - if (FP_REG_P (operands[1]) && FP_REG_P (operands[0])) - return \"fmov.ss %1,%0\"; - if (FP_REG_P (operands[1])) - return \"fxfr %1,%0\"; - if (FP_REG_P (operands[0]) && operands[1] == const0_rtx) - return \"fmov.ss %?f0,%0\"; - if (FP_REG_P (operands[0])) - return \"ixfr %1,%0\"; - - if (GET_CODE (operands[1]) == REG) - return \"shl %?r0,%1,%0\"; - - CC_STATUS_PARTIAL_INIT; - - return \"or %L1,%?r0,%0\"; -}") - -(define_insn "movqi" - [(set (match_operand:QI 0 "general_operand" "=r,m,!*f,!r") - (match_operand:QI 1 "general_operand" "rmi,rJ,rJ*f,*f"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - return \"st.b %r1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - return \"ld.b %1,%0\"; - } - if (FP_REG_P (operands[1]) && FP_REG_P (operands[0])) - return \"fmov.ss %1,%0\"; - if (FP_REG_P (operands[1])) - return \"fxfr %1,%0\"; - if (FP_REG_P (operands[0]) && operands[1] == const0_rtx) - return \"fmov.ss %?f0,%0\"; - if (FP_REG_P (operands[0])) - return \"ixfr %1,%0\"; - - if (GET_CODE (operands[1]) == REG) - return \"shl %?r0,%1,%0\"; - - CC_STATUS_PARTIAL_INIT; - - return \"or %L1,%?r0,%0\"; -}") - -;; The definition of this insn does not really explain what it does, -;; but it should suffice -;; that anything generated as this insn will be recognized as one -;; and that it won't successfully combine with anything. -(define_expand "movmemsi" - [(parallel [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:SI 2 "nonmemory_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6)) - (clobber (match_dup 7)) - (clobber (match_dup 8))])] - "" - " -{ - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_reg_rtx (SImode); - operands[7] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); - operands[8] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); - - operands[0] = replace_equiv_address (operands[0], operands[7]); - operands[1] = replace_equiv_address (operands[1], operands[8]); -}") - -(define_insn "" - [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) - (mem:BLK (match_operand:SI 1 "register_operand" "r"))) - (use (match_operand:SI 2 "general_operand" "rn")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_operand:SI 4 "register_operand" "=r")) - (clobber (match_operand:SI 5 "register_operand" "=r")) - (clobber (match_operand:SI 6 "register_operand" "=r")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* return output_block_move (operands);") - -;; Floating point move insns - -;; This pattern forces (set (reg:DF ...) (const_double ...)) -;; to be reloaded by putting the constant into memory. -;; It must come before the more general movdf pattern. -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=r,f,o") - (match_operand:DF 1 "" "mG,m,G"))] - "GET_CODE (operands[1]) == CONST_DOUBLE" - "* -{ - if (FP_REG_P (operands[0]) || operands[1] == CONST0_RTX (DFmode)) - return output_fp_move_double (operands); - return output_move_double (operands); -}") - -(define_insn "movdf" - [(set (match_operand:DF 0 "general_operand" "=*rm,*r,?f,?*rm") - (match_operand:DF 1 "general_operand" "*r,m,*rfmG,f"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - if (GET_CODE (operands[1]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return output_fp_move_double (operands); - return output_move_double (operands); -}") - -(define_insn "movdi" - [(set (match_operand:DI 0 "general_operand" "=rm,r,?f,?rm") - (match_operand:DI 1 "general_operand" "r,miF,rfmG,f"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - if (GET_CODE (operands[1]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - - /* ??? How can we have a DFmode arg here with DImode above? */ - if (FP_REG_P (operands[0]) && operands[1] == CONST0_RTX (DFmode)) - return \"fmov.dd %?f0,%0\"; - - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return output_fp_move_double (operands); - return output_move_double (operands); -}") - -;; The alternative m/r is separate from m/f -;; The first alternative is separate from the second for the same reason. -(define_insn "movsf" - [(set (match_operand:SF 0 "general_operand" "=*rf,*rf,*r,m,m") - (match_operand:SF 1 "general_operand" "*r,fmG,F,*r,f"))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - return output_store (operands); - if (GET_CODE (operands[1]) == MEM - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - return output_load (operands); - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fmov.ss %1,%0\"; - if (GET_CODE (operands[1]) == REG) - return \"ixfr %1,%0\"; - if (operands[1] == CONST0_RTX (SFmode)) - return \"fmov.ss %?f0,%0\"; - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && cc_prev_status.mdep == XEXP(operands[1],0))) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return \"orh %h1,%?r0,%?r31\;fld.l %L1(%?r31),%0\"; - } - return \"fld.l %L1(%?r31),%0\"; - } - return \"fld.l %1,%0\"; - } - if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE) - { - if (GET_CODE (operands[0]) == REG && FP_REG_P (operands[1])) - return \"fxfr %1,%0\"; - if (GET_CODE (operands[0]) == REG) - { - CC_STATUS_PARTIAL_INIT; - if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - register unsigned long ul; - - ul = sfmode_constant_to_ulong (operands[1]); - if ((ul & 0x0000ffff) == 0) - return \"orh %H1,%?r0,%0\"; - if ((ul & 0xffff0000) == 0) - return \"or %L1,%?r0,%0\"; - } - return \"orh %H1,%?r0,%0\;or %L1,%0,%0\"; - } - /* Now operand 0 must be memory. - If operand 1 is CONST_DOUBLE, its value must be 0. */ - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && XEXP (operands[0], 0) == cc_prev_status.mdep)) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - output_asm_insn (\"orh %h0,%?r0,%?r31\", operands); - } - return \"fst.l %r1,%L0(%?r31)\"; - } - return \"fst.l %r1,%0\"; - } - if (GET_CODE (operands[0]) == MEM) - return \"st.l %r1,%0\"; - if (GET_CODE (operands[1]) == MEM) - return \"ld.l %1,%0\"; - if (operands[1] == CONST0_RTX (SFmode)) - return \"shl %?r0,%?r0,%0\"; - return \"mov %1,%0\"; -}") - -;; Special load insns for REG+REG addresses. -;; Such addresses are not "legitimate" because st rejects them. - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=rf") - (match_operand:DF 1 "indexed_operand" "m"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - return output_fp_move_double (operands); - return output_move_double (operands); -}") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=rf") - (match_operand:SF 1 "indexed_operand" "m"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - return \"fld.l %1,%0\"; - return \"ld.l %1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=rf") - (match_operand:SI 1 "indexed_operand" "m"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - return \"fld.l %1,%0\"; - return \"ld.l %1,%0\"; -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "indexed_operand" "m"))] - "" - "ld.s %1,%0") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (match_operand:QI 1 "indexed_operand" "m"))] - "" - "ld.b %1,%0") - -;; Likewise for floating-point store insns. - -(define_insn "" - [(set (match_operand:DF 0 "indexed_operand" "=m") - (match_operand:DF 1 "register_operand" "f"))] - "" - "fst.d %1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "indexed_operand" "=m") - (match_operand:SF 1 "register_operand" "f"))] - "" - "fst.l %1,%0") - -;;- truncation instructions -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=g") - (truncate:QI - (match_operand:SI 1 "register_operand" "r")))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && XEXP (operands[0], 0) == cc_prev_status.mdep)) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - output_asm_insn (\"orh %h0,%?r0,%?r31\", operands); - } - return \"st.b %1,%L0(%?r31)\"; - } - else - return \"st.b %1,%0\"; - } - return \"shl %?r0,%1,%0\"; -}") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=g") - (truncate:QI - (match_operand:HI 1 "register_operand" "r")))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && XEXP (operands[0], 0) == cc_prev_status.mdep)) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - output_asm_insn (\"orh %h0,%?r0,%?r31\", operands); - } - return \"st.b %1,%L0(%?r31)\"; - } - else - return \"st.b %1,%0\"; - } - return \"shl %?r0,%1,%0\"; -}") - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=g") - (truncate:HI - (match_operand:SI 1 "register_operand" "r")))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - if (! ((cc_prev_status.flags & CC_KNOW_HI_R31) - && (cc_prev_status.flags & CC_HI_R31_ADJ) - && XEXP (operands[0], 0) == cc_prev_status.mdep)) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[0], 0); - output_asm_insn (\"orh %h0,%?r0,%?r31\", operands); - } - return \"st.s %1,%L0(%?r31)\"; - } - else - return \"st.s %1,%0\"; - } - return \"shl %?r0,%1,%0\"; -}") - -;;- zero extension instructions - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI - (match_operand:HI 1 "register_operand" "r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and 0xffff,%1,%0\"; -}") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI - (match_operand:QI 1 "register_operand" "r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and 0xff,%1,%0\"; -}") - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI - (match_operand:QI 1 "register_operand" "r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and 0xff,%1,%0\"; -}") - -;; Sign extension instructions. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI - (match_operand:HI 1 "indexed_operand" "m")))] - "" - "ld.s %1,%0") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI - (match_operand:QI 1 "indexed_operand" "m")))] - "" - "ld.b %1,%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI - (match_operand:QI 1 "indexed_operand" "m")))] - "" - "ld.b %1,%0") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "mr")))] - "" - "* -{ - if (REG_P (operands[1])) - return \"shl 16,%1,%0\;shra 16,%0,%0\"; - if (GET_CODE (operands[1]) == CONST_INT) - abort (); - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return \"orh %h1,%?r0,%?r31\;ld.s %L1(%?r31),%0\"; - } - else - return \"ld.s %1,%0\"; -}") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "mr")))] - "" - "* -{ - if (REG_P (operands[1])) - return \"shl 24,%1,%0\;shra 24,%0,%0\"; - if (GET_CODE (operands[1]) == CONST_INT) - abort (); - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\"; - } - else - return \"ld.b %1,%0\"; -}") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "mr")))] - "" - "* -{ - if (REG_P (operands[1])) - return \"shl 24,%1,%0\;shra 24,%0,%0\"; - if (GET_CODE (operands[1]) == CONST_INT) - abort (); - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\"; - } - else - return \"ld.b %1,%0\"; -}") - -;; Signed bitfield extractions come out looking like -;; (shiftrt (sign_extend (shift <Y> <C1>)) <C2>) -;; which we expand poorly as four shift insns. -;; These patterns yield two shifts: -;; (shiftrt (shift <Y> <C3>) <C4>) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI - (sign_extend:SI - (match_operand:QI 1 "register_operand" "r")) - (match_operand:SI 2 "logic_int" "n")))] - "INTVAL (operands[2]) < 8" - "* -{ - return \"shl 24,%1,%0\;shra 24+%2,%0,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI - (sign_extend:SI - (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "logic_int" "n")) 0)) - (match_operand:SI 3 "logic_int" "n")))] - "INTVAL (operands[3]) < 8" - "* -{ - return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI - (sign_extend:SI - (ashift:QI (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "logic_int" "n"))) - (match_operand:SI 3 "logic_int" "n")))] - "INTVAL (operands[3]) < 8" - "* -{ - return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\"; -}") - -;; Special patterns for optimizing bit-field instructions. - -;; First two patterns are for bitfields that came from memory -;; testing only the high bit. They work with old combiner. - -(define_insn "" - [(set (cc0) - (eq (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r") - (const_int 7)) 0)) - (const_int 0)))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and 128,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) - (eq (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r") - (const_int 7)) 0)) - (const_int 0)))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"and 128,%0,%?r0\"; -}") - -;; The next two patterns are good for bitfields coming from memory -;; (via pseudo-register) or from a register, though this optimization -;; is only good for values contained wholly within the bottom 13 bits. -(define_insn "" - [(set (cc0) - (eq - (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "logic_int" "n")) - (match_operand:SI 2 "logic_int" "n")) - (const_int 0)))] - "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))" - "* -{ - CC_STATUS_PARTIAL_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) << INTVAL (operands[1])); - return \"and %2,%0,%?r0\"; -}") - -(define_insn "" - [(set (cc0) - (eq - (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "logic_int" "n")) - (match_operand:SI 2 "logic_int" "n")) - (const_int 0)))] - "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))" - "* -{ - CC_STATUS_PARTIAL_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) << INTVAL (operands[1])); - return \"and %2,%0,%?r0\"; -}") - -;; Conversions between float and double. - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float_extend:DF - (match_operand:SF 1 "register_operand" "f")))] - "" - "fmov.sd %1,%0") - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float_truncate:SF - (match_operand:DF 1 "register_operand" "f")))] - "" - "fmov.ds %1,%0") - -;; Conversion between fixed point and floating point. -;; Note that among the fix-to-float insns -;; the ones that start with SImode come first. -;; That is so that an operand that is a CONST_INT -;; (and therefore lacks a specific machine mode) -;; will be recognized as SImode (which is always valid) -;; rather than as QImode or HImode. - -;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...))) -;; to be reloaded by putting the constant into memory. -;; It must come before the more general floatsisf2 pattern. -(define_expand "floatsidf2" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (xor:SI (match_operand:SI 1 "register_operand" "") - (const_int -2147483648))) - (set (match_dup 5) (match_dup 3)) - (set (subreg:SI (match_dup 5) 0) (match_dup 4)) - (set (match_operand:DF 0 "register_operand" "") - (minus:DF (match_dup 5) (match_dup 2)))] - "" - " -{ - REAL_VALUE_TYPE d; - /* 4503601774854144 is (1 << 30) * ((1 << 22) + (1 << 1)). */ - d = REAL_VALUE_ATOF (\"4503601774854144\", DFmode); - operands[2] = gen_reg_rtx (DFmode); - operands[3] = CONST_DOUBLE_FROM_REAL_VALUE (d, DFmode); - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (DFmode); -}") - -;; Floating to fixed conversion. - -(define_expand "fix_truncdfsi2" - ;; This first insn produces a double-word value - ;; in which only the low word is valid. - [(set (match_dup 2) - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f")))) - (set (match_operand:SI 0 "register_operand" "=f") - (subreg:SI (match_dup 2) 0))] - "" - " -{ - operands[2] = gen_reg_rtx (DImode); -}") - -;; Recognize the first insn generated above. -;; This RTL looks like a fix_truncdfdi2 insn, -;; but we don't call it that, because only 32 bits -;; of the result are valid. -;; This pattern will work for the intended purposes -;; as long as we do not have any fixdfdi2 or fix_truncdfdi2. -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] - "" - "ftrunc.dd %1,%0") - -(define_expand "fix_truncsfsi2" - ;; This first insn produces a double-word value - ;; in which only the low word is valid. - [(set (match_dup 2) - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) - (set (match_operand:SI 0 "register_operand" "=f") - (subreg:SI (match_dup 2) 0))] - "" - " -{ - operands[2] = gen_reg_rtx (DImode); -}") - -;; Recognize the first insn generated above. -;; This RTL looks like a fix_truncsfdi2 insn, -;; but we don't call it that, because only 32 bits -;; of the result are valid. -;; This pattern will work for the intended purposes -;; as long as we do not have any fixsfdi2 or fix_truncsfdi2. -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] - "" - "ftrunc.sd %1,%0") - -;;- arithmetic instructions - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,*f") - (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r,*f") - (match_operand:SI 2 "arith_operand" "rI,*f")))] - "" - "* -{ - if (which_alternative == 1) - return \"fiadd.ss %2,%1,%0\"; - CC_STATUS_PARTIAL_INIT; - return \"addu %2,%1,%0\"; -}") - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=f") - (plus:DI (match_operand:DI 1 "register_operand" "%f") - (match_operand:DI 2 "register_operand" "f")))] - "" - "fiadd.dd %1,%2,%0") - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,*f") - (minus:SI (match_operand:SI 1 "register_operand" "r,I,*f") - (match_operand:SI 2 "arith_operand" "rI,r,*f")))] - "" - "* -{ - if (which_alternative == 2) - return \"fisub.ss %1,%2,%0\"; - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[2])) - return \"subu %1,%2,%0\"; - operands[2] = GEN_INT (- INTVAL (operands[2])); - return \"addu %2,%1,%0\"; -}") - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=f") - (minus:DI (match_operand:DI 1 "register_operand" "f") - (match_operand:DI 2 "register_operand" "f")))] - "" - "fisub.dd %1,%2,%0") - -(define_expand "mulsi3" - [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" "")) - (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" "")) - (clobber (match_dup 3)) - (set (subreg:SI (match_dup 3) 0) - (mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0))) - (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))] - "" - " -{ - if (WORDS_BIG_ENDIAN) - emit_insn (gen_mulsi3_big (operands[0], operands[1], operands[2])); - else - emit_insn (gen_mulsi3_little (operands[0], operands[1], operands[2])); - DONE; -}") - -(define_expand "mulsi3_little" - [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" "")) - (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" "")) - (clobber (match_dup 3)) - (set (subreg:SI (match_dup 3) 0) - (mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0))) - (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))] - "! WORDS_BIG_ENDIAN" - " -{ - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_reg_rtx (DImode); - operands[5] = gen_reg_rtx (DImode); -}") - -(define_expand "mulsi3_big" - [(set (subreg:SI (match_dup 4) 4) (match_operand:SI 1 "general_operand" "")) - (set (subreg:SI (match_dup 5) 4) (match_operand:SI 2 "general_operand" "")) - (clobber (match_dup 3)) - (set (subreg:SI (match_dup 3) 4) - (mult:SI (subreg:SI (match_dup 4) 4) (subreg:SI (match_dup 5) 4))) - (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 4))] - "WORDS_BIG_ENDIAN" - " -{ - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_reg_rtx (DImode); - operands[5] = gen_reg_rtx (DImode); -}") - -(define_insn "" - [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 0) - (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0) - (subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))] - "! WORDS_BIG_ENDIAN" - "fmlow.dd %2,%1,%0") - -(define_insn "" - [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 4) - (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 4) - (subreg:SI (match_operand:DI 2 "register_operand" "f") 4)))] - "WORDS_BIG_ENDIAN" - "fmlow.dd %2,%1,%0") - -;;- and instructions (with compliment also) -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "nonmemory_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rL")))] - "" - "* -{ - rtx xop[3]; - - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[2]) || LOGIC_INT (operands[2])) - return \"and %2,%1,%0\"; - if ((INTVAL (operands[2]) & 0xffff) == 0) - { - operands[2] - = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"andh %2,%1,%0\"; - } - xop[0] = operands[0]; - xop[1] = operands[1]; - xop[2] = GEN_INT (~INTVAL (operands[2]) & 0xffff); - output_asm_insn (\"andnot %2,%1,%0\", xop); - operands[2] = GEN_INT (~(unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"andnoth %2,%0,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "rn")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "* -{ - rtx xop[3]; - - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[1]) || LOGIC_INT (operands[1])) - return \"andnot %1,%2,%0\"; - if ((INTVAL (operands[1]) & 0xffff) == 0) - { - operands[1] - = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[1]) >> 16); - return \"andnoth %1,%2,%0\"; - } - xop[0] = operands[0]; - xop[1] = GEN_INT (INTVAL (operands[1]) & 0xffff); - xop[2] = operands[2]; - output_asm_insn (\"andnot %1,%2,%0\", xop); - operands[1] = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[1]) >> 16); - return \"andnoth %1,%0,%0\"; -}") - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "nonmemory_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rL")))] - "" - "* -{ - rtx xop[3]; - - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[2]) || LOGIC_INT (operands[2])) - return \"or %2,%1,%0\"; - if ((INTVAL (operands[2]) & 0xffff) == 0) - { - operands[2] - = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"orh %2,%1,%0\"; - } - xop[0] = operands[0]; - xop[1] = operands[1]; - xop[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); - output_asm_insn (\"or %2,%1,%0\", xop); - operands[2] = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"orh %2,%0,%0\"; -}") - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_operand:SI 1 "nonmemory_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rL")))] - "" - "* -{ - rtx xop[3]; - - CC_STATUS_PARTIAL_INIT; - if (REG_P (operands[2]) || LOGIC_INT (operands[2])) - return \"xor %2,%1,%0\"; - if ((INTVAL (operands[2]) & 0xffff) == 0) - { - operands[2] - = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"xorh %2,%1,%0\"; - } - xop[0] = operands[0]; - xop[1] = operands[1]; - xop[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); - output_asm_insn (\"xor %2,%1,%0\", xop); - operands[2] = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) >> 16); - return \"xorh %2,%0,%0\"; -}") - -;(The i860 instruction set doesn't allow an immediate second operand in -; a subtraction.) -(define_insn "negsi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (neg:SI (match_operand:SI 1 "arith_operand" "r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"subu %?r0,%1,%0\"; -}") - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (not:SI (match_operand:SI 1 "arith_operand" "r")))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - return \"subu -1,%1,%0\"; -}") - -;; Floating point arithmetic instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "" - "fadd.dd %1,%2,%0") - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "" - "fadd.ss %1,%2,%0") - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "" - "fsub.dd %1,%2,%0") - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "" - "fsub.ss %1,%2,%0") - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "" - "fmul.dd %1,%2,%0") - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "" - "fmul.ss %1,%2,%0") - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "register_operand" "f")))] - "" - "fsub.dd %?f0,%1,%0") - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "f")))] - "" - "fsub.ss %?f0,%1,%0") - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=&f") - (div:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))) - (clobber (match_scratch:DF 3 "=&f")) - (clobber (match_scratch:DF 4 "=&f"))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0) - || (cc_prev_status.flags & CC_HI_R31_ADJ) - || (cc_prev_status.mdep != CONST2_RTX (SFmode))) - { - cc_status.flags |= CC_KNOW_HI_R31; - cc_status.flags &= ~CC_HI_R31_ADJ; - cc_status.mdep = CONST2_RTX (SFmode); - return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\ -orh 0x4000,%?r0,%?r31\;ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\"; - } - else - return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\ -ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\ -fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\"; -}") - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=&f") - (div:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))) - (clobber (match_scratch:SF 3 "=&f")) - (clobber (match_scratch:SF 4 "=&f"))] - "" - "* -{ - CC_STATUS_PARTIAL_INIT; - if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0) - || (cc_prev_status.flags & CC_HI_R31_ADJ) - || (cc_prev_status.mdep != CONST2_RTX (SFmode))) - { - cc_status.flags |= CC_KNOW_HI_R31; - cc_status.flags &= ~CC_HI_R31_ADJ; - cc_status.mdep = CONST2_RTX (SFmode); - output_asm_insn (\"orh 0x4000,%?r0,%?r31\", operands); - } - return \"ixfr %?r31,%4\;frcp.ss %2,%0\;\\ -fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;fmul.ss %0,%3,%0\;\\ -fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;\\ -fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\"; -}") - -;; Shift instructions - -;; Optimized special case of shifting, which must precede the general case. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 24)))] - "" - "* -{ - if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - CC_STATUS_INIT; - cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ; - cc_status.mdep = XEXP (operands[1], 0); - return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\"; - } - return \"ld.b %1,%0\"; -}") - - -;;- Arithmetic shift instructions. -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "shift_operand" "rn")))] - "" - "* -{ - return \"shl %2,%1,%0\"; -}") - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (ashift:HI (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "shift_operand" "rn")))] - "" - "* -{ - return \"shl %2,%1,%0\"; -}") - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (ashift:QI (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "shift_operand" "rn")))] - "" - "* -{ - return \"shl %2,%1,%0\"; -}") - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "shift_operand" "rn")))] - "" - "* -{ - return \"shra %2,%1,%0\"; -}") - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "shift_operand" "rn")))] - "" - "* -{ - return \"shr %2,%1,%0\"; -}") - -;; Unconditional and other jump instructions. - -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "* -{ - return \"br %l0\;nop\"; -}") - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "bri %0\;nop") - -;;- jump to subroutine -(define_expand "call" - [(call (match_operand:SI 0 "memory_operand" "m") - (match_operand 1 "" "i"))] - ;; operand[2] is next_arg_register - "" - " -{ - /* Make sure the address is just one reg and will stay that way. */ - if (! call_insn_operand (operands[0], QImode)) - operands[0] - = replace_equiv_address (operands[0], - copy_to_mode_reg (Pmode, - XEXP (operands[0], 0))); - if (INTVAL (operands[1]) > 0) - { - emit_move_insn (arg_pointer_rtx, stack_pointer_rtx); - emit_insn (gen_rtx_USE (VOIDmode, arg_pointer_rtx)); - } -}") - -;;- Jump to subroutine. -(define_insn "" - [(call (match_operand:SI 0 "call_insn_operand" "m") - (match_operand 1 "" "i"))] - ;; operand[2] is next_arg_register - "" - "* -{ - /* strip the MEM. */ - operands[0] = XEXP (operands[0], 0); - CC_STATUS_INIT; - if (GET_CODE (operands[0]) == REG) - return \"calli %0\;nop\"; - return \"call %0\;nop\"; -}") - -(define_expand "call_value" - [(set (match_operand 0 "register_operand" "=rf") - (call (match_operand:SI 1 "memory_operand" "m") - (match_operand 2 "" "i")))] - ;; operand 3 is next_arg_register - "" - " -{ - /* Make sure the address is just one reg and will stay that way. */ - if (! call_insn_operand (operands[1], QImode)) - operands[1] - = replace_equiv_address (operands[1], - copy_to_mode_reg (Pmode, - XEXP (operands[1], 0))); - if (INTVAL (operands[2]) > 0) - { - emit_move_insn (arg_pointer_rtx, stack_pointer_rtx); - emit_insn (gen_rtx_USE (VOIDmode, arg_pointer_rtx)); - } -}") - -(define_insn "" - [(set (match_operand 0 "register_operand" "=rf") - (call (match_operand:SI 1 "call_insn_operand" "m") - (match_operand 2 "" "i")))] - ;; operand 3 is next_arg_register - "" - "* -{ - /* Strip the MEM. */ - operands[1] = XEXP (operands[1], 0); - CC_STATUS_INIT; - if (GET_CODE (operands[1]) == REG) - return \"calli %1\;nop\"; - return \"call %1\;nop\"; -}") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] - "" - "") - -(define_insn "nop" - [(const_int 0)] - "" - "nop") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "bri %0") - -;; -;; A special insn that does the work to get setup just -;; before a table jump. -;; -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") - (label_ref (match_operand 2 "" "")))))] - "" - "* -{ - CC_STATUS_INIT; - return \"orh %H2,%?r0,%?r31\;or %L2,%?r31,%?r31\;ld.l %?r31(%1),%0\"; -}") - diff --git a/gcc/config/i860/i860.opt b/gcc/config/i860/i860.opt deleted file mode 100644 index 588832547cf..00000000000 --- a/gcc/config/i860/i860.opt +++ /dev/null @@ -1,32 +0,0 @@ -; Options for the Intel i860 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. - -mxp -Target Report RejectNegative Mask(XP) -Generate code which uses the FPU - -mnoxp -Target Report RejectNegative InverseMask(XP) -Do not generate code which uses the FPU - -mxr -Target Report RejectNegative InverseMask(XP) -Do not generate code which uses the FPU diff --git a/gcc/config/i860/sysv4.h b/gcc/config/i860/sysv4.h deleted file mode 100644 index 78e62826e96..00000000000 --- a/gcc/config/i860/sysv4.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Target definitions for GNU compiler for Intel 80860 running System V.4 - Copyright (C) 1991, 1996, 2000, 2002, 2003 Free Software Foundation, Inc. - Contributed by Ron Guilmette (rfg@monkeys.com). - -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. */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (i860 System V Release 4)"); - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "" - -/* Provide a set of pre-definitions and pre-assertions appropriate for - the i860 running svr4. Note that the symbol `__svr4__' MUST BE - DEFINED! It is needed so that the va_list struct in va-i860.h - will get correctly defined for the svr4 (ABI compliant) case rather - than for the previous (svr3, svr2, ...) case. It also needs to be - defined so that the correct (svr4) version of __builtin_saveregs - will be selected when we are building gnulib2.c. - __svr4__ is our extension. */ - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("unix"); \ - builtin_define ("SVR4"); \ - builtin_define ("__svr4__"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=svr4"); \ - } \ - while (0) - -/* For the benefit of i860_va_arg, flag it this way too. */ - -#define I860_SVR4_VA_LIST 1 - -/* The prefix to be used in assembler output for all names of registers. - This string gets prepended to all i860 register names (svr4 only). */ - -#define I860_REG_PREFIX "%" - -#define ASM_COMMENT_START "#" - -#undef TYPE_OPERAND_FMT -#define TYPE_OPERAND_FMT "\"%s\"" - -#define GLOBAL_ASM_OP ".globl " - -/* The following macro definition overrides the one in i860.h - because the svr4 i860 assembler requires a different syntax - for getting parts of constant/relocatable values. */ - -#undef PRINT_OPERAND_PART -#define PRINT_OPERAND_PART(FILE, X, PART_CODE) \ - do { fprintf (FILE, "["); \ - output_address (X); \ - fprintf (FILE, "]@%s", PART_CODE); \ - } while (0) - -#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE -#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true -#undef TARGET_ASM_FILE_START -#define TARGET_ASM_FILE_START i860_file_start - -/* Output the special word the svr4 SDB wants to see just before - the first word of each function's prologue code. */ - -extern const char *current_function_original_name; - -/* This special macro is used to output a magic word just before the - first word of each function. On some versions of UNIX running on - the i860, this word can be any word that looks like a NOP, however - under svr4, this neds to be an `shr r0,r0,r0' instruction in which - the normally unused low-order bits contain the length of the function - prologue code (in bytes). This is needed to make the svr4 SDB debugger - happy. */ - -#undef ASM_OUTPUT_FUNCTION_PREFIX -#define ASM_OUTPUT_FUNCTION_PREFIX(FILE, FNNAME) \ - do { ASM_OUTPUT_ALIGN (FILE, 2); \ - fprintf ((FILE), "\t.long\t.ep."); \ - assemble_name (FILE, FNNAME); \ - fprintf (FILE, "-"); \ - assemble_name (FILE, FNNAME); \ - fprintf (FILE, "+0xc8000000\n"); \ - current_function_original_name = (FNNAME); \ - } while (0) - -/* Output the special label that must go just after each function's - prologue code to support svr4 SDB. */ - -#define ASM_OUTPUT_PROLOGUE_SUFFIX(FILE) \ - do { fprintf (FILE, ".ep."); \ - assemble_name (FILE, current_function_original_name); \ - fprintf (FILE, ":\n"); \ - } while (0) - -/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. - - Note that we want to give these sections the SHF_WRITE attribute - because these sections will actually contain data (i.e. tables of - addresses of functions in the current root executable or shared library - file) and, in the case of a shared library, the relocatable addresses - will have to be properly resolved/relocated (and then written into) by - the dynamic linker when it actually attaches the given shared library - to the executing process. (Note that on SVR4, you may wish to use the - `-z text' option to the ELF linker, when building a shared library, as - an additional check that you are doing everything right. But if you do - use the `-z text' option when building a shared library, you will get - errors unless the .ctors and .dtors sections are marked as writable - via the SHF_WRITE attribute.) */ - -#undef CTORS_SECTION_ASM_OP -#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"aw\"" -#undef DTORS_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"aw\"" - -/* Add definitions to support the .tdesc section as specified in the svr4 - ABI for the i860. */ - -#define TDESC_SECTION_ASM_OP "\t.section\t.tdesc" - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_tdesc - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - TDESC_SECTION_FUNCTION - -#define TDESC_SECTION_FUNCTION \ -void \ -tdesc_section () \ -{ \ - if (in_section != in_tdesc) \ - { \ - fprintf (asm_out_file, "%s\n", TDESC_SECTION_ASM_OP); \ - in_section = in_tdesc; \ - } \ -} - diff --git a/gcc/config/i860/t-i860 b/gcc/config/i860/t-i860 deleted file mode 100644 index e3ec2091883..00000000000 --- a/gcc/config/i860/t-i860 +++ /dev/null @@ -1,5 +0,0 @@ -LIB2FUNCS_EXTRA = varargs.asm - -varargs.asm: $(srcdir)/config/i860/varargs.asm - cp $(srcdir)/config/i860/varargs.asm . - diff --git a/gcc/config/i860/varargs.asm b/gcc/config/i860/varargs.asm deleted file mode 100644 index 27ca7f33032..00000000000 --- a/gcc/config/i860/varargs.asm +++ /dev/null @@ -1,212 +0,0 @@ -/* Special varargs support for i860. - Copyright (C) 2001, 2003 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. - -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. */ - -#if defined(__svr4__) || defined(__alliant__) - .text - .align 4 - -/* The Alliant needs the added underscore. */ - .globl __builtin_saveregs -__builtin_saveregs: - .globl ___builtin_saveregs -___builtin_saveregs: - - andnot 0x0f,%sp,%sp /* round down to 16-byte boundary */ -#if 0 - adds -96,%sp,%sp /* allocate stack space for reg save - area and also for a new va_list - structure */ -#else - adds -80,%sp,%sp /* allocate stack space for reg save area */ -#endif - /* Save all argument registers in the arg reg save area. The - arg reg save area must have the following layout (according - to the svr4 ABI): - - struct { - union { - float freg[8]; - double dreg[4]; - } float_regs; - long ireg[12]; - }; - */ - - fst.q %f8, 0(%sp) /* save floating regs (f8-f15) */ - fst.q %f12,16(%sp) - - st.l %r16,32(%sp) /* save integer regs (r16-r27) */ - st.l %r17,36(%sp) - st.l %r18,40(%sp) - st.l %r19,44(%sp) - st.l %r20,48(%sp) - st.l %r21,52(%sp) - st.l %r22,56(%sp) - st.l %r23,60(%sp) - st.l %r24,64(%sp) - st.l %r25,68(%sp) - st.l %r26,72(%sp) - st.l %r27,76(%sp) - -#if 0 - adds 80,%sp,%r16 /* compute the address of the new - va_list structure. Put in into - r16 so that it will be returned - to the caller. */ -#endif - - /* Initialize all fields of the new va_list structure. This - structure looks like: - - typedef struct { - unsigned long ireg_used; - unsigned long freg_used; - long *reg_base; - long *mem_ptr; - } va_list; - */ - -#if 0 - st.l %r0, 0(%r16) /* nfixed */ - st.l %r0, 4(%r16) /* nfloating */ - st.l %sp, 8(%r16) /* __va_ctl points to __va_struct. */ - bri %r1 /* delayed return */ - st.l %r28,12(%r16) /* pointer to overflow args */ -#else - bri %r1 /* delayed return */ - or %sp,%r0,%r16 /* Return the address of the reg save area. */ -#endif - -#else /* not __svr4__ */ -#if defined(__PARAGON__) - /* - * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax, - * and we stand a better chance of hooking into libraries - * compiled by PGI. [andyp@ssd.intel.com] - */ - .text - .align 4 - .globl __builtin_saveregs -__builtin_saveregs: - .globl ___builtin_saveregs -___builtin_saveregs: - - andnot 0x0f,sp,sp /* round down to 16-byte boundary */ - adds -96,sp,sp /* allocate stack space for reg save - area and also for a new va_list - structure */ - /* Save all argument registers in the arg reg save area. The - arg reg save area must have the following layout (according - to the svr4 ABI): - - struct { - union { - float freg[8]; - double dreg[4]; - } float_regs; - long ireg[12]; - }; - */ - - fst.q f8, 0(sp) - fst.q f12,16(sp) - st.l r16,32(sp) - st.l r17,36(sp) - st.l r18,40(sp) - st.l r19,44(sp) - st.l r20,48(sp) - st.l r21,52(sp) - st.l r22,56(sp) - st.l r23,60(sp) - st.l r24,64(sp) - st.l r25,68(sp) - st.l r26,72(sp) - st.l r27,76(sp) - - adds 80,sp,r16 /* compute the address of the new - va_list structure. Put in into - r16 so that it will be returned - to the caller. */ - - /* Initialize all fields of the new va_list structure. This - structure looks like: - - typedef struct { - unsigned long ireg_used; - unsigned long freg_used; - long *reg_base; - long *mem_ptr; - } va_list; - */ - - st.l r0, 0(r16) /* nfixed */ - st.l r0, 4(r16) /* nfloating */ - st.l sp, 8(r16) /* __va_ctl points to __va_struct. */ - bri r1 /* delayed return */ - st.l r28,12(r16) /* pointer to overflow args */ -#else /* not __PARAGON__ */ - .text - .align 4 - - .globl ___builtin_saveregs -___builtin_saveregs: - mov sp,r30 - andnot 0x0f,sp,sp - adds -96,sp,sp /* allocate sufficient space on the stack */ - -/* Fill in the __va_struct. */ - st.l r16, 0(sp) /* save integer regs (r16-r27) */ - st.l r17, 4(sp) /* int fixed[12] */ - st.l r18, 8(sp) - st.l r19,12(sp) - st.l r20,16(sp) - st.l r21,20(sp) - st.l r22,24(sp) - st.l r23,28(sp) - st.l r24,32(sp) - st.l r25,36(sp) - st.l r26,40(sp) - st.l r27,44(sp) - - fst.q f8, 48(sp) /* save floating regs (f8-f15) */ - fst.q f12,64(sp) /* int floating[8] */ - -/* Fill in the __va_ctl. */ - st.l sp, 80(sp) /* __va_ctl points to __va_struct. */ - st.l r28,84(sp) /* pointer to more args */ - st.l r0, 88(sp) /* nfixed */ - st.l r0, 92(sp) /* nfloating */ - - adds 80,sp,r16 /* return address of the __va_ctl. */ - bri r1 - mov r30,sp - /* recover stack and pass address to start - of data. */ -#endif /* not __PARAGON__ */ -#endif /* not __svr4__ */ diff --git a/gcc/config/i860/x-sysv4 b/gcc/config/i860/x-sysv4 deleted file mode 100644 index c01fb887dca..00000000000 --- a/gcc/config/i860/x-sysv4 +++ /dev/null @@ -1,44 +0,0 @@ -# The svr4 reference port for the i860 contains an alloca.o routine -# in /usr/ucblib/libucb.a, but we can't just try to get that by -# setting CLIB to /usr/ucblib/libucb.a because (unfortunately) -# there are a lot of other routines in libucb.a which are supposed -# to be the Berkeley versions of library routines normally found in -# libc.a and many of these Berkeley versions are badly broken. Thus, -# if we try to link programs with libucb.a before libc.a, those -# programs tend to crash. - -# Also, the alloca() routine supplied in early version of svr4 for -# the i860 is non-ABI compliant. It doesn't keep the stack aligned -# to a 16-byte boundary as the ABI requires. - -# More importantly however, even a fully ABI compliant alloca() routine -# would fail to work correctly with some versions of the native svr4 C -# compiler currently being distributed for the i860 (as of 1/29/92). -# The problem is that the native C compiler generates non-ABI-compliant -# function epilogues which cut back the stack (upon function exit) in -# an incorrect manner. Specifically, they cut back the stack by adding -# the nominal *static* frame size (determined statically at compile-time) -# to the stack pointer rather than setting the stack pointer based upon -# the current value of the frame pointer (as called for in the i860 ABI). -# This can cause serious trouble in cases where you repeatedly call a -# routine which itself calls alloca(). In such cases, the stack will -# grow continuously until you finally run out of swap space or exceed -# the system's process size limit. To avoid this problem (which can -# arise when a stage1 gcc is being used to build a stage2 gcc) you -# *must* link in the C language version of alloca() which is supplied -# with gcc to your stage1 version of gcc. The following definition -# forces that to happen. - -ALLOCA=alloca.o - -# We build all stages *without* shared libraries because that may make -# debugging the compiler easier (until there is a GDB which supports -# both Dwarf *and* svr4 shared libraries). - -# Note that the native C compiler for the svr4 reference port on the -# i860 recognizes a special -gg option. Using that option causes *full* -# Dwarf debugging information to be generated, whereas using only -g -# causes only limited Dwarf debugging information to be generated. -# (This is an undocumented feature of the native svr4 C compiler.) - -CCLIBFLAGS=-Bstatic -dn -gg diff --git a/gcc/config/ip2k/crt0.S b/gcc/config/ip2k/crt0.S deleted file mode 100644 index 23390efb6a4..00000000000 --- a/gcc/config/ip2k/crt0.S +++ /dev/null @@ -1,53 +0,0 @@ -; -; Copyright (C) 2000, 2001 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. -; -; 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.) -; -; 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. -; - - .file "crt0.S" - .text - .global __start - .func __start -__start: - clr $ff ; Insure we have a zero available - mov w,#%hi8data(__stack) ; set up stack - mov sph,w ; - mov w,#%lo8data(__stack) - mov spl,w - - push #0 ; Set argc/argv. - push #0 ; Only required for testing - push #0 ; purposes and "ansi" main. - push #0 - page _main - call _main - push $81 ; use return value to call exit() - push $80 - page _exit - call _exit - break ; Should never return - .endfunc diff --git a/gcc/config/ip2k/ip2k-protos.h b/gcc/config/ip2k/ip2k-protos.h deleted file mode 100644 index b26ced8344c..00000000000 --- a/gcc/config/ip2k/ip2k-protos.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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 function_prologue (FILE *, HOST_WIDE_INT); -extern void function_epilogue (FILE *, HOST_WIDE_INT); -extern int find_one_set_bit_p (HOST_WIDE_INT); -extern int find_one_clear_bit_p (HOST_WIDE_INT); - -#ifdef TREE_CODE -extern void unique_section (tree, int); -extern int valid_machine_type_attribute (tree, tree, tree, tree); -extern int valid_machine_decl_attribute (tree, tree, tree, tree); -extern int ip2k_return_pops_args (tree, tree, int); -#endif /* TREE_CODE */ - -#ifdef RTX_CODE -extern int legitimate_address_p (enum machine_mode, rtx, int); -extern int ip2k_extra_constraint (rtx, int); -extern rtx legitimize_address (rtx, rtx, enum machine_mode, rtx); -extern int adjust_insn_length (rtx insn, int len); -extern void asm_output_char (FILE *, rtx); -extern void asm_output_short (FILE *, rtx); -extern void asm_output_byte (FILE *, int); -extern void print_operand (FILE *, rtx, int); -extern void print_operand_address (FILE *, rtx); -extern int ip2k_jump_mode (rtx, rtx); -extern void ip2k_split_words (enum machine_mode, enum machine_mode, rtx *); -extern rtx ip2k_get_low_half (rtx, enum machine_mode); -extern rtx ip2k_get_high_half (rtx, enum machine_mode); -extern int ip2k_nonptr_operand (rtx, enum machine_mode); -extern int ip2k_ptr_operand (rtx, enum machine_mode); -extern int ip2k_ip_operand (rtx, enum machine_mode); -extern int ip2k_short_operand (rtx, enum machine_mode); -extern int ip2k_gen_operand (rtx, enum machine_mode); -extern int ip2k_nonsp_reg_operand (rtx, enum machine_mode); -extern int ip2k_symbol_ref_operand (rtx, enum machine_mode); -extern const char *ip2k_set_compare (rtx, rtx); -extern const char *ip2k_gen_sCOND (rtx, enum rtx_code, rtx); -extern const char *ip2k_gen_signed_comp_branch (rtx, enum rtx_code, rtx); -extern const char *ip2k_gen_unsigned_comp_branch (rtx, enum rtx_code, rtx); -extern int is_regfile_address (rtx); -extern int ip2k_mode_dependent_address (rtx); -extern int ip2k_address_uses_reg_p (rtx, unsigned int); -extern int ip2k_xexp_not_uses_reg_p (rtx, unsigned int, int); -extern int ip2k_composite_xexp_not_uses_reg_p (rtx, unsigned int, int); -extern int ip2k_composite_xexp_not_uses_cc0_p (rtx); -extern int ip2k_signed_comparison_operator (rtx, enum machine_mode); -extern int ip2k_unsigned_comparison_operator (rtx, enum machine_mode); -extern int ip2k_unary_operator (rtx, enum machine_mode); -extern int ip2k_binary_operator (rtx, enum machine_mode); - -extern rtx ip2k_compare_operands[3]; -#endif /* RTX_CODE */ - -#ifdef HAVE_MACHINE_MODES -extern int class_max_nregs (enum reg_class, enum machine_mode); -extern enum reg_class class_likely_spilled_p (int c); -#endif /* HAVE_MACHINE_MODES */ - -#ifdef REAL_VALUE_TYPE -extern void asm_output_float (FILE *, REAL_VALUE_TYPE); -#endif - -extern int ip2k_init_elim_offset (int, int); -extern void ip2k_init_local_alloc (int *); - diff --git a/gcc/config/ip2k/ip2k.c b/gcc/config/ip2k/ip2k.c deleted file mode 100644 index e38ee5c4721..00000000000 --- a/gcc/config/ip2k/ip2k.c +++ /dev/null @@ -1,6217 +0,0 @@ -/* Subroutines used for code generation on Ubicom IP2022 - Communications Controller. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "insn-addr.h" -#include "flags.h" -#include "reload.h" -#include "tree.h" -#include "expr.h" -#include "optabs.h" -#include "toplev.h" -#include "obstack.h" -#include "function.h" -#include "recog.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" -#include "basic-block.h" - -/* There are problems with 'frame_pointer_needed'. If we force it - on, we either end up not eliminating uses of FP, which results in - SPILL register failures or we may end up with calculation errors in - the stack offsets. Isolate the decision process into a simple macro. */ -#define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED) - -static int ip2k_naked_function_p (tree); -#ifdef IP2K_MD_REORG_PASS -static void mdr_resequence_xy_yx (rtx); -static void mdr_pres_replace_and_recurse (rtx, rtx, rtx); -static void mdr_propagate_reg_equivs_sequence (rtx, rtx, rtx); -static void mdr_propagate_reg_equivs (rtx); -static int track_dp_reload (rtx , rtx *, int , int); -static void mdr_try_dp_reload_elim (rtx); -static void mdr_try_move_dp_reload (rtx); -static void mdr_try_move_pushes (rtx); -static void mdr_try_propagate_clr_sequence (rtx, unsigned int); -static void mdr_try_propagate_clr (rtx); -static void mdr_try_propagate_move_sequence (rtx, rtx, rtx); -static void mdr_try_propagate_move (rtx); -static void mdr_try_remove_redundant_insns (rtx); -static int track_w_reload (rtx, rtx *, int , int); -static void mdr_try_wreg_elim (rtx); -#endif /* IP2K_MD_REORG_PASS */ -static void ip2k_reorg (void); -static int ip2k_check_can_adjust_stack_ref (rtx, int); -static void ip2k_adjust_stack_ref (rtx *, int); -static int ip2k_xexp_not_uses_reg_for_mem (rtx, unsigned int); -static tree ip2k_handle_progmem_attribute (tree *, tree, tree, int, bool *); -static tree ip2k_handle_fndecl_attribute (tree *, tree, tree, int, bool *); -static bool ip2k_rtx_costs (rtx, int, int, int *); -static int ip2k_address_cost (rtx); -static void ip2k_init_libfuncs (void); -static bool ip2k_return_in_memory (tree, tree); -static void ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, - tree, int *, int); - -const struct attribute_spec ip2k_attribute_table[]; - - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE function_prologue - -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue - -#undef TARGET_ASM_UNIQUE_SECTION -#define TARGET_ASM_UNIQUE_SECTION unique_section - -#undef TARGET_ASM_FUNCTION_RODATA_SECTION -#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section - -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS ip2k_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST ip2k_address_cost - -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg - -#undef TARGET_INIT_LIBFUNCS -#define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs - -#undef TARGET_RETURN_IN_MEMORY -#define TARGET_RETURN_IN_MEMORY ip2k_return_in_memory - -#undef TARGET_SETUP_INCOMING_VARARGS -#define TARGET_SETUP_INCOMING_VARARGS ip2k_setup_incoming_varargs - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Prologue/Epilogue size in words. */ -static int prologue_size; -static int epilogue_size; - -/* compare and test instructions for the IP2K are materialized by - the conditional branch that uses them. This is because conditional - branches are skips over unconditional branches. */ -rtx ip2k_compare_operands[3]; /* Additional operands for condition code. */ -int ip2k_test_flag; /* Indicates Z, WREG contain condition code - information. */ - -/* Some ip2k patterns push a byte onto the stack and then access - SP-relative addresses. Since reload doesn't know about these - pushes, we must track them internally with a %< (push) or %> (pop) - indicator. */ -static int ip2k_stack_delta; - -/* Track if or how far our ip2k reorganization pass has run. */ -int ip2k_reorg_in_progress = 0; -int ip2k_reorg_completed = 0; -int ip2k_reorg_split_dimode = 0; -int ip2k_reorg_split_simode = 0; -int ip2k_reorg_split_himode = 0; -int ip2k_reorg_split_qimode = 0; -int ip2k_reorg_merge_qimode = 0; - -/* Set up local allocation order. */ - -void -ip2k_init_local_alloc (int *rao) -{ - static const int alloc_order[] = REG_ALLOC_ORDER; - - memcpy (rao, alloc_order, sizeof (alloc_order)); -} - -/* Returns the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -int -ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED, tree funtype, int size) -{ - if (TREE_CODE (funtype) == IDENTIFIER_NODE) - return size; - - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)) - return size; - - return 0; -} - -/* Return nonzero if FUNC is a naked function. */ - -static int -ip2k_naked_function_p (tree func) -{ - tree a; - - if (TREE_CODE (func) != FUNCTION_DECL) - abort (); - - a = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); - return a != NULL_TREE; -} - -/* Output function prologue. */ -void -function_prologue (FILE *file, HOST_WIDE_INT size) -{ - int leaf_func_p; - int main_p; - int reg; - rtx operands[2]; - - prologue_size = epilogue_size = 0; - - if (ip2k_naked_function_p (current_function_decl)) - { - fprintf (file, "/* prologue: naked */\n"); - return; - } - - leaf_func_p = leaf_function_p (); - main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); - - /* For now, we compute all these facts about the function, but don't - take any action based on the information. */ - - prologue_size = 0; - fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", - size); - - /* Unless we're a leaf we need to save the return PC. */ - - if (! leaf_func_p) - { - OUT_AS1 (push, calll); - OUT_AS1 (push, callh); - prologue_size += 4; - } - - /* We need to save the old FP and set the new FP pointing at the - stack location where the old one is saved. Note that because of - post-decrement addressing, the SP is off-by-one after the - push, so we harvest the SP address BEFORE we push the MSBs of - the FP. */ - if (CHAIN_FRAMES) - { - OUT_AS1 (push, REG_FP+1); /* Save old LSBs. */ - OUT_AS2 (mov, w, spl); - OUT_AS2 (mov, REG_FP+1, w); /* SPL -> FPL */ - - OUT_AS2 (mov, w, sph); /* Freeze SP MSBs */ - OUT_AS1 (push, REG_FP); /* Save old MSBs */ - OUT_AS2 (mov, REG_FP, w); /* SPH -> FPH */ - prologue_size += 12; - } - - for (reg = (CHAIN_FRAMES) ? (REG_FP - 1) : (REG_FP + 1); - reg > 0; --reg) - { - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - fprintf (file, "\t" AS1 (push,%s) "\n", reg_names[reg]); - prologue_size += 2; - } - } - - if (size) - { - operands[0] = GEN_INT (size); - - switch (size & 0xff) - { - case 0: - break; - case 1: - OUT_AS1 (dec, spl); - prologue_size += 2; - break; - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, spl, w); - prologue_size += 4; - } - - switch (size & 0xff00) - { - case 0: - break; - case 0x100: - OUT_AS1 (dec, sph); - prologue_size += 2; - break; - default: - if ((size & 0xff) != ((size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); /* Otherwise W has value we want. */ - OUT_AS2 (sub, sph, w); - prologue_size += 4; - } - } - -/* XXX - change this to use the carry-propagating subtract trick. */ - if (flag_stack_check) - { - OUT_AS2 (mov, w, sph); - OUT_AS2 (cmp, w, #%%hi8data(_end)); - OUT_AS1 (sc, ); /* C == 0 -> hi8(edata) < sph */ - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (sz, ); /* Z == 1 -> look at low byte */ - OUT_AS1 (page,0f); - OUT_AS1 (jmp,0f); /* sp < edata, so raise stack fault */ - OUT_AS2 (mov, w, spl); - OUT_AS2 (cmp, w, #%%lo8data(_end)); - OUT_AS1 (sc,); /* C==1 -> lo8(edata) >= spl */ - OUT_AS1 (page,1f); - OUT_AS1 (jmp,1f); - OUT_AS1 (0:,); - output_asm_insn ("push\t$ff", operands); - OUT_AS1 (system,); - OUT_AS1 (1:, ); - prologue_size += 30; - } -} - -/* Output function epilogue. */ -void -function_epilogue (FILE *file, HOST_WIDE_INT size) -{ - int leaf_func_p; - int reg,savelimit; - rtx operands[2]; /* Dummy used by OUT_ASn */ - int args_locals_size = current_function_args_size; - int saved_regs_p = 0; - int need_ret = 1; - - /* Use this opportunity to reset the reorg flags! */ - ip2k_reorg_in_progress = 0; - ip2k_reorg_completed = 0; - ip2k_reorg_split_dimode = 0; - ip2k_reorg_split_simode = 0; - ip2k_reorg_split_himode = 0; - ip2k_reorg_split_qimode = 0; - ip2k_reorg_merge_qimode = 0; - - if (ip2k_naked_function_p (current_function_decl)) - { - fprintf (file, "/* epilogue: naked */\n"); - return; - } - - leaf_func_p = leaf_function_p (); - epilogue_size = 0; - fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", - size); - - savelimit = (CHAIN_FRAMES) ? REG_FP : (REG_FP + 2); - for (reg = 0; reg < savelimit; reg++) - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - saved_regs_p = 1; - break; - } - - if (size) - { - if (leaf_func_p && !CHAIN_FRAMES && !saved_regs_p - && current_function_pops_args) - args_locals_size = current_function_args_size + size; - else - { - operands[0] = GEN_INT (size); - - switch (size & 0xff) - { - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (add, spl, w); - epilogue_size += 4; - /* fall-through */ - case 0: - break; - case 1: - OUT_AS1 (inc, spl); - epilogue_size += 2; - } - - switch (size & 0xff00) - { - default: - if ((size & 0xff) != ((size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); - OUT_AS2 (add, sph, w); - epilogue_size += 4; - /* fall-through */ - case 0: - break; - case 0x100: - OUT_AS1 (inc, sph); - epilogue_size += 2; - } - } - } - - for (reg = 0; reg < savelimit; reg++) - { - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - fprintf (file, "\t" AS1 (pop,%s) "\n", reg_names[reg]); - prologue_size += 2; - } - } - - if (CHAIN_FRAMES - && ! (current_function_pops_args - && current_function_args_size >= 2 - && current_function_args_size < 0x100)) - { - OUT_AS1 (pop, REG_FP); - OUT_AS1 (pop, REG_FP+1); - epilogue_size += 4; - } - - if (! leaf_func_p) - { - if (current_function_pops_args - && current_function_args_size >= 2 - && current_function_args_size < 0x100) - { - if (current_function_args_size == 2) - { - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __fp_pop2_args_ret); - OUT_AS1 (jmp, __fp_pop2_args_ret); - } - else - { - OUT_AS1 (page, __pop2_args_ret); - OUT_AS1 (jmp, __pop2_args_ret); - } - epilogue_size += 4; - } - else - { - operands[0] = GEN_INT (current_function_args_size); - OUT_AS2 (mov, w, %L0); - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __fp_pop_args_ret); - OUT_AS1 (jmp, __fp_pop_args_ret); - } - else - { - OUT_AS1 (page, __pop_args_ret); - OUT_AS1 (jmp, __pop_args_ret); - } - epilogue_size += 6; - } - need_ret = 0; - } - else - { - OUT_AS1 (pop, callh); - OUT_AS1 (pop, calll); - epilogue_size += 4; - } - } - else - { - if (current_function_pops_args - && args_locals_size >= 2 - && args_locals_size < 0x100) - { - if (args_locals_size == 2) - { - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __leaf_fp_pop2_args_ret); - OUT_AS1 (jmp, __leaf_fp_pop2_args_ret); - epilogue_size += 4; - need_ret = 0; - } - } - else - { - operands[0] = GEN_INT (args_locals_size); - if (CHAIN_FRAMES) - { - OUT_AS2 (mov, w, %L0); - OUT_AS1 (page, __leaf_fp_pop_args_ret); - OUT_AS1 (jmp, __leaf_fp_pop_args_ret); - epilogue_size += 6; - need_ret = 0; - } - } - } - } - - if (current_function_pops_args && args_locals_size && need_ret) - { - operands[0] = GEN_INT (args_locals_size); - - switch (args_locals_size & 0xff) - { - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (add, spl, w); - epilogue_size += 4; - /* fall-through */ - - case 0: - break; - - case 1: - OUT_AS1 (inc, spl); - epilogue_size += 2; - } - - switch (args_locals_size & 0xff00) - { - default: - if ((args_locals_size & 0xff) != ((args_locals_size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); - OUT_AS2 (add, sph, w); - epilogue_size += 4; - /* fall-through */ - - case 0: - break; - - case 0x100: - OUT_AS1 (inc, sph); - epilogue_size += 2; - } - } - - if (need_ret) - { - OUT_AS1 (ret,); - epilogue_size += 2; - } - - fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size); -} - -/* Return the difference between the registers after the function - prologue. - - Stack Frame grows down: - - ARGUMENTS - <------ AP ($102:$103) - RETURN PC (unless leaf function) - SAVEDFP (if needed) - <------ FP [HARD_FRAME_POINTER] ($FD:$FE) - SAVED REGS - <------ VFP [$100:$101] - STACK ALLOCATION - <------ SP ($6:$7) */ -int -ip2k_init_elim_offset (int from, int to) -{ - int leaf_func_p = leaf_function_p (); - int no_saved_pc = leaf_func_p - || ip2k_naked_function_p (current_function_decl); - int offset; - int reg; - int reglimit; - - if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - return get_frame_size () + 1; - - if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) - return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); - - /* Count all the registers we had to preserve. */ - - reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2); - for (offset = 0,reg = 0; reg < reglimit; ++reg) - { - if ((regs_ever_live[reg] && ! call_used_regs[reg])) - { - ++offset; - } - } - - if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) - return -offset; - - if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - /* Add in the stack-local variables. */ - return offset + get_frame_size () + 1; - - if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - /* Add stack-locals plus saved FP and PC. */ - return offset + get_frame_size () + 1 - + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); - - abort (); /* Unanticipated elimination. */ -} - -/* Return nonzero if X (an RTX) is a legitimate memory address on the target - machine for a memory operand of mode MODE. */ - -int -legitimate_address_p (enum machine_mode mode, rtx x, int strict) -{ - int off; - - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - switch (GET_CODE (x)) - { - case REG: - /* IP allows indirection without offset - only okay if - we don't require access to multiple bytes. */ - if (REGNO (x) == REG_IP) - return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; - - /* We can indirect through DP or SP register. */ - if (strict ? REG_OK_FOR_BASE_STRICT_P (x) - : REG_OK_FOR_BASE_NOSTRICT_P (x)) - return 'S'; - break; - - case PLUS: - /* Offsets from DP or SP are legal in the range 0..127 */ - { - rtx op1, op2; - - op1 = XEXP (x, 0); - op2 = XEXP (x, 1); - - if (REG_P (op2) && ! REG_P (op1)) - { - rtx tmp = op1; - op1 = op2; - op2 = tmp; - } - - /* Don't let anything but R+I through.. */ - if (! REG_P (op1) - || REG_P (op2) - || GET_CODE (op2) != CONST_INT) - return 0; - - switch (REGNO (op1)) - { - case REG_DP: /* only 0..127 displacement */ - case REG_SP: - off = 2 * GET_MODE_SIZE (mode); - if (! off) - off = 1; - - if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off)) - return 0; /* Positive must be small enough that after - splitting all pieces are addressed. */ - return 'S'; /* Safe displacement. */ - - case REG_IP: - if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0) - return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; - return 0; - - case REG_AP: - case REG_FP: - case REG_VFP: - default: - if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1)) - return 0; /* Allow until reload. */ - - return 'S'; - } - } - break; - - case CONST: - case SYMBOL_REF: - /* We always allow references to things in code space. */ - return is_regfile_address (x) ? 0 : 'C'; - - case LABEL_REF: - return 'L'; - - default: - return 0; - } - - return 0; -} - -/* Is ADDR mode dependent? */ -int -ip2k_mode_dependent_address (rtx addr) -{ - switch (GET_CODE (addr)) - { - case POST_INC: - case POST_DEC: - case PRE_INC: - case PRE_DEC: - return 1; - - case REG: - return (REGNO (addr) == REG_IP); /* Can't do IP displaced addresses. */ - - default: - return 0; /* Assume no dependency. */ - } -} - -/* Attempts to replace X with a valid - memory address for an operand of mode MODE. */ - -rtx -legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, rtx scratch) -{ - rtx reg; - - /* You might think that we could split up a symbolic address by - adding the HIGH 8 bits and doing a displacement off the dp. But - because we only have 7 bits of offset, that doesn't actually - help. So only constant displacements are likely to obtain an - advantage. */ - - if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) - && GET_CODE (XEXP (x, 1)) == CONST_INT - && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K')) - { - int offset = INTVAL (XEXP (x, 1)); - - reg = scratch ? scratch : gen_reg_rtx (Pmode); - - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_PLUS (Pmode, XEXP (x, 0), - GEN_INT (offset & 0xffc0)))); - x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f)); - } - - return x; /* We don't have any other tricks. */ -} - -/* Determine if X is a 'data' address or a code address. All static - data and stack variables reside in data memory. Only code is believed - to be in PRAM or FLASH. */ -int -is_regfile_address (rtx x) -{ - while (1) - switch (GET_CODE (x)) - { - case SYMBOL_REF: - return ! SYMBOL_REF_FUNCTION_P (x); /* Declared as function. */ - case CONST: - case PLUS: - x = XEXP (x, 0); - break; - case CONST_INT: - case REG: - case SUBREG: - return 1; - case LABEL_REF: - return 0; - default: - return 0; - } - - return 0; -} - -/* Output ADDR to FILE as address. */ - -void -print_operand_address (FILE *file, rtx addr) -{ - switch (GET_CODE (addr)) - { - case SUBREG: - addr = alter_subreg (&addr); - /* fall-through */ - - case REG: - fprintf (file, "(%s)", - REGNO (addr) == REG_DP ? "DP" - : REGNO (addr) == REG_SP ? "SP" - : REGNO (addr) == REG_IP ? "IP" - : REGNO (addr) == REG_VFP ? "VFP" /* Should never see this */ - : REGNO (addr) == REG_AP ? "AP" /* or this, either. */ - : reg_names[REGNO (addr)]); - break; - - case PRE_DEC: - case POST_INC: - abort (); - break; - - case CONST: - addr = XEXP (addr, 0); - print_operand_address (file, XEXP (addr, 0)); - fprintf (file, "+"); - print_operand_address (file, XEXP (addr, 1)); - return; - - case LO_SUM: - if (is_regfile_address (XEXP (addr, 1))) - fprintf (file, "%%lo8data("); - else - fprintf (file, "%%lo8insn("); - print_operand_address (file, XEXP (addr, 1)); - fprintf (file, ")"); - print_operand_address (file, XEXP (addr, 0)); - break; - - case PLUS: /* Ought to be stack or dp references. */ - if (XEXP (addr, 1) == const0_rtx - && GET_CODE (XEXP (addr, 0)) == PLUS) - { - print_operand_address (file, XEXP (addr, 0)); - return; - } - - if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP) - print_operand_address (file, XEXP (addr, 1)); /* const */ - print_operand_address (file, XEXP (addr, 0)); /* (reg) */ - break; - - case HIGH: - if (is_regfile_address (XEXP (addr, 0))) - fprintf (file, "%%hi8data("); - else - fprintf (file, "%%hi8insn("); - output_addr_const (file, XEXP (addr, 0)); - fprintf (file, ")"); - break; - - default: - output_addr_const (file, addr); - } -} - - -/* Output X as assembler operand to file FILE. */ - -void -print_operand (FILE *file, rtx x, int code) -{ - int abcd = 0; - unsigned long value; - - switch (code) - { - case '<': /* Push */ - ip2k_stack_delta++; - return; - - case '>': /* Pop */ - ip2k_stack_delta--; - return; - - case 'A': - case 'B': - case 'C': - case 'D': - abcd = code - 'A'; - break; - - case 'H': - abcd = 0; - break; - - case 'L': - abcd = 1; - break; - - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - abcd = code - 'S'; - - default: - break; - } - - if (ip2k_short_operand (x, GET_MODE (x)) - && ip2k_address_uses_reg_p (x, REG_SP)) - /* An SP-relative address needs to account for interior stack - pushes that reload didn't know about when it calculated the - stack offset. */ - abcd += ip2k_stack_delta; - - switch (GET_CODE (x)) - { - case SUBREG: - x = alter_subreg (&x); - /* fall-through */ - - case REG: - fprintf (file, reg_names[true_regnum (x) + abcd]); - break; - - case CONST_INT: - switch (code) - { - case 'x': - fprintf (file, "$%x", (int)(INTVAL (x) & 0xffff)); - break; - - case 'b': - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); /* bit selector */ - break; - - case 'e': /* "1 << n" - e.g. "exp" */ - fprintf (file, "#%d", 1 << INTVAL (x)); - break; - - case 'A': - case 'B': - case 'C': - case 'D': - value = INTVAL (x); - value >>= 8 * (3 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - - case 'H': - fprintf (file, "#%d", (int)((INTVAL (x) >> 8) & 0xff)); - break; - - case 'L': - fprintf (file, "#%d", (int)(INTVAL (x) & 0xff)); - break; - - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff; - fprintf (file, "#%ld", value); - break; - - default: - fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); - } - break; - - case SYMBOL_REF: - case LABEL_REF: - case CODE_LABEL: - case CONST: - switch (code) - { - case 'A': - case 'B': - case 'C': - case 'D': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - abort (); /* Probably an error. */ - break; - - case 'H': - fprintf (file, "#%s(", - is_regfile_address (x) ? "%hi8data" - : "%hi8insn"); - print_operand_address (file, x); - fputc (')', file); - break; - - case 'L': - fprintf (file, "#%s(", - is_regfile_address (x) ? "%lo8data" - : "%lo8insn"); - print_operand_address (file, x); - fputc (')', file); - break; - - default: - print_operand_address (file, x); - } - break; - - case MEM: - { - rtx addr = XEXP (x, 0); - - if (GET_CODE (addr) == SUBREG) - addr = alter_subreg (&x); - - if (CONSTANT_P (addr) && abcd) - { - fputc ('(', file); - print_operand_address (file, addr); - fprintf (file, ")+%d", abcd); - } - else if (abcd) - { - switch (GET_CODE (addr)) - { - case PLUS: - abcd += INTVAL (XEXP (addr, 1)); - - /* Worry about (plus (plus (reg DP) (const_int 10)) - (const_int 0)) */ - if (GET_CODE (XEXP (addr, 0)) == PLUS) - { - addr = XEXP (addr, 0); - abcd += INTVAL (XEXP (addr, 1)); - } - - fprintf (file, "%d", abcd); - print_operand_address (file, XEXP (addr, 0)); - break; - - case REG: - default: - fprintf (file, "%d", abcd); - print_operand_address (file, addr); - } - } - else if (GET_CODE (addr) == REG - && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP)) - { - fprintf (file, "0"); - print_operand_address (file, addr); - } - else - print_operand_address (file, addr); - } - break; - - case CONST_DOUBLE: - /* Is this an integer or a floating point value? */ - if (GET_MODE (x) == VOIDmode) - { - switch (code) - { - case 'S': - case 'T': - case 'U': - case 'V': - value = CONST_DOUBLE_HIGH (x); - value >>= 8 * (3 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - - case 'W': - case 'X': - case 'Y': - case 'Z': - value = CONST_DOUBLE_LOW (x); - value >>= 8 * (7 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - } - - } - else - { - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - fprintf (file, "0x%lx", value); - } - break; - - default: - fatal_insn ("bad operand", x); - } -} - -/* Remember the operands for the compare. */ -const char * -ip2k_set_compare (rtx x, rtx y) -{ - ip2k_compare_operands[0] = x; - ip2k_compare_operands[1] = y; - return ""; -} - -/* Emit the code for sCOND instructions. */ -const char * -ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED, enum rtx_code code, rtx dest) -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - - operands[2] = dest; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) - && (mode != SImode) && (mode != DImode)) - mode = GET_MODE (operands[1]); - - /* We have a fast path for a specific type of QImode compare. We ought - to extend this for larger cases too but that wins less frequently and - introduces a lot of complexity. */ - if (mode == QImode - && !rtx_equal_p (operands[0], operands[2]) - && !rtx_equal_p (operands[1], operands[2]) - && (! REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 1)))) - { - OUT_AS1 (clr, %2); - if (immediate_operand (operands[1], QImode) - && ((INTVAL (operands[1]) & 0xff) == 0xff)) - { - if (code == EQ) - OUT_AS2 (incsnz, w, %0); - else - OUT_AS2 (incsz, w, %0); - } - else if (immediate_operand (operands[1], QImode) - && ((INTVAL (operands[1]) & 0xff) == 0x01)) - { - if (code == EQ) - OUT_AS2 (decsnz, w, %0); - else - OUT_AS2 (decsz, w, %0); - } - else if (ip2k_compare_operands[1] == const0_rtx) - { - OUT_AS2 (mov, w, %0); - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - } - else - { - OUT_AS2 (mov, w, %0); - if (code == EQ) - OUT_AS2 (csne, w, %1); - else - OUT_AS2 (cse, w, %1); - } - OUT_AS1 (inc, %2); - } - else - { - if (ip2k_compare_operands[1] == const0_rtx) - { - switch (mode) - { - case QImode: - OUT_AS2 (mov, w, %0); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - break; - - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - break; - - default: - abort (); - } - } - else - { - switch (mode) - { - case QImode: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - break; - - case HImode: - OUT_AS2 (mov, w, %H1); - OUT_AS2 (cmp, w, %H0); - OUT_AS1 (sz,); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %L1); - OUT_AS2 (cmp, w, %L0); - OUT_AS1 (2:,); - break; - - case SImode: - if (code == EQ) - { - OUT_AS2 (mov, w, #1); - OUT_AS2 (mov, mulh, w); - } - else - OUT_AS1 (clr, mulh); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %D1); - OUT_AS2 (cse, w, %D0); - OUT_AS1 (2:,); - if (code == EQ) - OUT_AS1 (dec, mulh); - else - OUT_AS1 (inc, mulh); - OUT_AS2 (mov, w, mulh); - OUT_AS2 (mov, %2, w); - return ""; - - case DImode: - if (code == EQ) - { - OUT_AS2 (mov, w, #1); - OUT_AS2 (mov, mulh, w); - } - else - OUT_AS1 (clr, mulh); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (cse, w, %Z0); - OUT_AS1 (2:,); - if (code == EQ) - OUT_AS1 (dec, mulh); - else - OUT_AS1 (inc, mulh); - OUT_AS2 (mov, w, mulh); - OUT_AS2 (mov, %2, w); - return ""; - - default: - abort (); - } - } - OUT_AS2 (mov, w, #0); - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - OUT_AS1 (inc, wreg); - OUT_AS2 (mov, %2, w); - } - - return ""; -#undef operands -} - -const char * -ip2k_gen_signed_comp_branch (rtx insn, enum rtx_code code, rtx label) -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - int can_use_skip = 0; - rtx ninsn; - - operands[2] = label; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) - && (mode != SImode) && (mode != DImode)) - mode = GET_MODE (operands[1]); - - /* Look for situations where we can just skip the next instruction instead - of skipping and then branching! */ - ninsn = next_real_insn (insn); - if (ninsn - && (recog_memoized (ninsn) >= 0) - && get_attr_skip (ninsn) == SKIP_YES) - { - rtx skip_tgt = next_nonnote_insn (next_real_insn (insn)); - - /* The first situation is where the target of the jump is one insn - after the jump insn and the insn being jumped is only one machine - opcode long. */ - if (label == skip_tgt) - can_use_skip = 1; - else - { - /* If our skip target is in fact a code label then we ignore the - label and move onto the next useful instruction. Nothing we do - here has any effect on the use of skipping instructions. */ - if (GET_CODE (skip_tgt) == CODE_LABEL) - skip_tgt = next_nonnote_insn (skip_tgt); - - /* The second situation is where we have something of the form: - - test_condition - skip_conditional - page/jump label - - optional_label (this may or may not exist): - skippable_insn - page/jump label - - In this case we can eliminate the first "page/jump label". */ - if (GET_CODE (skip_tgt) == JUMP_INSN) - { - rtx set = single_set (skip_tgt); - if (GET_CODE (XEXP (set, 0)) == PC - && GET_CODE (XEXP (set, 1)) == LABEL_REF - && label == JUMP_LABEL (skip_tgt)) - can_use_skip = 2; - } - } - } - - /* gcc is a little braindead and does some rather stateful things while - inspecting attributes - we have to put this state back to what it's - supposed to be. */ - extract_constrain_insn_cached (insn); - - if (ip2k_compare_operands[1] == const0_rtx) /* These are easier. */ - { - switch (code) - { - case LT: - if (can_use_skip) - { - OUT_AS2 (sb, %0, 7); - } - else - { - OUT_AS2 (snb, %0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GT: - switch (mode) - { - case DImode: - OUT_AS2 (rl, w, %S0); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case SImode: - OUT_AS2 (rl, w, %A0); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case HImode: - OUT_AS2 (rl, w, %H0); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case QImode: - OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ - OUT_AS1 (snz, ); - OUT_AS2 (setb, wreg, 7); - OUT_AS2 (sb, wreg, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case LE: - switch (mode) - { - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); /* Z is correct. */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, %S0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); /* Z is correct. */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, %A0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - OUT_AS1 (sz, ); - OUT_AS2 (snb, %H0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case QImode: - OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, wreg, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case GE: - if (can_use_skip) - { - OUT_AS2 (snb, %0, 7); - } - else - { - OUT_AS2 (sb, %0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - return ""; - } - - /* signed compares are out of line because we can't get - the hardware to compute the overflow for us. */ - - switch (mode) - { - case QImode: - OUT_AS1 (push, %1%<); - OUT_AS1 (push, %0%>); - OUT_AS1 (page, __cmpqi2); - OUT_AS1 (call, __cmpqi2); - break; - - case HImode: - OUT_AS1 (push, %L1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %L0%<); - OUT_AS1 (push, %H0%>%>%>); - OUT_AS1 (page, __cmphi2); - OUT_AS1 (call, __cmphi2); - break; - - case SImode: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%<); - OUT_AS1 (push, %D0%<); - OUT_AS1 (push, %C0%<); - OUT_AS1 (push, %B0%<); - OUT_AS1 (push, %A0%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpsi2); - OUT_AS1 (call, __cmpsi2); - break; - - case DImode: - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - } - break; - - default: - abort (); - } - - switch (code) - { - case LT: - if (can_use_skip) - { - OUT_AS2 (cse, w, #0); - } - else - { - OUT_AS2 (csne, w, #0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GT: - if (can_use_skip) - { - OUT_AS2 (cse, w, #2); - } - else - { - OUT_AS2 (csne, w, #2); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LE: - if (can_use_skip) - { - OUT_AS2 (snb, wreg, 1); - } - else - { - OUT_AS2 (sb, wreg, 1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GE: - if (can_use_skip) - { - OUT_AS2 (csne, w, #0); - } - else - { - OUT_AS2 (cse, w, #0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - return ""; -#undef operands -} - -const char * -ip2k_gen_unsigned_comp_branch (rtx insn, enum rtx_code code, rtx label) -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - int imm_sub = 0; - int imm_cmp = 0; - int can_use_skip = 0; - rtx ninsn; - HOST_WIDE_INT const_low; - HOST_WIDE_INT const_high; - - operands[2] = label; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) && (mode != SImode) - && (mode != DImode)) - { - mode = GET_MODE (operands[1]); - } - - /* Look for situations where we can just skip the next instruction instead - of skipping and then branching! */ - ninsn = next_real_insn (insn); - if (ninsn - && (recog_memoized (ninsn) >= 0) - && get_attr_skip (ninsn) == SKIP_YES) - { - rtx skip_tgt = next_nonnote_insn (next_real_insn (insn)); - - /* The first situation is where the target of the jump is one insn - after the jump insn and the insn being jumped is only one machine - opcode long. */ - if (label == skip_tgt) - can_use_skip = 1; - else - { - /* If our skip target is in fact a code label then we ignore the - label and move onto the next useful instruction. Nothing we do - here has any effect on the use of skipping instructions. */ - if (GET_CODE (skip_tgt) == CODE_LABEL) - skip_tgt = next_nonnote_insn (skip_tgt); - - /* The second situation is where we have something of the form: - - test_condition - skip_conditional - page/jump label - - optional_label (this may or may not exist): - skippable_insn - page/jump label - - In this case we can eliminate the first "page/jump label". */ - if (GET_CODE (skip_tgt) == JUMP_INSN) - { - rtx set = single_set (skip_tgt); - if (GET_CODE (XEXP (set, 0)) == PC - && GET_CODE (XEXP (set, 1)) == LABEL_REF - && label == JUMP_LABEL (skip_tgt)) - can_use_skip = 2; - } - } - } - - /* gcc is a little braindead and does some rather stateful things while - inspecting attributes - we have to put this state back to what it's - supposed to be. */ - extract_constrain_insn_cached (insn); - - if (ip2k_compare_operands[1] == const0_rtx) - { - switch (code) - { - case LEU: - code = EQ; /* Nothing is LTU 0. */ - goto zero; - - case GTU: - code = NE; /* Anything nonzero is GTU. */ - /* fall-through */ - - case EQ: - case NE: /* Test all the bits, result in - Z AND WREG. */ - zero: - switch (mode) - { - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - break; - - case QImode: - OUT_AS2 (mov, w, %0); - break; - - default: - abort (); - } - - if (can_use_skip) - { - if (code == EQ) - OUT_AS1 (sz, ); - else - OUT_AS1 (snz, ); - } - else - { - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - /* Always succeed. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LTU: - /* Always fail. */ - break; - - default: - abort (); - } - return ""; - } - - /* Look at whether we have a constant as one of our operands. If we do - and it's in the position that we use to subtract from during our - normal optimized comparison concept then we have to shuffle things - around! */ - if (mode != QImode) - { - if ((immediate_operand (operands[1], GET_MODE (operands[1])) - && ((code == LEU) || (code == GTU))) - || (immediate_operand (operands[0], GET_MODE (operands[0])) - && ((code == LTU) || (code == GEU)))) - { - imm_sub = 1; - } - } - - /* Same as above - look if we have a constant that we can compare - for equality or non-equality. If we know this then we can look - for common value eliminations. Note that we want to ensure that - any immediate value is operand 1 to simplify the code later! */ - if ((code == EQ) || (code == NE)) - { - imm_cmp = immediate_operand (operands[1], GET_MODE (operands[1])); - if (! imm_cmp) - { - imm_cmp = immediate_operand (operands[0], GET_MODE (operands[0])); - if (imm_cmp) - { - rtx tmp = operands[1]; - operands[1] = operands[0]; - operands[0] = tmp; - } - } - } - - switch (mode) - { - case QImode: - switch (code) - { - case EQ: - if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff)) - OUT_AS2 (incsnz, w, %0); - else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01)) - OUT_AS2 (decsnz, w, %0); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (csne, w, %0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case NE: - if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff)) - OUT_AS2 (incsz, w, %0); - else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01)) - OUT_AS2 (decsz, w, %0); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (cse, w, %0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case GTU: - OUT_AS2 (mov, w, %0); - OUT_AS2 (cmp, w, %1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case GEU: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LTU: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LEU: - OUT_AS2 (mov, w, %0); - OUT_AS2 (cmp, w, %1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case HImode: - switch (code) - { - case EQ: - { - unsigned char h = 0, l = 1; - - if (imm_cmp) - { - h = (INTVAL (operands[1]) >> 8) & 0xff; - l = INTVAL (operands[1]) & 0xff; - - if ((h == 0xff) && (l == 0xff)) - { - /* We should be able to do the following, but the - IP2k simulator doesn't like it and we get a load - of failures in gcc-c-torture. */ - OUT_AS2 (incsnz, w, %L0); - OUT_AS2 (incsz, w, %H0); -/* OUT_AS1 (skip,); Should have this */ - OUT_AS1 (page, 1f);/* Shouldn't need this! */ - OUT_AS1 (jmp, 1f); /* Shouldn't need this either. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (1:,); - break; - } - else if (h == 0) - { - if (l == 1) - OUT_AS2 (dec, w, %L0); - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - } - OUT_AS2 (or, w, %H0); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (l == 0) - { - if (h == 1) - OUT_AS2 (dec, w, %H0); - else - { - OUT_AS2 (mov, w, %H0); - OUT_AS2 (sub, w, %H1); - } - OUT_AS2 (or, w, %L0); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - } - - OUT_AS2 (mov, w, %H1); - OUT_AS2 (cse, w, %H0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (h != l)) - OUT_AS2 (mov, w, %L1); - OUT_AS2 (csne, w, %L0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - break; - - case NE: - { - unsigned char h = 0, l = 1; - - if (imm_cmp) - { - h = (INTVAL (operands[1]) >> 8) & 0xff; - l = INTVAL (operands[1]) & 0xff; - - if ((h == 0xff) && (l == 0xff)) - { - OUT_AS2 (incsnz, w, %L0); - OUT_AS2 (incsz, w, %H0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (h == 0) - { - if (l == 1) - OUT_AS2 (dec, w, %L0); - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - } - OUT_AS2 (or, w, %H0); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (l == 0) - { - if (h == 1) - OUT_AS2 (dec, w, %H0); - else - { - OUT_AS2 (mov, w, %H0); - OUT_AS2 (sub, w, %H1); - } - OUT_AS2 (or, w, %L0); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - } - - OUT_AS2 (mov, w, %H1); - if (imm_cmp && (h == l)) - { - OUT_AS2 (csne, w, %H0); - OUT_AS2 (cse, w, %L0); - } - else - { - OUT_AS2 (cse, w, %H0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %L1); - OUT_AS2 (cse, w, %L0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffff never succeeds! */ - if ((INTVAL (operands[1]) & 0xffff) != 0xffff) - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %H1); - OUT_AS2 (or, w, %L1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %H1); - OUT_AS2 (or, w, %L1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if ((INTVAL (operands[1]) & 0xffff) == 0xffff) - { - /* <= 0xffff always succeeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - case SImode: - switch (code) - { - case EQ: - { - unsigned char a = 0, b = 1, c = 2, d = 3; - - if (imm_cmp) - { - a = (INTVAL (operands[1]) >> 24) & 0xff; - b = (INTVAL (operands[1]) >> 16) & 0xff; - c = (INTVAL (operands[1]) >> 8) & 0xff; - d = INTVAL (operands[1]) & 0xff; - } - - OUT_AS2 (mov, w, %A1); - if (imm_cmp && (b == a)) - { - OUT_AS2 (csne, w, %A0); - OUT_AS2 (cse, w, %B0); - } - else - { - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (c != b)) - OUT_AS2 (mov, w, %C1); - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (d != c)) - OUT_AS2 (mov, w, %D1); - OUT_AS2 (csne, w, %D0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - break; - - case NE: - { - unsigned char a = 0, b = 1, c = 2, d = 3; - - if (imm_cmp) - { - a = (INTVAL (operands[1]) >> 24) & 0xff; - b = (INTVAL (operands[1]) >> 16) & 0xff; - c = (INTVAL (operands[1]) >> 8) & 0xff; - d = INTVAL (operands[1]) & 0xff; - } - - OUT_AS2 (mov, w, %A1); - if (imm_cmp && (b == a)) - { - OUT_AS2 (csne, w, %A0); - OUT_AS2 (cse, w, %B0); - } - else - { - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - if (! imm_cmp || (c != b)) - OUT_AS2 (mov, w, %C1); - if (imm_cmp && (d == c)) - { - OUT_AS2 (csne, w, %C0); - OUT_AS2 (cse, w, %D0); - } - else - { - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %D1); - OUT_AS2 (cse, w, %D0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffffffff never succeeds! */ - if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff) - != 0xffffffff) - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D0); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C0); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B0); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %A1); - OUT_AS2 (or, w, %B1); - OUT_AS2 (or, w, %C1); - OUT_AS2 (or, w, %D1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D1); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %A1); - OUT_AS2 (or, w, %B1); - OUT_AS2 (or, w, %C1); - OUT_AS2 (or, w, %D1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D1); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff) - == 0xffffffff) - { - /* <= 0xffffffff always succeeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D0); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C0); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B0); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - case DImode: - if (GET_CODE (operands[1]) == CONST_INT) - { - const_low = INTVAL (operands[1]); - const_high = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - const_low = CONST_DOUBLE_LOW (operands[1]); - const_high = CONST_DOUBLE_HIGH (operands[1]); - } - switch (code) - { - case EQ: - { - unsigned char s = 0, t = 1, u = 2, v = 3; - unsigned char w = 4, x = 5, y = 6, z = 7; - if (optimize_size) - { - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - OUT_AS2 (csne, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - OUT_AS2 (csne, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - if (imm_cmp) - { - s = (const_high >> 24) & 0xff; - t = (const_high >> 16) & 0xff; - u = (const_high >> 8) & 0xff; - v = const_high & 0xff; - w = (const_low >> 24) & 0xff; - x = (const_low >> 16) & 0xff; - y = (const_low >> 8) & 0xff; - z = const_low & 0xff; - } - - OUT_AS2 (mov, w, %S1); - if (imm_cmp && (s == t)) - { - OUT_AS2 (csne, w, %S0); - OUT_AS2 (cse, w, %T0); - } - else - { - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - OUT_AS2 (mov, w, %U1); - if (imm_cmp && (u == v)) - { - OUT_AS2 (csne, w, %U0); - OUT_AS2 (cse, w, %V0); - } - else - { - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - OUT_AS2 (mov, w, %W1); - if (imm_cmp && (w == x)) - { - OUT_AS2 (csne, w, %W0); - OUT_AS2 (cse, w, %X0); - } - else - { - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - if (! imm_cmp || (x != y)) - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (z != y)) - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (csne, w, %Z0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - } - break; - - case NE: - { - unsigned char s = 0, t = 1, u = 2, v = 3; - unsigned char w = 4, x = 5, y = 6, z = 7; - - if (optimize_size) - { - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - OUT_AS2 (cse, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - OUT_AS2 (cse, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - if (imm_cmp) - { - s = (const_high >> 24) & 0xff; - t = (const_high >> 16) & 0xff; - u = (const_high >> 8) & 0xff; - v = const_high & 0xff; - w = (const_low >> 24) & 0xff; - x = (const_low >> 16) & 0xff; - y = (const_low >> 8) & 0xff; - z = const_low & 0xff; - } - - OUT_AS2 (mov, w, %S1); - if (imm_cmp && (s == t)) - { - OUT_AS2 (csne, w, %S0); - OUT_AS2 (cse, w, %T0); - } - else - { - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - OUT_AS2 (mov, w, %U1); - if (imm_cmp && (u == v)) - { - OUT_AS2 (csne, w, %U0); - OUT_AS2 (cse, w, %V0); - } - else - { - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - OUT_AS2 (mov, w, %W1); - if (imm_cmp && (w == x)) - { - OUT_AS2 (csne, w, %W0); - OUT_AS2 (cse, w, %X0); - } - else - { - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - if (! imm_cmp || (y != x)) - OUT_AS2 (mov, w, %Y1); - if (imm_cmp && (z == y)) - { - OUT_AS2 (csne, w, %Y0); - OUT_AS2 (cse, w, %Z0); - } - else - { - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (cse, w, %Z0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffffffffffffffff never succeeds! */ - if (((const_high & 0xffffffff) != 0xffffffff) - || ((const_low & 0xffffffff) != 0xffffffff)) - { - operands[3] = GEN_INT (const_low + 1); - operands[4] = GEN_INT (const_high - + (INTVAL (operands[3]) ? 0 : 1)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z0); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %Y0); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %X0); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %W0); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %V0); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %U0); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %T0); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - HOST_WIDE_INT const_low0; - HOST_WIDE_INT const_high0; - - if (GET_CODE (operands[0]) == CONST_INT) - { - const_low0 = INTVAL (operands[0]); - const_high0 = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[0]) == CONST_DOUBLE) - { - const_low0 = CONST_DOUBLE_LOW (operands[0]); - const_high0 = CONST_DOUBLE_HIGH (operands[0]); - } - - if (const_high0 == 0 && const_low0 == 0) - { - OUT_AS2 (mov, w, %S1); - OUT_AS2 (or, w, %T1); - OUT_AS2 (or, w, %U1); - OUT_AS2 (or, w, %V1); - OUT_AS2 (or, w, %W1); - OUT_AS2 (or, w, %X1); - OUT_AS2 (or, w, %Y1); - OUT_AS2 (or, w, %Z1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low0 - 1); - operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - HOST_WIDE_INT const_low0; - HOST_WIDE_INT const_high0; - - if (GET_CODE (operands[0]) == CONST_INT) - { - const_low0 = INTVAL (operands[0]); - const_high0 = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[0]) == CONST_DOUBLE) - { - const_low0 = CONST_DOUBLE_LOW (operands[0]); - const_high0 = CONST_DOUBLE_HIGH (operands[0]); - } - - if (const_high0 == 0 && const_low0 == 0) - { - OUT_AS2 (mov, w, %S1); - OUT_AS2 (or, w, %T1); - OUT_AS2 (or, w, %U1); - OUT_AS2 (or, w, %V1); - OUT_AS2 (or, w, %W1); - OUT_AS2 (or, w, %X1); - OUT_AS2 (or, w, %Y1); - OUT_AS2 (or, w, %Z1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low0 - 1); - operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if (((const_high & 0xffffffff) == 0xffffffff) - && ((const_low & 0xffffffff) == 0xffffffff)) - { - /* <= 0xffffffffffffffff always succeeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low + 1); - operands[4] = GEN_INT (const_high - + (INTVAL (operands[3]) ? 0 : 1)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z0); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %Y0); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %X0); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %W0); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %V0); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %U0); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %T0); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - default: - abort (); - } -#undef operands - return ""; -} - -/* Output rtx VALUE as .byte to file FILE. */ - -void -asm_output_char (FILE *file, rtx value) -{ - fprintf (file, "\t.byte "); - output_addr_const (file, value); - fprintf (file, "\n"); -} - - -/* Output VALUE as .byte to file FILE. */ - -void -asm_output_byte (FILE *file, int value) -{ - fprintf (file, "\t.byte 0x%x\n",value & 0xff); -} - - -/* Output rtx VALUE as .word to file FILE. */ - -void -asm_output_short (FILE *file, rtx value) -{ - fprintf (file, "\t.word "); - output_addr_const (file, (value)); - fprintf (file, "\n"); -} - - -/* Output real N to file FILE. */ - -void -asm_output_float (FILE *file, REAL_VALUE_TYPE n) -{ - long val; - char dstr[100]; - - REAL_VALUE_TO_TARGET_SINGLE (n, val); - real_to_decimal (dstr, &n, sizeof (dstr), 0, 1); - - fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr); -} - -/* Sets section name for declaration DECL. */ - -void -unique_section (tree decl, int reloc ATTRIBUTE_UNUSED) -{ - int len; - const char *name; - char *string; - const char *prefix; - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - /* Strip off any encoding in name. */ - name = (* targetm.strip_name_encoding) (name); - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (flag_function_sections) - prefix = ".text."; - else - prefix = ".text"; - } - else - abort (); - - if (flag_function_sections) - { - len = strlen (name) + strlen (prefix); - string = alloca (len + 1); - sprintf (string, "%s%s", prefix, name); - DECL_SECTION_NAME (decl) = build_string (len, string); - } -} - -/* Return value is nonzero if pseudos that have been - assigned to registers of class CLASS would likely be spilled - because registers of CLASS are needed for spill registers. */ - -enum reg_class -class_likely_spilled_p (int c) -{ - return (c == IP_REGS - || c == IPL_REGS - || c == IPH_REGS - || c == DP_SP_REGS - || c == SP_REGS - || c == DP_REGS - || c == DPL_REGS - || c == DPH_REGS - || c == PTR_REGS); -} - -/* Valid attributes: - progmem - put data to program memory; - naked - don't generate function prologue/epilogue and `ret' command. - - Only `progmem' attribute valid for type. */ - -const struct attribute_spec ip2k_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute }, - { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - -/* Handle a "progmem" attribute; arguments as in - struct attribute_spec.handler. */ -static tree -ip2k_handle_progmem_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (DECL_P (*node)) - { - if (TREE_CODE (*node) == TYPE_DECL) - { - /* This is really a decl attribute, not a type attribute, - but try to handle it for GCC 3.0 backwards compatibility. */ - - tree type = TREE_TYPE (*node); - tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type)); - tree newtype = build_type_attribute_variant (type, attr); - - TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type); - TREE_TYPE (*node) = newtype; - *no_add_attrs = true; - } - else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node)) - { - if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node)) - { - warning (0, "only initialized variables can be placed into " - "program memory area"); - *no_add_attrs = true; - } - } - else - { - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - } - - return NULL_TREE; -} - -/* Handle an attribute requiring a FUNCTION_DECL; arguments as in - struct attribute_spec.handler. */ -static tree -ip2k_handle_fndecl_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; -} - -/* Cost functions. */ - -/* Compute a (partial) cost for rtx X. Return true if the complete - cost has been computed, and false if subexpressions should be - scanned. In either case, *TOTAL contains the cost result. */ - -static bool -ip2k_rtx_costs (rtx x, int code, int outer_code, int *total) -{ - enum machine_mode mode = GET_MODE (x); - int extra_cost = 0; - - switch (code) - { - case CONST_INT: - case CONST_DOUBLE: - case LABEL_REF: - *total = 0; - return true; - case CONST: - case SYMBOL_REF: - *total = 8; - return true; - - case MEM: - *total = ip2k_address_cost (XEXP (x, 0)); - return true; - - case ROTATE: - case ROTATERT: - case ASHIFT: - case LSHIFTRT: - case ASHIFTRT: - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - { - int val = INTVAL (XEXP (x, 1)); - int cost; - - /* Shift by const instructions are proportional to - the shift count modulus 8. Note that we increase the mode - size multiplier by 1 to account for clearing the carry flag. */ - cost = COSTS_N_INSNS (abs (val) % 8); - cost += rtx_cost (XEXP (x, 0), code); - cost *= (GET_MODE_SIZE (mode) + 1); - - /* Sign-preserving shifts require 2 extra instructions. */ - if (code == ASHIFT) - cost += COSTS_N_INSNS (2); - - *total = cost; - return true; - } - *total = rtx_cost (XEXP (x, 0), code); - *total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8); - return true; - - case MINUS: - case PLUS: - case AND: - case XOR: - case IOR: - *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3); - return false; - - case MOD: - case DIV: - if (mode == QImode) - *total = COSTS_N_INSNS (20); - else if (mode == HImode) - *total = COSTS_N_INSNS (60); - else if (mode == SImode) - *total = COSTS_N_INSNS (180); - else - *total = COSTS_N_INSNS (540); - return true; - - case MULT: - /* These costs are OK, but should really handle subtle cases - where we're using sign or zero extended args as these are - *much* cheaper than those given below! */ - if (mode == QImode) - *total = COSTS_N_INSNS (4); - else if (mode == HImode) - *total = COSTS_N_INSNS (12); - else if (mode == SImode) - *total = COSTS_N_INSNS (36); - else - *total = COSTS_N_INSNS (108); - return true; - - case NEG: - case SIGN_EXTEND: - extra_cost = COSTS_N_INSNS (GET_MODE_SIZE (mode)); - - /* Fall through. */ - case NOT: - case COMPARE: - case ABS: - *total = extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2); - return false; - - case TRUNCATE: - case ZERO_EXTEND: - if (outer_code == SET) - { - *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2); - return false; - } - else - { - *total = -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2); - return true; - } - - case IF_THEN_ELSE: - *total = rtx_cost (XEXP (x, 0), code) + COSTS_N_INSNS (2); - return true; - - case EQ: - case NE: - case LTU: - case GTU: - case LEU: - case GEU: - case LT: - case GT: - case LE: - case GE: - *total = 0; - return false; - - default: - *total = COSTS_N_INSNS (4); - return true; - } -} - -/* Calculate the cost of a memory address. */ - -static int -ip2k_address_cost (rtx x) -{ - switch (legitimate_address_p (VOIDmode, x, 0)) - { - case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */ - return 8; - - case 'R': /* Indirected through IP. */ - return 8; - - case 'L': /* Label references. */ - return 0; - - case 'C': /* Constants and symbol references. */ - return 4; - - default: - return 1000; /* Must reload. */ - } -} - -/* As part of the machine-dependent reorg we look for opcode sequences where - we do some operation and then move the results back to one of the original - source operands. With working on the source operand directly is probably - much cheaper and the move from this to the original source operand will be - no more expensive than the original move. */ - -#ifdef IP2K_MD_REORG_PASS -static void -mdr_resequence_xy_yx (first_insn) - rtx first_insn; -{ - rtx insn; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - rtx set; - - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Look for operations that tend to be very cheap to run when the source - * and dest args are the same because the IP2022 has opcodes that can - operate on the source directly. If we have to spill through the W - register then we've possibly not got a good case for doing this. */ - if ((GET_CODE (XEXP (set, 0)) == REG - || GET_CODE (XEXP (set, 0)) == MEM) - && (GET_CODE (XEXP (set, 1)) == ASHIFT - || GET_CODE (XEXP (set, 1)) == ASHIFTRT - || GET_CODE (XEXP (set, 1)) == LSHIFTRT - || GET_CODE (XEXP (set, 1)) == XOR - || GET_CODE (XEXP (set, 1)) == IOR - || GET_CODE (XEXP (set, 1)) == AND - || GET_CODE (XEXP (set, 1)) == PLUS - || GET_CODE (XEXP (set, 1)) == MINUS - || GET_CODE (XEXP (set, 1)) == MULT)) - { - rtx set2; - rtx next_insn; - - next_insn = next_nonnote_insn (insn); - if (! next_insn) - continue; - - if (GET_CODE (next_insn) != INSN) - continue; - - set2 = ((GET_CODE (PATTERN (next_insn)) == SET) - ? PATTERN (next_insn) : NULL_RTX); - if (set2 == NULL_RTX) - continue; - - if ((GET_CODE (XEXP (XEXP (set, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM) - && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 0)) - && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0))) - { - rtx next2_insn; - rtx b_insn; - - b_insn = gen_rtx_SET (VOIDmode, - XEXP (XEXP (set, 1), 0), - gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)), - GET_MODE (XEXP (set, 0)), - XEXP (XEXP (set, 1), 0), - XEXP (XEXP (set, 1), 1))); - - emit_insn_before (b_insn, insn); - b_insn = gen_rtx_SET (GET_MODE (XEXP (set, 0)), XEXP (set, 0), - XEXP (XEXP (set, 1), 0)); - next2_insn = emit_insn_before (b_insn, insn); - delete_insn (insn); - delete_insn (next_insn); - insn = next2_insn; - continue; - } - - /* Having tried with one operand of the expression, now, if - appropriate, try to do the same thing with the second operand. - Of course there are fewer operations that can match here - because they must be commutative. */ - if (GET_RTX_CLASS (GET_CODE (XEXP (set, 1))) == RTX_COMM_ARITH - && (GET_CODE (XEXP (XEXP (set, 1), 1)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 1)) == MEM) - && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 1)) - && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0))) - { - rtx rtx_ee; - rtx next2_insn; - int swap_args; - - /* Try to ensure that we put things in a canonical form. */ - swap_args = (GET_CODE (XEXP (XEXP (set, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM); - rtx_ee = gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)), - GET_MODE (XEXP (set, 0)), - XEXP (XEXP (set, 1), swap_args ? 1 : 0), - XEXP (XEXP (set, 1), - swap_args ? 0 : 1)); - - emit_insn_before (gen_rtx_SET (VOIDmode, - XEXP (XEXP (set, 1), 1), - rtx_ee), - insn); - next2_insn = emit_insn_before (gen_rtx_SET - (GET_MODE (XEXP (set, 0)), - XEXP (set, 0), - XEXP (XEXP (set, 1), 1)), - insn); - delete_insn (insn); - delete_insn (next_insn); - insn = next2_insn; - } - } - } -} - -/* Replace and recurse until we've tried QImode pieces! */ - -static void -mdr_pres_replace_and_recurse (orig, with, insn) - rtx orig; - rtx with; - rtx insn; -{ - enum machine_mode new_mode; - - validate_replace_rtx (orig, with, insn); - - switch (GET_MODE (orig)) - { - case DImode: - case DFmode: - new_mode = SImode; - break; - - case SImode: - case SFmode: - new_mode = HImode; - break; - - case HImode: - new_mode = QImode; - break; - - default: - return; - } - - mdr_pres_replace_and_recurse (ip2k_get_low_half (orig, new_mode), - ip2k_get_low_half (with, new_mode), - insn); - mdr_pres_replace_and_recurse (ip2k_get_high_half (orig, new_mode), - ip2k_get_high_half (with, new_mode), - insn); -} - -/* Assist the following function, mdr_propagate_reg_equivs(). */ - -static void -mdr_propagate_reg_equivs_sequence (first_insn, orig, equiv) - rtx first_insn; - rtx orig; - rtx equiv; -{ - rtx try_insn; - rtx try_equiv = equiv; - - /* First scan the RTL looking for anything else that might clobber what - we're doing. If we find anything then we can't do the replacement. */ - for (try_insn = next_nonnote_insn (first_insn); - try_insn; try_insn = next_nonnote_insn (try_insn)) - { - rtx pattern; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - continue; - - pattern = PATTERN (try_insn); - if (GET_CODE (pattern) == PARALLEL) - { - int j; - - for (j = 0; j < XVECLEN (pattern, 0); j++) - { - rtx px = XVECEXP (pattern, 0, j); - - if (GET_CODE (px) == SET) - if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px, 0), - REGNO (orig), - GET_MODE_SIZE (GET_MODE (orig)))) - return; - } - } - else if (GET_CODE (pattern) == SET) - { - if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern, 0), - REGNO (orig), - GET_MODE_SIZE (GET_MODE (orig)))) - return; - } - } - - /* Once we've decided that we're safe to do the replacement then make the - changes. */ - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx set; - rtx new_equiv = NULL_RTX; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - { - try_equiv = equiv; - continue; - } - - set = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set == NULL_RTX) - continue; - - /* We look for a special case of "push" operations screwing our - register equivalence when it's based on a stack slot. We can - track this one and replace the old equivalence expression with - a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && REG_P (XEXP (XEXP (XEXP (set, 0), 0), 0)) - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (try_equiv, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - new_equiv = gen_rtx_MEM (GET_MODE (try_equiv), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (HImode, REG_SP), - GEN_INT (disp))); - } - - /* The replacement process is somewhat complicated by the fact that we - might be dealing with what were originally subregs and thus we have - to replace parts of our original expression! */ - mdr_pres_replace_and_recurse (orig, try_equiv, try_insn); - - if (new_equiv != NULL_RTX) - try_equiv = new_equiv; - } -} - -/* Try propagating register equivalences forwards. It may be that we can - replace a register use with an equivalent expression that already - holds the same value and thus allow one or more register loads to - be eliminated. */ - -static void -mdr_propagate_reg_equivs (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a stack slot equivalence for a register? */ - if (REG_P (XEXP (set, 0)) - && REGNO (XEXP (set, 0)) >= 0x88 - && GET_CODE (XEXP (set, 1)) == MEM - && GET_CODE (XEXP (XEXP (set, 1), 0)) == PLUS - && REG_P (XEXP (XEXP (XEXP (set, 1), 0), 0)) - && REGNO (XEXP (XEXP (XEXP (set, 1), 0), 0)) == REG_SP - && find_reg_note (insn, REG_EQUIV, NULL_RTX)) - { - mdr_propagate_reg_equivs_sequence (insn, XEXP (set, 0), - XEXP (set, 1)); - } - } -} - -/* Structure used to track jump targets. */ - -struct dpre_jump_targets -{ - int target; /* Is this a jump target? */ - int reach_count; /* Number of ways we can reach this insn. */ - int touch_count; /* Number of times we've touched this - insns during scanning. */ - rtx dp_equiv; /* DP-equivalence at this point. */ -}; - -struct dpre_jump_targets *ip2k_dpre_jump_targets; - -/* DP equivalence tracking used within DP reload elimination. */ - -static int -track_dp_reload (insn, dp_current, dp_current_ok, modifying) - rtx insn; - rtx *dp_current; - int dp_current_ok; - int modifying; -{ - rtx set; - - if (GET_CODE (insn) != INSN) - { - *dp_current = NULL_RTX; - return 1; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - { - *dp_current = NULL_RTX; - return 1; - } - - /* If we're pushing a PLUS or MINUS then it's a win if we can replace - an expression for which DP is equivalent with DP. This happens - surprisingly often when we pass a pointer to a structure embedded - within another structure. */ - if (*dp_current != NULL_RTX - && GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && (GET_CODE (XEXP (set, 1)) == PLUS - || GET_CODE (XEXP (set, 1)) == MINUS) - && GET_CODE (*dp_current) != SYMBOL_REF - && GET_CODE (*dp_current) != LABEL_REF - && GET_CODE (*dp_current) != CONST) - { - if (modifying) - validate_replace_rtx (*dp_current, gen_rtx_REG (HImode, REG_DP), insn); - } - - /* Look for DP being modified. If it is, see if it's being changed - to what it already is! */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_DP - && GET_MODE (XEXP (set, 0)) == HImode) - { - /* If this is an equivalence we can delete the new set operation. */ - if (*dp_current != NULL_RTX - && rtx_equal_p (XEXP (set, 1), *dp_current)) - { - if (modifying) - delete_insn (insn); - } - else - { - /* If we've not found an equivalence we can look for a special - case where an operand of the expression that sets DP is - already equivalent to DP and in that circumstance we simplify - by replacing that expression with DP. */ - if (*dp_current != NULL_RTX - && GET_CODE (*dp_current) != SYMBOL_REF - && GET_CODE (*dp_current) != LABEL_REF - && GET_CODE (*dp_current) != CONST - && modifying) - validate_replace_rtx (*dp_current, XEXP (set, 0), insn); - - /* Assuming that we're not loading DP from something that uses DP - itself then we mark the new equivalence for DP. If we did match - DP then we can't re-use this one. */ - if (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2)) - { - *dp_current = XEXP (set, 1); - return 1; - } - else - { - *dp_current = NULL_RTX; - return 1; - } - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) == REG_DPL - || REGNO (XEXP (set, 0)) == REG_DPH)) - { - /* If we clobber part of DP then we've clobbered any equivalences! */ - *dp_current = NULL_RTX; - return 1; - } - else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2) - && *dp_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*dp_current, REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing up the - setting of DP when it's based on the stack. We can track this one - and replace the old expression for DP with a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (*dp_current) == MEM - && GET_CODE (XEXP (*dp_current, 0)) == PLUS) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (*dp_current, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - *dp_current = gen_rtx_MEM (HImode, - gen_rtx_PLUS (Pmode, - gen_rtx_REG (HImode, REG_SP), - GEN_INT (disp))); - return 1; - } - - /* Now we look for writes to the stack. We can determine if these will - affect the equivalence we're tracking for DP and if not then we can - keep tracking it. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (*dp_current) == MEM) - { - /* Look at the SP offsets and look for any overlaps. */ - int dp_cur_sp_offs = INTVAL (XEXP (XEXP (*dp_current, 0), 1)); - int set_sp_offs = INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)); - - if (abs (dp_cur_sp_offs - set_sp_offs) < 2) - { - *dp_current = NULL_RTX; - return 1; - } - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && *dp_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*dp_current, REGNO (XEXP (set, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (set, - 0))))) - { - /* If we've just clobbered all or part of a register reference that we - were sharing for DP then we can't share it any more! */ - *dp_current = NULL_RTX; - } - - return dp_current_ok; -} - -/* As part of the machine-dependent reorg we scan loads and reloads of - DP to see where any are redundant. This does happens because we - are able to subsequently transform things in interesting ways. Sometimes - gcc also does unnecessary reloads too so we try to eliminate these too. */ - -static void -mdr_try_dp_reload_elim (first_insn) - rtx first_insn; -{ - rtx insn; - struct dpre_jump_targets *djt; - rtx dp_current; - int incomplete_scan; - int last_incomplete_scan; - - ip2k_dpre_jump_targets - = (struct dpre_jump_targets *) xcalloc (get_max_uid (), - sizeof (struct dpre_jump_targets)); - - /* First we scan to build up a list of all CODE_LABEL insns and we work out - how many different ways we can reach them. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - djt->target = 1; - djt->reach_count = LABEL_NUSES (insn); - djt->touch_count = 0; - djt->dp_equiv = NULL_RTX; - if (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)) - djt->reach_count++; - } - } - - /* Next we scan all of the ways of reaching the code labels to see - what the DP register is equivalent to as we reach them. If we find - that they're the same then we keep noting the matched value. We - iterate around this until we reach a convergence on DP equivalences - at all code labels - we have to be very careful not to be too - optimistic! */ - incomplete_scan = -1; - do - { - int dp_current_ok = 0; - last_incomplete_scan = incomplete_scan; - dp_current = NULL_RTX; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - /* If we have a code label then we need to see if we already know - what the equivalence is at this point. If we do then we use it - immediately, but if we don't then we have a special case to track - when we hit a fallthrough-edge (label with no barrier preceding - it). Any other accesses to the label must be from jump insns - and so they're handled elsewhere. */ - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - - /* If we're fully characterized the use the equivalence. */ - if (djt->touch_count == djt->reach_count) - { - dp_current = djt->dp_equiv; - dp_current_ok = 1; - continue; - } - - /* If we have a known equivalence for DP as we reach the - fallthrough-edge then track this into the code label. */ - if (dp_current_ok - && (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))) - { - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - { - /* When we definitely know that we can't form an - equivalence for DP here we must clobber anything - that we'd started to track too. */ - djt->dp_equiv = NULL_RTX; - dp_current = NULL_RTX; - dp_current_ok = 1; - } - } - } - - /* If we've not completely characterized this code label then - be cautious and assume that we don't know what DP is - equivalent to. */ - if (djt->touch_count < djt->reach_count) - { - dp_current = NULL_RTX; - dp_current_ok = 0; - } - - continue; - } - - /* If we've hit a jump insn then we look for either an address - vector (jump table) or for jump label references. */ - if (GET_CODE (insn) == JUMP_INSN) - { - /* Don't attempt to track here if we don't have a known - equivalence for DP at this point. */ - if (dp_current_ok) - { - rtx pat = PATTERN (insn); - if (GET_CODE (pat) == ADDR_VEC) - { - int i; - int len = XVECLEN (pat, 0); - - for (i = 0; i < len; i++) - { - rtx vec_insn = XEXP (XVECEXP (pat, 0, i), 0); - djt = &ip2k_dpre_jump_targets [INSN_UID (vec_insn)]; - - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - djt->dp_equiv = NULL_RTX; - } - } - } - else if (JUMP_LABEL (insn)) - { - rtx j_insn = JUMP_LABEL (insn); - djt = &ip2k_dpre_jump_targets[INSN_UID (j_insn)]; - - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - djt->dp_equiv = NULL_RTX; - } - } - } - - continue; - } - - /* Anything other than a code labal or jump arrives here. - We try and track DP, but sometimes we might not be able to. */ - dp_current_ok = track_dp_reload (insn, &dp_current, - dp_current_ok, 0); - } - - /* When we're looking to see if we've finished we count the number of - paths through the code labels where we weren't able to definitively - track DP. - This number is used to see if we're converging on a solution. - If this hits zero then we've fully converged, but if this stays the - same as last time then we probably can't make any further - progress. */ - incomplete_scan = 0; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - if (djt->touch_count != djt->reach_count) - { - incomplete_scan += (djt->reach_count - djt->touch_count); - djt->dp_equiv = NULL_RTX; - djt->touch_count = 0; - } - } - } - } - while (incomplete_scan && incomplete_scan != last_incomplete_scan); - - /* Finally we scan the whole function and run DP elimination. When we hit - a CODE_LABEL we pick up any stored equivalence since we now know that - every path to this point entered with DP holding the same thing! If - we subsequently have a reload that matches then we can eliminate it. */ - dp_current = NULL_RTX; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == JUMP_INSN) - continue; - - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - dp_current = djt->dp_equiv; - continue; - } - - track_dp_reload (insn, &dp_current, 1, 1); - } - - free (ip2k_dpre_jump_targets); -} - -/* As part of the machine-dependent reorg we look for reloads of DP - that we can move to earlier points within the file. - Moving these out of the way allows more peepholes to match. */ - -static void -mdr_try_move_dp_reload (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - rtx orig_first; - - /* Don't try to match the first instruction because we can't move it - anyway. */ - orig_first = first_insn; - first_insn = next_nonnote_insn (first_insn); - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Look for DP being loaded. When we find this we start a rewind - scan looking for possible positions to move this to. */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_DP - && GET_MODE (XEXP (set, 0)) == HImode) - { - int try_again; - rtx try_insn = insn; - - do - { - rtx rewind; - rtx check; - - try_again = 0; - - /* For now we do the *really* simple version of things and only - attempt to move the load of DP if it's very safe to do so. */ - rewind = prev_nonnote_insn (try_insn); - if (rewind != orig_first && rewind != NULL_RTX - && GET_CODE (rewind) == INSN) - { - check = ((GET_CODE (PATTERN (rewind)) == SET) - ? PATTERN (rewind) : NULL_RTX); - if (check != NULL_RTX - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 1))) - { - if (GET_CODE (XEXP (check, 0)) == REG - && REGNO (XEXP (check, 0)) != REG_DPH - && REGNO (XEXP (check, 0)) != REG_DPL - && (ip2k_composite_xexp_not_uses_reg_p - (XEXP (check, 1), REG_DP, 2)) - && (ip2k_composite_xexp_not_uses_reg_p - (XEXP (set, 1), - REGNO (XEXP (check, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (check, 0)))))) - { - emit_insn_before (set, rewind); - if (try_insn == insn) - insn = prev_nonnote_insn (insn); - delete_insn (try_insn); - try_insn = prev_nonnote_insn (rewind); - try_again = 1; - } - else if (GET_CODE (XEXP (set, 1)) == REG - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 1), REG_DP, 2) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REG_DP, 2) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REGNO (XEXP (set, 1)), - GET_MODE_SIZE (GET_MODE (XEXP (set, 1))))) - { - emit_insn_before (set, rewind); - if (try_insn == insn) - insn = prev_nonnote_insn (insn); - delete_insn (try_insn); - try_insn = prev_nonnote_insn (rewind); - try_again = 1; - } - } - } - } - while (try_again && try_insn); - } - } -} -#endif /* IP2K_MD_REORG_PASS */ - -/* Look to see if the expression, x, can have any stack references offset by - a fixed constant, offset. If it definitely can then returns nonzero. */ - -static int -ip2k_check_can_adjust_stack_ref (rtx x, int offset) -{ - if (ARITHMETIC_P (x)) - return (ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset) - && ip2k_check_can_adjust_stack_ref (XEXP (x, 1), offset)); - - if (UNARY_P (x)) - return ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset); - - switch (GET_CODE (x)) - { - case REG: - return (REGNO (x) != REG_SPH && REGNO (x) != REG_SPL); - - case MEM: - if (GET_CODE (XEXP (x, 0)) != PLUS) - return 1; - - if (GET_CODE (XEXP (XEXP (x, 0), 0)) != REG) - return 1; - - if (REGNO (XEXP (XEXP (x, 0), 0)) != REG_SP) - return 1; - - /* We can't allow this if the adjustment will create an - invalid address. */ - return (INTVAL (XEXP (XEXP (x, 0), 1)) - + offset <= (128 - 2 * GET_MODE_SIZE (GET_MODE (x)))); - - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - return 1; - - default: - return 0; - } -} - -/* Adjusts all of the stack references in the expression pointed to by x by - a fixed offset. */ - -static void -ip2k_adjust_stack_ref (rtx *x, int offset) -{ - if (ARITHMETIC_P (*x)) - { - ip2k_adjust_stack_ref (&XEXP (*x, 0), offset); - ip2k_adjust_stack_ref (&XEXP (*x, 1), offset); - return; - } - - if (UNARY_P (*x)) - { - ip2k_adjust_stack_ref (&XEXP (*x, 0), offset); - return; - } - - switch (GET_CODE (*x)) - { - case MEM: - if (GET_CODE (XEXP (*x, 0)) != PLUS) - return; - - if (GET_CODE (XEXP (XEXP (*x, 0), 0)) != REG) - return; - - if (REGNO (XEXP (XEXP (*x, 0), 0)) != REG_SP) - return; - - *x = copy_rtx (*x); - XEXP (XEXP (*x, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x, 0), 1)) - + offset); - break; - - default: - break; - } -} - -#ifdef IP2K_MD_REORG_PASS -/* As part of the machine-dependent reorg we look to move push instructions - to earlier points within the file. Moving these out of the way allows more - peepholes to match. */ - -static void -mdr_try_move_pushes (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - rtx orig_first; - - /* Don't try to match the first instruction because we can't move - it anyway. */ - orig_first = first_insn; - first_insn = next_nonnote_insn (first_insn); - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a push instruction? */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (XEXP (set, 1)) == REG) - { - rtx try_insn = insn; - unsigned int regno = REGNO (XEXP (set, 1)); - int reg_range = GET_MODE_SIZE (GET_MODE (XEXP (set, 1))); - - while (1) - { - rtx rewind; - rtx check; - - rewind = prev_nonnote_insn (try_insn); - if (rewind == orig_first || rewind == NULL_RTX - || GET_CODE (rewind) != INSN) - break; - - check = (GET_CODE (PATTERN (rewind)) == SET) ? PATTERN (rewind) : NULL_RTX; - if (check == NULL_RTX) - break; - - if (! ip2k_check_can_adjust_stack_ref (XEXP (check, 0), - reg_range) - || ! ip2k_check_can_adjust_stack_ref (XEXP (check, 1), - reg_range)) - break; - - /* If we've hit another push instruction we can't go any - further. */ - if (GET_CODE (XEXP (check, 0)) == MEM - && GET_CODE (XEXP (XEXP (check, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG_SP) - break; - - /* If this is a register move then check that it doesn't clobber - SP or any part of the instruction we're trying to move. */ - if (GET_CODE (XEXP (check, 0)) == REG) - { - unsigned int check_reg = REGNO (XEXP (check, 0)); - int check_reg_range = GET_MODE_SIZE (GET_MODE (XEXP (check, - 0))); - - /* If we have a special case where what we want to push is - being loaded by this "clobbering" insn then we can just - push what is being used to load us and then do the load. - This may seem a little odd, but we may subsequently be - able to merge the load with another instruction as it - may only be used once now! Note though that we - specifically don't try this if the expression being - loaded is an HImode MEM using IP. */ - if (check_reg == regno - && check_reg_range == reg_range - && ((GET_CODE (XEXP (check, 1)) == REG - || (GET_CODE (XEXP (check, 1)) == MEM - && (GET_MODE (XEXP (check, 1)) != HImode - || ip2k_xexp_not_uses_reg_for_mem (XEXP (check, 1), REG_IP)))))) - { - switch (check_reg_range) - { - case 1: - emit_insn_before (gen_movqi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 2: - emit_insn_before (gen_movhi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 4: - emit_insn_before (gen_movsi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 8: - emit_insn_before (gen_movdi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - } - - ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range); - ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range); - try_insn = prev_nonnote_insn (rewind); - /* XXX - should be a continue? */ - break; - } - - if ((check_reg == REG_SPL) - || (check_reg == REG_SPH) - || (((regno <= check_reg) - && (regno + reg_range - 1) >= check_reg) - || ((regno <= (check_reg + check_reg_range - 1)) - && ((regno + reg_range - 1) - >= (check_reg + check_reg_range - 1))))) - break; - } - - emit_insn_before (set, rewind); - delete_insn (try_insn); - ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range); - ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range); - try_insn = prev_nonnote_insn (rewind); - } - } - } -} - -/* Assist the following function, mdr_try_propagate_clr(). */ - -static void -mdr_try_propagate_clr_sequence (first_insn, regno) - rtx first_insn; - unsigned int regno; -{ - rtx try_insn; - - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx new_insn = NULL_RTX; - rtx set2; - - if (GET_CODE (try_insn) == JUMP_INSN) - continue; - - if (GET_CODE (try_insn) != INSN) - break; - - set2 = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set2 == NULL_RTX) - continue; - - if (GET_CODE (XEXP (set2, 1)) == AND - && ((GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - || (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno))) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - const0_rtx), try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == IOR - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 1)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == IOR - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 0)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == XOR - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 1)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == XOR - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 0)), - try_insn); - delete_insn (remove_insn); - } - - if (GET_CODE (XEXP (set2, 0)) == REG) - { - int reg2_range = GET_MODE_SIZE (GET_MODE (XEXP (set2, 0))); - unsigned int regno2 = REGNO (XEXP (set2, 0)); - - if (reg2_range == 1 - && regno == regno2 - && GET_CODE (XEXP (set2, 1)) == CONST_INT) - { - int iv = INTVAL (XEXP (set2, 1)); - if (iv == 0xff) - iv = -1; - if (iv == 1 || iv == -1) - { - new_insn = gen_rtx_SET (QImode, XEXP (set2, 0), - gen_rtx_PLUS (QImode, XEXP (set2, 0), - GEN_INT (iv))); - new_insn = emit_insn_before (new_insn, try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - break; - } - - if ((regno >= regno2) && (regno <= regno2 + reg2_range - 1)) - break; - - if (GET_CODE (XEXP (set2, 1)) == REG - && REGNO (XEXP (set2, 1)) == regno) - { - new_insn = emit_insn_before (gen_rtx_SET (QImode, - XEXP (set2, 0), - const0_rtx), - try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - } - - if (GET_CODE (XEXP (set2, 0)) == CC0) - { - if (GET_CODE (XEXP (set2, 1)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (set2, 1))) == 2 - && REGNO (XEXP (set2, 1)) == regno) - { - new_insn = gen_rtx_SET (VOIDmode, gen_rtx_CC0 (VOIDmode), - gen_rtx_REG(QImode, regno + 1)); - new_insn = emit_insn_before (new_insn, try_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == COMPARE - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set2, 1), 1)) >= 0 - && INTVAL (XEXP (XEXP (set2, 1), 1)) < 256) - { - new_insn = gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE(QImode, - gen_rtx_REG (QImode, - regno + 1), - XEXP (XEXP (set2, 1), - 1))); - new_insn = emit_insn_before (new_insn, try_insn); - } - - /* If we have inserted a replacement for a CC0 setter operation - then we need to delete the old one. */ - if (new_insn != NULL_RTX) - { - delete_insn (try_insn); - try_insn = new_insn; - - /* Now as we know that we have just done an unsigned compare - (remember we were zero-extended by the clr!) we also know - that we don't need a signed jump insn. If we find that - our next isns is a signed jump then make it unsigned! */ - if (GET_CODE (next_nonnote_insn (try_insn)) == JUMP_INSN) - { - rtx set3; - - try_insn = next_nonnote_insn (try_insn); - set3 = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set3 == NULL_RTX) - continue; - - /* If we discover that our jump target is only accessible - from here then we can continue our "clr" propagation to - it too! */ - if (LABEL_NUSES (JUMP_LABEL (try_insn)) == 1) - mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn), - regno); - - if (GET_CODE (XEXP (set3, 0)) == PC - && GET_CODE (XEXP (set3, 1)) == IF_THEN_ELSE - && (GET_CODE (XEXP (XEXP (set3, 1), 0)) == GT - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == GE - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LT - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LE) - && GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 0)) == CC0 - && (GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 1)) - == CONST_INT) - && GET_CODE (XEXP (XEXP (set3, 1), 1)) == LABEL_REF - && GET_CODE (XEXP (XEXP (set3, 1), 2)) == PC) - { - enum rtx_code code; - rtx new_if; - rtx cmp; - - /* Replace our old conditional jump with a new one that - does the unsigned form of what was previously a - signed comparison. */ - code = GET_CODE (XEXP (XEXP (set3, 1), 0)); - cmp = gen_rtx_fmt_ee ((code == GT - ? GTU - : (code == GE - ? GEU - : (code == LT ? LTU : LEU))), - VOIDmode, - XEXP (XEXP (XEXP (set3, 1), 0), 0), - XEXP (XEXP (XEXP (set3, 1), 0), - 1)); - new_if - = gen_rtx_SET (GET_MODE (set3), - pc_rtx, - gen_rtx_IF_THEN_ELSE - (GET_MODE (XEXP (set3, 1)), cmp, - XEXP (XEXP (set3, 1), 1), - XEXP (XEXP (set3, 1), 2))); - new_insn = emit_jump_insn_before (new_if, try_insn); - LABEL_NUSES (JUMP_LABEL (try_insn))++; - delete_insn (try_insn); - try_insn = new_insn; - } - } - } - } - else if (GET_CODE (XEXP (set2, 1)) == PLUS - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno - && (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == MEM - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == SYMBOL_REF)) - { - rtx extend = gen_rtx_ZERO_EXTEND (HImode, - gen_rtx_REG (QImode, regno + 1)); - new_insn = gen_rtx_SET (HImode, XEXP (set2, 0), - gen_rtx_PLUS (HImode, extend, - XEXP (XEXP (set2, 1), 1))); - new_insn = emit_insn_before (new_insn, try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - else if (GET_CODE (XEXP (set2, 1)) == PLUS - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 1))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno - && (GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == MEM - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST_INT - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == SYMBOL_REF)) - { - rtx t_src = gen_rtx_PLUS (HImode, - gen_rtx_ZERO_EXTEND (HImode, - gen_rtx_REG (QImode, - regno - + 1)), - XEXP (XEXP (set2, 1), 0)); - new_insn = emit_insn_before (gen_rtx_SET (HImode, XEXP (set2, 0), - t_src), - try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - } -} - -/* One of the things that can quite often happen with an 8-bit CPU is that - we end up clearing the MSByte of a 16-bit value. Unfortunately, all too - often gcc doesn't have any way to realize that only half of the value is - useful and ends up doing more work than it should. We scan for such - occurrences here, track them and reduce compare operations to a smaller - size where possible. - - Note that this is somewhat different to move propagation as we may - actually change some instruction patterns when we're doing this whereas - move propagation is just about doing a search and replace. */ - -static void -mdr_try_propagate_clr (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a "clr" instruction? */ - if (GET_CODE (XEXP (set, 0)) == REG - && GET_CODE (XEXP (set, 1)) == CONST_INT - && GET_MODE_SIZE (GET_MODE (XEXP (set, 0))) == 1 - && INTVAL (XEXP (set, 1)) == 0) - { - mdr_try_propagate_clr_sequence (insn, REGNO (XEXP (set, 0))); - } - } -} -#endif /* IP2K_MD_REORG_PASS */ - -/* Look to see if the expression, x, does not make any memory references - via the specified register. This is very conservative and only returns - nonzero if we definitely don't have such a memory ref. */ - -static int -ip2k_xexp_not_uses_reg_for_mem (rtx x, unsigned int regno) -{ - if (regno & 1) - regno &= 0xfffffffe; - - switch (GET_CODE (x)) - { - case REG: - return 1; - - case MEM: - if ((GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG - && REGNO (XEXP (XEXP (x, 0), 0)) == regno) - || (GET_CODE (XEXP (x, 0)) == REG - && REGNO (XEXP (x, 0)) == regno)) - return 0; - else - return 1; - - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CC0: - case PC: - return 1; - - default: - if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS) - return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 2), regno)); - - if (BINARY_P (x)) - return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno)); - - if (UNARY_P (x) - || GET_RTX_CLASS (GET_CODE (x)) == '3') - return ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno); - - return 0; - } -} - -#ifdef IP2K_MD_REORG_PASS -/* Assist the following function, mdr_try_propagate_move(). */ - -static void -mdr_try_propagate_move_sequence (first_insn, orig, equiv) - rtx first_insn; - rtx orig; - rtx equiv; -{ - rtx try_insn; - - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx set; - int range; - rtx new_equiv = NULL_RTX; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - break; - - set = single_set (try_insn); - if (set == NULL_RTX) - break; - - range = MAX (GET_MODE_SIZE (GET_MODE (equiv)), - GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - - if (GET_CODE (equiv) == REG - && REGNO (equiv) == REG_W - && (recog_memoized (try_insn) < 0 - || get_attr_clobberw (try_insn) != CLOBBERW_NO) - && (! (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_W - && rtx_equal_p (XEXP (set, 1), orig)))) - break; - else if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) == REG_SP - || ! ip2k_xexp_not_uses_reg_p (equiv, REGNO (XEXP (set, 0)), - range) - || ! ip2k_xexp_not_uses_reg_p (orig, REGNO (XEXP (set, 0)), - range)) - && ! rtx_equal_p (equiv, XEXP (set, 0)) - && ! rtx_equal_p (orig, XEXP (set, 0))) - break; - else if (GET_CODE (orig) == REG - && (REGNO (orig) == REG_IPL - || REGNO (orig) == REG_IPH - || REGNO (orig) == REG_DPL - || REGNO (orig) == REG_DPH) - && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 0), - REGNO (orig)) - || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 1), - REGNO (orig)))) - break; - else if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (equiv) == MEM) - { - if (! ip2k_xexp_not_uses_reg_p (equiv, REG_SP, 2)) - { - if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing - our register equivalence when it's based on a stack slot. - We can track this one and replace the old equivalence - expression with a new one. */ - if (GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (XEXP (equiv, 0)) == PLUS - && REGNO (XEXP (XEXP (equiv, 0), 0)) == REG_SP) - { - int md_size = GET_MODE_SIZE (GET_MODE (XEXP (set, 0))); - int new_sp_offs = INTVAL (XEXP (XEXP (equiv, 0), 1)) - + md_size; - - /* Don't allow an invalid stack pointer offset to be - created. */ - if (new_sp_offs > (128 - 2 * md_size)) - break; - - new_equiv - = gen_rtx_MEM (GET_MODE (equiv), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (HImode , - REG_SP), - GEN_INT (new_sp_offs))); - } - else if (! rtx_equal_p (equiv, XEXP (set, 0))) - { - /* Look at the SP offsets and look for any overlaps. */ - int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS - ? INTVAL (XEXP (XEXP (equiv, 0), 1)) - : 0; - int set_offs - = (GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS - ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)) - : 0); - - if (abs (equiv_offs - set_offs) < range) - break; - } - } - } - - if (! ip2k_xexp_not_uses_reg_p (equiv, REG_IP, 2)) - break; - - if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_DP, 2) - && ! ip2k_xexp_not_uses_reg_p (equiv, REG_DP, 2) - && ! rtx_equal_p (equiv, XEXP (set, 0))) - { - /* Look at the DP offsets and look for any overlaps. */ - int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS - ? INTVAL (XEXP (XEXP (equiv, 0), 1)) - : 0; - int set_offs = GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS - ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)) - : 0; - - if (abs (equiv_offs - set_offs) < range) - break; - } - } - - validate_replace_rtx_subexp (orig, equiv, try_insn, &XEXP (set, 1)); - - if (rtx_equal_p (equiv, XEXP (set, 0)) - || rtx_equal_p (orig, XEXP (set, 0))) - break; - - if (new_equiv != NULL_RTX) - equiv = new_equiv; - } -} - -/* Try propagating move instructions forwards. It may be that we can - replace a register use with an equivalent expression that already - holds the same value and thus allow one or more register loads to - be eliminated. */ - -static void -mdr_try_propagate_move (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a simple move instruction? */ - if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) >= 0x80 - || REGNO (XEXP (set, 0)) == REG_DPL - || REGNO (XEXP (set, 0)) == REG_DPH - || REGNO (XEXP (set, 0)) == REG_IPL - || REGNO (XEXP (set, 0)) == REG_IPH) - && ((GET_CODE (XEXP (set, 1)) == REG - && REGNO (XEXP (set, 1)) != REG_SP - && ip2k_xexp_not_uses_reg_p (XEXP (set, 0), - REGNO (XEXP (set, 1)), - GET_MODE_SIZE (GET_MODE (XEXP (set, - 0))))) - || (GET_CODE (XEXP (set, 1)) == MEM - && (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_IP, 2) - || GET_MODE (XEXP (set, 1)) == QImode) - && ((REGNO (XEXP (set, 0)) != REG_DPH - && REGNO (XEXP (set, 0)) != REG_DPL) - || ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2))) - || (GET_CODE (XEXP (set, 1)) == CONST_INT - && (GET_MODE (XEXP (set, 0)) != QImode - || INTVAL (XEXP (set, 1)) != 0)) - || GET_CODE (XEXP (set, 1)) == CONST_DOUBLE - || GET_CODE (XEXP (set, 1)) == CONST - || GET_CODE (XEXP (set, 1)) == SYMBOL_REF)) - { - mdr_try_propagate_move_sequence (insn, XEXP (set, 0), XEXP (set, 1)); - } - } -} - -/* Try to remove redundant instructions. */ - -static void -mdr_try_remove_redundant_insns (first_insn) - rtx first_insn; -{ - rtx insn; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - rtx set; - enum machine_mode mode; - int md_size; - HOST_WIDE_INT pattern; - int i; - - if (GET_CODE (insn) != INSN) - continue; - - if (GET_CODE (PATTERN (insn)) == CONST_INT) - { - /* We've found a dummy expression. */ - rtx remove_insn = insn; - insn = prev_nonnote_insn (insn); - delete_insn (remove_insn); - continue; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - mode = GET_MODE (XEXP (set, 0)); - md_size = GET_MODE_SIZE (mode); - if ((md_size < 1) || (md_size > 4)) - continue; - - pattern = 0; - for (i = 0; i < md_size; i++) - { - pattern <<= 8; - pattern |= 0xff; - } - - if ((GET_CODE (XEXP (set, 1)) == AND - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == pattern) - || ((GET_CODE (XEXP (set, 1)) == IOR - || GET_CODE (XEXP (set, 1)) == XOR) - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == 0x00)) - { - /* We've found an AND with all 1's, an XOR with all 0's or an - IOR with 0's. */ - rtx remove_insn = insn; - - /* Is it completely redundant or should it become a move insn? */ - if (! rtx_equal_p (XEXP (set, 0), XEXP (XEXP (set, 1), 0))) - { - emit_insn_before (gen_rtx_SET (mode, - XEXP (set, 0), - XEXP (XEXP (set, 1), 0)), - insn); - } - - insn = prev_nonnote_insn(insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set, 1)) == AND - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == 0) - { - /* We've found an AND with all 0's. */ - rtx remove_insn = insn; - insn = emit_insn_before (gen_rtx_SET (mode, - XEXP (set, 0), - XEXP (XEXP (set, 1), 1)), - insn); - delete_insn (remove_insn); - } - } -} - -/* Structure used to track jump targets. */ - -struct we_jump_targets -{ - int target; /* Is this a jump target? */ - int reach_count; /* Number of ways we can reach this insn. */ - int touch_count; /* Number of times we've touched this insn - during scanning. */ - rtx w_equiv; /* WREG-equivalence at this point. */ -}; - -struct we_jump_targets *ip2k_we_jump_targets; - -/* WREG equivalence tracking used within DP reload elimination. */ - -static int -track_w_reload (insn, w_current, w_current_ok, modifying) - rtx insn; - rtx *w_current; - int w_current_ok; - int modifying; -{ - rtx set; - - if (GET_CODE (insn) != INSN) - { - *w_current = NULL_RTX; - return 1; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - { - *w_current = NULL_RTX; - return 1; - } - - /* Look for W being modified. If it is, see if it's being changed - to what it already is! */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_W - && GET_MODE (XEXP (set, 0)) == QImode) - { - /* If this is an equivalence we can delete the new set operation. */ - if (*w_current != NULL_RTX - && rtx_equal_p (XEXP (set, 1), *w_current)) - { - if (modifying) - delete_insn (insn); - } - else - { - *w_current = XEXP (set, 1); - return 1; - } - } - else if (recog_memoized (insn) < 0 - || get_attr_clobberw (insn) != CLOBBERW_NO) - { - /* If we clobber W then we've clobbered any equivalences ! */ - *w_current = NULL_RTX; - return 1; - } - else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2) - && *w_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*w_current, REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing up the - setting of DP when it's based on the stack. We can track this one - and replace the old expression for DP with a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (*w_current) == MEM - && GET_CODE (XEXP (*w_current, 0)) == PLUS) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - rtx val = GEN_INT (INTVAL (XEXP (XEXP (*w_current, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - *w_current - = gen_rtx_MEM (HImode, gen_rtx_PLUS (Pmode, - gen_rtx_REG(HImode, REG_SP), - val)); - return 1; - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && *w_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*w_current, REGNO (XEXP (set, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (set - , 0))))) - { - /* If we've just clobbered all or part of a register reference that we - were sharing for W then we can't share it any more! */ - *w_current = NULL_RTX; - } - - return w_current_ok; -} - -/* As part of the machine-dependent reorg we scan moves into w and track them - to see where any are redundant. */ - -static void -mdr_try_wreg_elim (first_insn) - rtx first_insn; -{ - rtx insn; - struct we_jump_targets *wjt; - rtx w_current; - int incomplete_scan; - int last_incomplete_scan; - - ip2k_we_jump_targets - = (struct we_jump_targets *) xcalloc (get_max_uid (), - sizeof (struct we_jump_targets)); - - /* First we scan to build up a list of all CODE_LABEL insns and we work out - how many different ways we can reach them. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - wjt->target = 1; - wjt->reach_count = LABEL_NUSES (insn); - wjt->touch_count = 0; - wjt->w_equiv = NULL_RTX; - if (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)) - wjt->reach_count++; - } - } - - /* Next we scan all of the ways of reaching the code labels to see - what the WREG register is equivalent to as we reach them. If we find - that they're the same then we keep noting the matched value. We - iterate around this until we reach a convergence on WREG equivalences - at all code labels - we have to be very careful not to be too - optimistic! */ - incomplete_scan = -1; - do - { - int w_current_ok = 0; - last_incomplete_scan = incomplete_scan; - w_current = NULL_RTX; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - /* If we have a code label then we need to see if we already know - what the equivalence is at this point. If we do then we use it - immediately, but if we don't then we have a special case to track - when we hit a fallthrough-edge (label with no barrier preceding - it). Any other accesses to the label must be from jump insns - and so they're handled elsewhere. */ - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - - /* If we're fully characterized the use the equivalence. */ - if (wjt->touch_count == wjt->reach_count) - { - w_current = wjt->w_equiv; - w_current_ok = 1; - continue; - } - - /* If we have a known equivalence for WREG as we reach the - fallthrough-edge then track this into the code label. */ - if (w_current_ok - && (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))) - { - if (wjt->touch_count == 0) - wjt->w_equiv = w_current; - - if (wjt->touch_count < wjt->reach_count) - { - wjt->touch_count++; - if (! rtx_equal_p (wjt->w_equiv, w_current)) - { - /* When we definitely know that we can't form an - equivalence for WREG here we must clobber anything - that we'd started to track too. */ - wjt->w_equiv = NULL_RTX; - w_current = NULL_RTX; - w_current_ok = 1; - } - } - } - - /* If we've not completely characterized this code label then - be cautious and assume that we don't know what WREG is - equivalent to. */ - if (wjt->touch_count < wjt->reach_count) - { - w_current = NULL_RTX; - w_current_ok = 0; - } - - continue; - } - - /* If we've hit a jump insn then we look for either an address - vector (jump table) or for jump label references. */ - if (GET_CODE (insn) == JUMP_INSN) - { - /* Don't attempt to track here if we don't have a known - equivalence for WREG at this point. */ - if (w_current_ok) - { - if (JUMP_LABEL (insn)) - { - wjt - = &ip2k_we_jump_targets[INSN_UID (JUMP_LABEL (insn))]; - - if (wjt->touch_count == 0) - wjt->w_equiv = w_current; - - if (wjt->touch_count < wjt->reach_count) - { - wjt->touch_count++; - if (! rtx_equal_p (wjt->w_equiv, w_current)) - wjt->w_equiv = NULL_RTX; - } - } - } - - continue; - } - - /* Anything other than a code labal or jump arrives here. We try and - track WREG, but sometimes we might not be able to. */ - w_current_ok = track_w_reload (insn, &w_current, w_current_ok, 0); - } - - /* When we're looking to see if we've finished we count the number of - paths through the code labels where we weren't able to definitively - track WREG. This number is used to see if we're converging on a - solution. - If this hits zero then we've fully converged, but if this stays the - same as last time then we probably can't make any further - progress. */ - incomplete_scan = 0; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - if (wjt->touch_count != wjt->reach_count) - { - incomplete_scan += (wjt->reach_count - wjt->touch_count); - wjt->w_equiv = NULL_RTX; - wjt->touch_count = 0; - } - } - } - } - while (incomplete_scan && incomplete_scan != last_incomplete_scan); - - /* Finally we scan the whole function and run WREG elimination. When we hit - a CODE_LABEL we pick up any stored equivalence since we now know that - every path to this point entered with WREG holding the same thing! If - we subsequently have a reload that matches then we can eliminate it. */ - w_current = NULL_RTX; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == JUMP_INSN) - continue; - - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - w_current = wjt->w_equiv; - continue; - } - - track_w_reload (insn, &w_current, 1, 1); - } - - free (ip2k_we_jump_targets); -} -#endif /* IP2K_MD_REORG_PASS */ - -/* We perform a lot of untangling of the RTL within the reorg pass since - the IP2k requires some really bizarre (and really undesirable) things - to happen in order to guarantee not aborting. This pass causes several - earlier passes to be re-run as it progressively transforms things, - making the subsequent runs continue to win. */ - -static void -ip2k_reorg (void) -{ -#ifdef IP2K_MD_REORG_PASS - rtx first_insn, insn, set; -#endif - - CC_STATUS_INIT; - - if (optimize == 0) - { - ip2k_reorg_completed = 1; - ip2k_reorg_split_dimode = 1; - ip2k_reorg_split_simode = 1; - ip2k_reorg_split_himode = 1; - ip2k_reorg_split_qimode = 1; - ip2k_reorg_merge_qimode = 1; - return; - } -#ifndef IP2K_MD_REORG_PASS - ip2k_reorg_completed = 1; - ip2k_reorg_split_dimode = 1; - ip2k_reorg_split_simode = 1; - ip2k_reorg_split_himode = 1; - ip2k_reorg_split_qimode = 1; - ip2k_reorg_merge_qimode = 1; -#else - /* All optimizations below must be debugged and enabled one by one. - All of them commented now because of abort in GCC core. */ - - ip2k_reorg_in_progress = 1; - - first_insn = get_insns (); - - /* Look for size effects of earlier optimizations - in particular look for - situations where we're saying "use" a register on one hand but immediately - tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc - somewhere really but this is what we have to live with! */ - for (insn = first_insn; insn; insn = NEXT_INSN (insn)) - { - rtx body; - - if (GET_CODE (insn) == CODE_LABEL - || GET_CODE (insn) == NOTE - || GET_CODE (insn) == BARRIER) - continue; - - if (!INSN_P (insn)) - continue; - - body = PATTERN (insn); - if (GET_CODE (body) == USE) - if (GET_CODE (XEXP (body, 0)) == REG) - { - int reg; - - reg = REGNO (XEXP (body, 0)); - if (find_regno_note (insn, REG_DEAD, reg)) - { - delete_insn (insn); - } - } - } - - /* There's a good chance that since we last did CSE that we've rearranged - things in such a way that another go will win. Do so now! */ - reload_cse_regs (first_insn); - find_basic_blocks (first_insn); - life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES); - - /* Look for where absurd things are happening with DP. */ - mdr_try_dp_reload_elim (first_insn); - - ip2k_reorg_in_progress = 0; - ip2k_reorg_completed = 1; - - split_all_insns (0); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn); - life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_resequence_xy_yx (first_insn); - mdr_propagate_reg_equivs (first_insn); - - /* Look for redundant set instructions. These can occur when we split - instruction patterns and end up with the second half merging with - or being replaced by something that clobbers the first half. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == INSN) - { - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if ((set != NULL_RTX) - && (GET_CODE (XEXP (set, 0)) == REG) - && (GET_MODE (XEXP (set, 0)) == QImode) - && (find_regno_note (insn, REG_UNUSED, REGNO (XEXP (set, 0))))) - delete_insn (insn); - } - } - - mdr_try_move_dp_reload (first_insn); - mdr_try_move_pushes (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - - mdr_try_propagate_move (first_insn); - mdr_resequence_xy_yx (first_insn); - - ip2k_reorg_split_dimode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_move (first_insn); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - - ip2k_reorg_split_simode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_move (first_insn); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - - ip2k_reorg_split_himode = 1; - ip2k_reorg_merge_qimode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - mdr_try_propagate_clr (first_insn); - mdr_try_propagate_move (first_insn); - - mdr_try_dp_reload_elim (first_insn); - mdr_try_move_dp_reload (first_insn); - - rebuild_jump_labels (first_insn); - - /* Call to jump_optimize (...) was here, but now I removed it. */ - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_clr (first_insn); - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); - - ip2k_reorg_split_qimode = 1; - split_all_insns (0); - - mdr_try_wreg_elim (first_insn); - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn); - life_analysis (0, PROP_FINAL); -#endif -} - -static void -ip2k_init_libfuncs (void) -{ - set_optab_libfunc (smul_optab, SImode, "_mulsi3"); - set_optab_libfunc (smul_optab, DImode, "_muldi3"); - set_optab_libfunc (cmp_optab, HImode, "_cmphi2"); - set_optab_libfunc (cmp_optab, SImode, "_cmpsi2"); -} - -/* Returns a bit position if mask contains only a single bit. Returns -1 if - there were zero or more than one set bits. */ -int -find_one_set_bit_p (HOST_WIDE_INT mask) -{ - int i; - unsigned HOST_WIDE_INT n = mask; - for (i = 0; i < 32; i++) - { - if (n & 0x80000000UL) - { - if (n & 0x7fffffffUL) - return -1; - else - return 31 - i; - } - n <<= 1; - } - return -1; -} - -/* Returns a bit position if mask contains only a single clear bit. - Returns -1 if there were zero or more than one clear bits. */ -int -find_one_clear_bit_p (HOST_WIDE_INT mask) -{ - int i; - unsigned HOST_WIDE_INT n = mask; - for (i = 0; i < 32; i++) - { - if ((n & 0x80000000UL) == 0UL) - { - if ((n & 0x7fffffffUL) != 0x7fffffffUL) - return -1; - else - return 31 - i; - } - n <<= 1; - n |= 1; - } - return -1; -} - - -/* 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 -ip2k_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. */ - int pushflag = 0; - - 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]) - || (true_regnum (operands[1]) - + GET_MODE_SIZE (omode) - 1 < true_regnum (operands[0])))) - move_high_first = 1; - - if (GET_CODE (operands[0]) == SUBREG) - { - dl = simplify_gen_subreg (nmode, operands[0], omode, - GET_MODE_SIZE (nmode)); - dh = simplify_gen_subreg (nmode, operands[0], omode, 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: - abort (); - case POST_DEC: - dl = dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0)); - pushflag = 1; - break; - default: - dl = change_address (operands[0], nmode, - plus_constant (XEXP (operands[0], 0), - GET_MODE_SIZE (nmode))); - dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0)); - } - break; - default: - abort (); - } - - 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 - { - if (GET_MODE (operands[0]) != DImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - sh = gen_int_mode ((value >> 16) & 0xffff, nmode); - sl = gen_int_mode (value & 0xffff, nmode); - } - else - { - sh = gen_int_mode (CONST_DOUBLE_HIGH (operands[1]), nmode); - sl = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), nmode); - } - } - break; - - case CONST_INT: - if (operands[1] == const0_rtx) - sh = sl = const0_rtx; - else - { - int val = INTVAL (operands[1]); - int vl, vh; - - switch (nmode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - sl = gen_int_mode (vl, nmode); - sh = gen_int_mode (vh, nmode); - } - break; - - case SUBREG: - sl = simplify_gen_subreg (nmode, operands[1], omode, - GET_MODE_SIZE (nmode)); - sh = simplify_gen_subreg (nmode, operands[1], omode, 0); - break; - - case MEM: - switch (GET_CODE (XEXP (operands[1], 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - /* Worry about splitting stack pushes. */ - if (pushflag && ip2k_address_uses_reg_p (operands[1], REG_SP)) - sl = sh = change_address (operands[1], nmode, - plus_constant (XEXP (operands[1], 0), - GET_MODE_SIZE (nmode))); - else - { - sl = change_address (operands[1], nmode, - plus_constant (XEXP (operands[1], 0), - GET_MODE_SIZE (nmode))); - sh = gen_rtx_MEM (nmode, XEXP (operands[1], 0)); - } - } - break; - - default: - abort (); - } - - 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; -} - -/* Get the low half of an operand. */ -rtx -ip2k_get_low_half (rtx x, enum machine_mode mode) -{ - switch (GET_CODE (x)) - { - case REG: - if (! IS_PSEUDO_P (x)) - { - unsigned int r = REGNO (x); - - return gen_rtx_REG (mode, r + HARD_REGNO_NREGS (r, mode)); - } - else - { - return gen_rtx_SUBREG (mode, x, GET_MODE_SIZE (mode)); - } - break; - - case CONST_DOUBLE: - if (x == const0_rtx) - return const0_rtx; - else - { - if (mode != SImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - return gen_int_mode (value & 0xffff, mode); - } - else - return gen_int_mode (CONST_DOUBLE_LOW (x), mode); - } - break; - - case CONST_INT: - if (x == const0_rtx) - return const0_rtx; - else - { - int val = INTVAL (x); - int vl, vh; - - switch (mode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - return gen_int_mode (vl, mode); - } - break; - - case SUBREG: - return simplify_gen_subreg (mode, x, GET_MODE (x), GET_MODE_SIZE (mode)); - - case MEM: - switch (GET_CODE (XEXP (x, 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - return change_address (x, mode, - plus_constant (XEXP (x, 0), - GET_MODE_SIZE (mode))); - } - break; - - default: - abort (); - } - return NULL_RTX; -} - -/* Get the high half of an operand. */ -rtx -ip2k_get_high_half (rtx x, enum machine_mode mode) -{ - switch (GET_CODE (x)) - { - case REG: - if (! IS_PSEUDO_P (x)) - { - unsigned int r = REGNO (x); - - return gen_rtx_REG (mode, r); - } - else - { - return gen_rtx_SUBREG (mode, x, 0); - } - break; - - case CONST_DOUBLE: - if (x == const0_rtx) - return const0_rtx; - else - { - if (mode != SImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - return gen_int_mode ((value >> 16) & 0xffff, mode); - } - else - return gen_int_mode (CONST_DOUBLE_HIGH (x), mode); - } - break; - - case CONST_INT: - if (x == const0_rtx) - return const0_rtx; - else - { - int val = INTVAL (x); - int vl, vh; - - switch (mode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - return gen_int_mode (vh, mode); - } - break; - - case SUBREG: - return simplify_gen_subreg (mode, x, GET_MODE (x), 0); - break; - - case MEM: - switch (GET_CODE (XEXP (x, 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - return change_address (x, mode, plus_constant (XEXP (x, 0), 0)); - } - break; - - default: - abort (); - } - return NULL_RTX; -} - -/* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP - or REG_FP. */ - -int -ip2k_address_uses_reg_p (rtx x, unsigned int r) -{ - if (GET_CODE (x) != MEM) - return 0; - - x = XEXP (x, 0); - - while (1) - switch (GET_CODE (x)) - { - case POST_DEC: - case POST_INC: - case PRE_DEC: - case PRE_INC: - x = XEXP (x, 0); - break; - - case PLUS: - if (ip2k_address_uses_reg_p (XEXP (x, 1), r)) - return 1; - - x = XEXP (x, 0); - break; - - case SUBREG: - /* Ignore subwords. */ - x = SUBREG_REG (x); - break; - - case REG: - /* Have to consider that r might be LSB of a pointer reg. */ - return ((REGNO (x) == r) || (REGNO (x) == (r - 1))) ? 1 : 0; - - case MEM: - /* We might be looking at a (mem:BLK (mem (...))) */ - x = XEXP (x, 0); - break; - - default: - return 0; - }; -} - -/* Does the queried XEXP not use a particular register? If we're certain - that it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz) -{ - switch (GET_CODE (x)) - { - case REG: - { - int msz = GET_MODE_SIZE (GET_MODE (x)); - - return (((REGNO (x) + msz - 1) < r) - || (REGNO (x) > (r + rsz - 1))); - } - - case MEM: - return !ip2k_address_uses_reg_p (x, r); - - case LABEL_REF: - case SYMBOL_REF: - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case CC0: - case PC: - return 1; - - default: - return 0; - } -} - -/* Does the queried XEXP not use a particular register? If we're certain - that it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_composite_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz) -{ - if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS) - return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 2), r, rsz)); - - if (BINARY_P (x)) - return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz)); - - if (UNARY_P (x) - || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY) - return ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz); - - return ip2k_xexp_not_uses_reg_p (x, r, rsz); -} - -/* Does the queried XEXP not use CC0? If we're certain that - it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_composite_xexp_not_uses_cc0_p (rtx x) -{ - if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS) - return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 2))); - - if (BINARY_P (x)) - return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1))); - - if (UNARY_P (x) - || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY) - return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)); - - return GET_CODE (x) != CC0; -} - -int -ip2k_split_dest_operand (rtx x, enum machine_mode mode) -{ - return nonimmediate_operand (x, mode) || push_operand (x, mode); -} - -int -ip2k_nonptr_operand (rtx x, enum machine_mode mode) -{ - return register_operand (x, mode) && !ip2k_ptr_operand (x, mode); -} - -/* Is X a reference to IP or DP or SP? */ - -int -ip2k_ptr_operand (rtx x, enum machine_mode mode) - -{ - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - return (REG_P (x) - && (mode == HImode || mode == VOIDmode) - && (REGNO (x) == REG_IP - || REGNO (x) == REG_DP - || REGNO (x) == REG_SP)); -} - -int -ip2k_sp_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) - -{ - return REG_P (x) && REGNO (x) == REG_SP; -} - -int -ip2k_ip_operand (rtx x, enum machine_mode mode) - -{ - if (GET_CODE (x) != MEM) - return 0; - - x = XEXP (x, 0); - - if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx) - x = XEXP (x, 0); - - if (! REG_P (x)) - return 0; - - if (GET_MODE_SIZE (mode) > 1) - return 0; /* Can't access offset bytes. */ - - return REGNO (x) == REG_IP; -} - -/* Is X a memory address suitable for SP or DP relative addressing? */ -int -ip2k_short_operand (rtx x, enum machine_mode mode) -{ - int r; - unsigned int offs = 0; - - if (! memory_operand (x, mode)) - return 0; /* Got to be a memory address. */ - - x = XEXP (x, 0); - switch (GET_CODE (x)) - { - default: - return 0; - - case PLUS: - if (! REG_P (XEXP (x, 0)) - || GET_CODE (XEXP (x, 1)) != CONST_INT) - return 0; - - offs = INTVAL (XEXP (x, 1)); - - if (128 <= offs) - return 0; - - x = XEXP (x, 0); - - /* fall through */ - - case REG: - if (IS_PSEUDO_P (x)) - return 0; /* Optimistic - doesn't work. */ - - r = REGNO (x); - - /* For 'S' constraint, we presume that no IP adjustment - simulation is performed - so only QI mode allows IP to be a - short offset address. All other IP references must be - handled by 'R' constraints. */ - if (r == REG_IP && offs == 0 && GET_MODE_SIZE (mode) <= 1) - return 1; - - return (r == REG_SP || r == REG_DP); - } -} - -int -ip2k_nonsp_reg_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - return (REG_P (x) && REGNO (x) != REG_SP); -} - -int -ip2k_gen_operand (rtx x, enum machine_mode mode) -{ - return ip2k_short_operand (x, mode) - || (GET_CODE (x) == SUBREG - && REG_P (SUBREG_REG (x))) - || (ip2k_nonsp_reg_operand (x, mode)); -} - -int -ip2k_extra_constraint (rtx x, int c) -{ - switch (c) - { - case 'S': /* Allow offset in stack frame... */ - return ip2k_short_operand (x, GET_MODE (x)); - - case 'R': - return ip2k_ip_operand (x, GET_MODE (x)); - - case 'T': /* Constant int or .data address. */ - return CONSTANT_P (x) && is_regfile_address (x); - - default: - return 0; - } -} - -int -ip2k_unary_operator (rtx op, enum machine_mode mode) -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && UNARY_P (op)); -} - -int -ip2k_binary_operator (rtx op, enum machine_mode mode) -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && ARITHMETIC_P (op)); -} - -int -ip2k_symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - /* We define an IP2k symbol ref to be either a direct reference or one - with a constant offset. */ - return (GET_CODE (op) == SYMBOL_REF) - || (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF); -} - -int -ip2k_signed_comparison_operator (rtx op, enum machine_mode mode) -{ - return (comparison_operator (op, mode) - && signed_condition (GET_CODE (op)) == GET_CODE (op)); -} - -int -ip2k_unsigned_comparison_operator (rtx op, enum machine_mode mode) -{ - return (comparison_operator (op, mode) - && unsigned_condition (GET_CODE (op)) == GET_CODE (op)); -} - -/* Worker function for TARGET_RETURN_IN_MEMORY. */ - -static bool -ip2k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) -{ - if (TYPE_MODE (type) == BLKmode) - { - HOST_WIDE_INT size = int_size_in_bytes (type); - return (size == -1 || size > 8); - } - else - return false; -} - -/* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ - -static void -ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, - tree type ATTRIBUTE_UNUSED, - int *pretend_arg_size, - int second_time ATTRIBUTE_UNUSED) -{ - *pretend_arg_size = 0; -} diff --git a/gcc/config/ip2k/ip2k.h b/gcc/config/ip2k/ip2k.h deleted file mode 100644 index 0b88e3a4e6b..00000000000 --- a/gcc/config/ip2k/ip2k.h +++ /dev/null @@ -1,851 +0,0 @@ -/* Definitions of target machine for GCC, - For Ubicom IP2022 Communications Controller - - Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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. */ - - -#undef ASM_SPEC /* We have a GAS assembler. */ - -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("IP2K"); \ - builtin_define ("_DOUBLE_IS_32BITS"); \ - builtin_define ("_BUFSIZ=512"); \ - builtin_define ("__FILENAME_MAX__=128"); \ - } \ - while (0) - -#define TARGET_VERSION fprintf (stderr, " (ip2k, GNU assembler syntax)") - -/* Caller-saves is not a win for the IP2K. Pretty much anywhere that - a register is permitted allows SP-relative addresses too. - - This machine doesn't have PIC addressing modes, so disable that also. */ - -#define OVERRIDE_OPTIONS \ - do { \ - flag_caller_saves = 0; \ - flag_pic = 0; \ - } while (0) - -/* Put each function in its own section so that PAGE-instruction - relaxation can do its best. */ -#define OPTIMIZATION_OPTIONS(LEVEL, SIZEFLAG) \ - do { \ - if ((LEVEL) || (SIZEFLAG)) \ - flag_function_sections = 1; \ - } while (0) - -#define BITS_BIG_ENDIAN 0 -#define BYTES_BIG_ENDIAN 1 -#define WORDS_BIG_ENDIAN 1 -#define BITS_PER_WORD 8 -#define UNITS_PER_WORD (BITS_PER_WORD / BITS_PER_UNIT) - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 16 - -/* Maximum sized of reasonable data type DImode or Dfmode ... */ -#define MAX_FIXED_MODE_SIZE 64 - -#define PARM_BOUNDARY 8 -#define FUNCTION_BOUNDARY 16 -#define EMPTY_FIELD_BOUNDARY 8 -#define BIGGEST_ALIGNMENT 8 - -#define STRICT_ALIGNMENT 0 - -#define PCC_BITFIELD_TYPE_MATTERS 1 - -#undef INT_TYPE_SIZE -#define INT_TYPE_SIZE 16 - -#undef SHORT_TYPE_SIZE -#define SHORT_TYPE_SIZE 16 - -#undef LONG_TYPE_SIZE -#define LONG_TYPE_SIZE 32 - -#undef LONG_LONG_TYPE_SIZE -#define LONG_LONG_TYPE_SIZE 64 - -#undef CHAR_TYPE_SIZE -#define CHAR_TYPE_SIZE 8 - -#undef FLOAT_TYPE_SIZE -#define FLOAT_TYPE_SIZE 32 - -#undef DOUBLE_TYPE_SIZE -#define DOUBLE_TYPE_SIZE 32 - -#undef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE 32 - -#define DEFAULT_SIGNED_CHAR 1 - -#define SIZE_TYPE "unsigned int" - -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "int" -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -#define HARD_REG_SIZE (UNITS_PER_WORD) -/* Standard register usage. - - for the IP2K, we are going to have a LOT of registers, but only some of them - are named. */ - -#define FIRST_PSEUDO_REGISTER (0x104) /* Skip over physical regs, VFP, AP. */ - -#define REG_IP 0x4 -#define REG_IPH REG_IP -#define REG_IPL 0x5 - -#define REG_SP 0x6 -#define REG_SPH REG_SP -#define REG_SPL 0x7 - -#define REG_PCH 0x8 -#define REG_PCL 0x9 - -#define REG_W 0xa -#define REG_STATUS 0xb - -#define REG_DP 0xc -#define REG_DPH REG_DP -#define REG_DPL 0xd - -#define REG_MULH 0xf - -#define REG_CALLH 0x7e /* Call-stack readout. */ -#define REG_CALLL 0x7f - - -#define REG_RESULT 0x80 /* Result register (upto 8 bytes). */ -#define REG_FP 0xfd /* 2 bytes for FRAME chain */ - -#define REG_ZERO 0xff /* Initialized to zero by runtime. */ - -#define REG_VFP 0x100 /* Virtual frame pointer. */ -#define REG_AP 0x102 /* Virtual arg pointer. */ - -/* Status register bits. */ -#define Z_FLAG 0x2 -#define DC_FLAG 0x1 -#define C_FLAG 0x0 - -#define FIXED_REGISTERS {\ -1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r0.. r31*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r32.. r63*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r64.. r95*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r96..r127*/\ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/*r128..r159*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r160..r191*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r192..r223*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r224..r255*/\ -1,1,1,1} - -#define CALL_USED_REGISTERS { \ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r0.. r31*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r32.. r63*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r64.. r95*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r96..r127*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r128..r159*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r160..r191*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r192..r223*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r224..r255*/\ -1,1,1,1} - -#define REG_ALLOC_ORDER { \ - 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, \ - 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, \ - 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, \ - 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, \ - 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, \ - 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, \ - 0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, \ - 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, \ - 0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, \ - 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7, \ - 0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, \ - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, \ - 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, \ - 0x00,0x01,0x02,0x03,0x0c,0x0d,0x06,0x07, \ - 0x08,0x09,0x0a,0x0b,0x04,0x05,0x0e,0x0f, \ - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, \ - 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, \ - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, \ - 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, \ - 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, \ - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, \ - 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, \ - 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, \ - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, \ - 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, \ - 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, \ - 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, \ - 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, \ - 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, \ - 0x100,0x101,0x102,0x103} - - -#define ORDER_REGS_FOR_LOCAL_ALLOC ip2k_init_local_alloc (reg_alloc_order) - -/* Are we allowed to rename registers? For some reason, regrename was - changing DP to IP (when it appeared in addresses like (plus:HI - (reg: DP) (const_int 37)) - and that's bad because IP doesn't - permit offsets! */ - -#define HARD_REGNO_RENAME_OK(REG, NREG) \ - (((REG) == REG_DPH) ? 0 \ - : ((REG) == REG_IPH) ? ((NREG) == REG_DPH) \ - : (((NREG) == REG_IPL) || ((NREG) == REG_DPL)) ? 0 : 1) - -#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 - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == QImode && (MODE2) == HImode) \ - || ((MODE2) == QImode && (MODE1) == HImode)) -/* We originally had this as follows - this isn't a win on the IP2k - though as registers just get in our way! - - #define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) > HImode && (MODE2) == HImode) - || ((MODE1) == HImode && (MODE2) > HImode)) */ - -enum reg_class { - NO_REGS, - DPH_REGS, - DPL_REGS, - DP_REGS, - SP_REGS, - IPH_REGS, - IPL_REGS, - IP_REGS, - DP_SP_REGS, - PTR_REGS, - NONPTR_REGS, - NONSP_REGS, - GENERAL_REGS, - ALL_REGS = GENERAL_REGS, - LIM_REG_CLASSES -}; - -#define N_REG_CLASSES (int)LIM_REG_CLASSES - -#define REG_CLASS_NAMES { \ - "NO_REGS", \ - "DPH_REGS", \ - "DPL_REGS", \ - "DP_REGS", \ - "SP_REGS", \ - "IPH_REGS", \ - "IPL_REGS", \ - "IP_REGS", \ - "DP_SP_REGS", \ - "PTR_REGS", \ - "NONPTR_REGS", \ - "NONSP_REGS", \ - "GENERAL_REGS" \ - } - - -#define REG_CLASS_CONTENTS { \ -{0x00000000, 0, 0, 0, 0, 0, 0, 0, 0}, /* NO_REGS */ \ -{0x00001000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DPH_REGS */ \ -{0x00002000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DPL_REGS */ \ -{0x00003000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DP_REGS */ \ -{0x000000c0, 0, 0, 0, 0, 0, 0, 0, 0}, /* SP_REGS */ \ -{0x00000010, 0, 0, 0, 0, 0, 0, 0, 0}, /* IPH_REGS */ \ -{0x00000020, 0, 0, 0, 0, 0, 0, 0, 0}, /* IPL_REGS */ \ -{0x00000030, 0, 0, 0, 0, 0, 0, 0, 0}, /* IP_REGS */ \ -{0x000030c0, 0, 0, 0, 0, 0, 0, 0, 0}, /* DP_SP_REGS */ \ -{0x000030f0, 0, 0, 0, 0, 0, 0, 0, 0}, /* PTR_REGS */ \ -{0xffffcf0f,-1,-1,-1,-1,-1,-1,-1, 0}, /* NONPTR_REGS */ \ -{0xffffff3f,-1,-1,-1,-1,-1,-1,-1, 0}, /* NONSP_REGS */ \ -{0xffffffff,-1,-1,-1,-1,-1,-1,-1,15} /* GENERAL_REGS */ \ -} - -#define REGNO_REG_CLASS(R) \ - ( (R) == REG_IPH ? IPH_REGS \ - : (R) == REG_IPL ? IPL_REGS \ - : (R) == REG_DPH ? DPH_REGS \ - : (R) == REG_DPL ? DPL_REGS \ - : (R) == REG_SPH ? SP_REGS \ - : (R) == REG_SPL ? SP_REGS \ - : NONPTR_REGS) - -#define MODE_BASE_REG_CLASS(MODE) ((MODE) == QImode ? PTR_REGS : DP_SP_REGS) - -#define BASE_REG_CLASS PTR_REGS - -#define INDEX_REG_CLASS NO_REGS - -#define REG_CLASS_FROM_LETTER(C) \ - ( (C) == 'j' ? IPH_REGS \ - : (C) == 'k' ? IPL_REGS \ - : (C) == 'f' ? IP_REGS \ - : (C) == 'y' ? DPH_REGS \ - : (C) == 'z' ? DPL_REGS \ - : (C) == 'b' ? DP_REGS \ - : (C) == 'u' ? NONSP_REGS \ - : (C) == 'q' ? SP_REGS \ - : (C) == 'c' ? DP_SP_REGS \ - : (C) == 'a' ? PTR_REGS \ - : (C) == 'd' ? NONPTR_REGS \ - : NO_REGS) - -#define REGNO_OK_FOR_BASE_P(R) \ - ((R) == REG_DP || (R) == REG_IP || (R) == REG_SP) - -#define REGNO_MODE_OK_FOR_BASE_P(R,M) \ - ((R) == REG_DP || (R) == REG_SP \ - || ((R) == REG_IP && GET_MODE_SIZE (M) <= 1)) - -#define REGNO_OK_FOR_INDEX_P(NUM) 0 - -#define PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS) - -#define SMALL_REGISTER_CLASSES 1 - -#define CLASS_LIKELY_SPILLED_P(CLASS) class_likely_spilled_p(CLASS) - -#define CLASS_MAX_NREGS(CLASS, MODE) GET_MODE_SIZE (MODE) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (VALUE) >= -255 && (VALUE) <= -1 : \ - (C) == 'J' ? (VALUE) >= 0 && (VALUE) <= 7 : \ - (C) == 'K' ? (VALUE) >= 0 && (VALUE) <= 127 : \ - (C) == 'L' ? (VALUE) > 0 && (VALUE) < 128: \ - (C) == 'M' ? (VALUE) == -1: \ - (C) == 'N' ? (VALUE) == 1: \ - (C) == 'O' ? (VALUE) == 0: \ - (C) == 'P' ? (VALUE) >= 0 && (VALUE) <= 255: \ - 0) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 - -#define EXTRA_CONSTRAINT(X, C) ip2k_extra_constraint (X, C) - -/* This is an undocumented variable which describes - how GCC will pop a data. */ -#define STACK_POP_CODE PRE_INC - -#define STACK_PUSH_CODE POST_DEC - -#define STACK_CHECK_BUILTIN 1 -/* Prologue code will do stack checking as necessary. */ - -#define STARTING_FRAME_OFFSET (0) - -#define FRAME_GROWS_DOWNWARD 1 -#define STACK_GROWS_DOWNWARD 1 - -/* On IP2K arg pointer is virtual and resolves to either SP or FP - after we've resolved what registers are saved (fp chain, return - pc, etc. */ - -#define FIRST_PARM_OFFSET(FUNDECL) 0 - -#define STACK_POINTER_OFFSET 1 -/* IP2K stack is post-decremented, so 0(sp) is address of open space - and 1(sp) is offset to the location avobe the forst location at which - outgoing arguments are placed. */ - -#define STACK_BOUNDARY 8 - -#define STACK_POINTER_REGNUM REG_SP - -#define FRAME_POINTER_REGNUM REG_VFP -#define HARD_FRAME_POINTER_REGNUM REG_FP - -#define ARG_POINTER_REGNUM REG_AP - -/* We don't really want to support nested functions. But we'll crash - in various testsuite tests if we don't at least define the register - to contain the static chain. The return value register is about as - bad a place as any for this. */ - -#define STATIC_CHAIN_REGNUM REG_RESULT - -#define FRAME_POINTER_REQUIRED (!flag_omit_frame_pointer) - -#define ELIMINABLE_REGS { \ - {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - {HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -} - -#define CAN_ELIMINATE(FROM, TO) \ - ((FROM) == HARD_FRAME_POINTER_REGNUM \ - ? (flag_omit_frame_pointer && !frame_pointer_needed) : 1) -/* Don't eliminate FP unless we EXPLICITLY_ASKED */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - ((OFFSET) = ip2k_init_elim_offset ((FROM), (TO))) - -#define RETURN_ADDR_RTX(COUNT, X) \ - (((COUNT) == 0) ? gen_rtx_REG (HImode, REG_CALLH) : NULL_RTX) - -#define PUSH_ROUNDING(NPUSHED) (NPUSHED) - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - ip2k_return_pops_args ((FUNDECL), (FUNTYPE), (SIZE)) - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 - -#define CUMULATIVE_ARGS int - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - ((CUM) = 0) - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) - -/* All arguments are passed on stack - do nothing here. */ - -#define FUNCTION_ARG_REGNO_P(R) 0 - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - ((TYPE_MODE (VALTYPE) == QImode) \ - ? gen_rtx_REG (TYPE_MODE (VALTYPE), REG_RESULT + 1) \ - : gen_rtx_REG (TYPE_MODE (VALTYPE), REG_RESULT)) - -/* Because functions returning 'char' actually widen to 'int', we have to - use $81 as the return location if we think we only have a 'char'. */ - -#define LIBCALL_VALUE(MODE) gen_rtx_REG ((MODE), REG_RESULT) - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == REG_RESULT) - -#define DEFAULT_PCC_STRUCT_RETURN 0 - -#define EPILOGUE_USES(REGNO) 0 - - -/* Hmmm. We don't actually like constants as addresses - they always need - to be loaded to a register, except for function calls which take an - address by immediate value. But changing this to zero had negative - effects, causing the compiler to get very confused.... */ - -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -#define MAX_REGS_PER_ADDRESS 1 - -#ifdef REG_OK_STRICT -# define GO_IF_LEGITIMATE_ADDRESS(MODE, OPERAND, ADDR) \ -{ \ - if (legitimate_address_p ((MODE), (OPERAND), 1)) \ - goto ADDR; \ -} -#else -# define GO_IF_LEGITIMATE_ADDRESS(MODE, OPERAND, ADDR) \ -{ \ - if (legitimate_address_p ((MODE), (OPERAND), 0)) \ - goto ADDR; \ -} -#endif - -#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#define REG_OK_FOR_BASE_NOSTRICT_P(X) \ - (REGNO (X) >= FIRST_PSEUDO_REGISTER \ - || (REGNO (X) == REG_FP) \ - || (REGNO (X) == REG_VFP) \ - || (REGNO (X) == REG_AP) \ - || REG_OK_FOR_BASE_STRICT_P(X)) - -#ifdef REG_OK_STRICT -# define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X) -#else -# define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NOSTRICT_P (X) -#endif - -#define REG_OK_FOR_INDEX_P(X) 0 - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -do { rtx orig_x = (X); \ - (X) = legitimize_address ((X), (OLDX), (MODE), 0); \ - if ((X) != orig_x && memory_address_p ((MODE), (X))) \ - goto WIN; \ -} while (0) - -/* Is X a legitimate register to reload, or is it a pseudo stack-temp - that is problematic for push_reload() ? */ - -#define LRA_REG(X) \ - (! (reg_equiv_memory_loc[REGNO (X)] \ - && (reg_equiv_address[REGNO (X)] \ - || num_not_at_initial_offset))) - -/* Given a register X that failed the LRA_REG test, replace X - by its memory equivalent, find the reloads needed for THAT memory - location and substitute that back for the higher-level reload - that we're conducting... */ - -/* WARNING: we reference 'ind_levels' and 'insn' which are local variables - in find_reloads_address (), where the LEGITIMIZE_RELOAD_ADDRESS macro - expands. */ - -#define FRA_REG(X,MODE,OPNUM,TYPE) \ -do { \ - rtx tem = make_memloc ((X), REGNO (X)); \ - \ - if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0))) \ - { \ - /* Note that we're doing address in address - cf. ADDR_TYPE */ \ - find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), \ - &XEXP (tem, 0), (OPNUM), \ - ADDR_TYPE (TYPE), ind_levels, insn); \ - } \ - (X) = tem; \ -} while (0) - - -/* For the IP2K, we want to be clever about picking IP vs DP for a - base pointer since IP only directly supports a zero displacement. - (Note that we have modified all the HI patterns to correctly handle - IP references by manipulating iph:ipl as we fetch the pieces). */ -#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND,WIN) \ -{ \ - if (GET_CODE (X) == PLUS \ - && REG_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - int disp = INTVAL (XEXP (X, 1)); \ - int fit = (disp >= 0 && disp <= (127 - 2 * GET_MODE_SIZE (MODE))); \ - rtx reg = XEXP (X, 0); \ - if (!fit) \ - { \ - push_reload ((X), NULL_RTX, &(X), \ - NULL, MODE_BASE_REG_CLASS (MODE), GET_MODE (X), \ - VOIDmode, 0, 0, OPNUM, TYPE); \ - goto WIN; \ - } \ - if (reg_equiv_memory_loc[REGNO (reg)] \ - && (reg_equiv_address[REGNO (reg)] || num_not_at_initial_offset)) \ - { \ - rtx mem = make_memloc (reg, REGNO (reg)); \ - if (! strict_memory_address_p (GET_MODE (mem), XEXP (mem, 0))) \ - { \ - /* Note that we're doing address in address - cf. ADDR_TYPE */\ - find_reloads_address (GET_MODE (mem), &mem, XEXP (mem, 0), \ - &XEXP (mem, 0), (OPNUM), \ - ADDR_TYPE (TYPE), (IND), insn); \ - } \ - push_reload (mem, NULL, &XEXP (X, 0), NULL, \ - GENERAL_REGS, Pmode, VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - push_reload (X, NULL, &X, NULL, \ - MODE_BASE_REG_CLASS (MODE), GET_MODE (X), VOIDmode, \ - 0, 0, OPNUM, TYPE); \ - goto WIN; \ - } \ - } \ -} - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ - do { \ - if (ip2k_mode_dependent_address (ADDR)) goto LABEL; \ - } while (0) - -#define LEGITIMATE_CONSTANT_P(X) 1 - -#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) 7 - -#define MEMORY_MOVE_COST(MODE,CLASS,IN) 6 - -#define SLOW_BYTE_ACCESS 0 - -#define NO_FUNCTION_CSE - -#define TEXT_SECTION_ASM_OP ".text" -#define DATA_SECTION_ASM_OP ".data" - -#define JUMP_TABLES_IN_TEXT_SECTION 1 - -#define ASM_COMMENT_START " ; " - -#define ASM_APP_ON "/* #APP */\n" - -#define ASM_APP_OFF "/* #NOAPP */\n" - -#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \ - fprintf ((STREAM), ".double %.20e\n", (VALUE)) -#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ - asm_output_float ((STREAM), (VALUE)) - -#define ASM_OUTPUT_INT(FILE, VALUE) \ - ( fprintf ((FILE), "\t.long "), \ - output_addr_const ((FILE), (VALUE)), \ - fputs ("\n", (FILE))) - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ - asm_output_short ((FILE), (VALUE)) -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ - asm_output_char ((FILE), (VALUE)) - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - asm_output_byte ((FILE), (VALUE)) - -#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) \ - ((C) == '\n' || ((C) == '$')) - -#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.comm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%d\n", (int)(SIZE)); \ -} while (0) - -#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.lcomm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%d\n", (int)(SIZE)); \ -} while (0) - -#undef WEAK_ASM_OP -#define WEAK_ASM_OP ".weak" - -#undef ASM_DECLARE_FUNCTION_SIZE -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \ - } while (0) - -#define ESCAPES \ -"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ -\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ -\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ -\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ -\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ -\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" -/* A table of bytes codes used by the ASM_OUTPUT_ASCII and - ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table - corresponds to a particular byte value [0..255]. For any - given byte value, if the value in the corresponding table - position is zero, the given character can be output directly. - If the table value is 1, the byte must be output as a \ooo - octal escape. If the tables value is anything else, then the - byte value should be output as a \ followed by the value - in the table. Note that we can use standard UN*X escape - sequences for many control characters, but we don't use - \a to represent BEL because some svr4 assemblers (e.g. on - the i386) don't know about that. Also, we don't use \v - since some versions of gas, such as 2.2 did not accept it. */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP ".global\t" - -#define REGISTER_NAMES { \ - "$00","$01","$02","$03","iph","ipl","sph","spl", \ - "pch","pcl","wreg","status","dph","dpl","$0e","mulh", \ - "$10","$11","$12","$13","$14","$15","$16","$17", \ - "$18","$19","$1a","$1b","$1c","$1d","$1e","$1f", \ - "$20","$21","$22","$23","$24","$25","$26","$27", \ - "$28","$29","$2a","$2b","$2c","$2d","$2e","$2f", \ - "$30","$31","$32","$33","$34","$35","$36","$37", \ - "$38","$39","$3a","$3b","$3c","$3d","$3e","$3f", \ - "$40","$41","$42","$43","$44","$45","$46","$47", \ - "$48","$49","$4a","$4b","$4c","$4d","$4e","$4f", \ - "$50","$51","$52","$53","$54","$55","$56","$57", \ - "$58","$59","$5a","$5b","$5c","$5d","$5e","$5f", \ - "$60","$61","$62","$63","$64","$65","$66","$67", \ - "$68","$69","$6a","$6b","$6c","$6d","$6e","$6f", \ - "$70","$71","$72","$73","$74","$75","$76","$77", \ - "$78","$79","$7a","$7b","$7c","$7d","callh","calll", \ - "$80","$81","$82","$83","$84","$85","$86","$87", \ - "$88","$89","$8a","$8b","$8c","$8d","$8e","$8f", \ - "$90","$91","$92","$93","$94","$95","$96","$97", \ - "$98","$99","$9a","$9b","$9c","$9d","$9e","$9f", \ - "$a0","$a1","$a2","$a3","$a4","$a5","$a6","$a7", \ - "$a8","$a9","$aa","$ab","$ac","$ad","$ae","$af", \ - "$b0","$b1","$b2","$b3","$b4","$b5","$b6","$b7", \ - "$b8","$b9","$ba","$bb","$bc","$bd","$be","$bf", \ - "$c0","$c1","$c2","$c3","$c4","$c5","$c6","$c7", \ - "$c8","$c9","$ca","$cb","$cc","$cd","$ce","$cf", \ - "$d0","$d1","$d2","$d3","$d4","$d5","$d6","$d7", \ - "$d8","$d9","$da","$db","$dc","$dd","$de","$df", \ - "$e0","$e1","$e2","$e3","$e4","$e5","$e6","$e7", \ - "$e8","$e9","$ea","$eb","$ec","$ed","$ee","$ef", \ - "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7", \ - "$f8","$f9","$fa","$fb","$fc","$fd","$fe","$ff", \ - "vfph","vfpl","vaph","vapl"} - -#define PRINT_OPERAND(STREAM, X, CODE) \ - print_operand ((STREAM), (X), (CODE)) - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - ((CODE) == '<' || (CODE) == '>') - -#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X) - -/* Since register names don't have a prefix, we must preface all - user identifiers with the '_' to prevent confusion. */ - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" -#define LOCAL_LABEL_PREFIX ".L" - -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ - asm_fprintf ((STREAM), "\tpage\t%L%d\n\tjmp\t%L%d\n", (VALUE), (VALUE)) - -/* elfos.h presumes that we will want switch/case dispatch tables aligned. - This is not so for the ip2k. */ -#undef ASM_OUTPUT_CASE_LABEL - -#undef ASM_OUTPUT_ADDR_VEC_ELT -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - asm_fprintf ((STREAM), "\tpage\t%L%d\n\tjmp\t%L%d\n", (VALUE), (VALUE)) - -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ - fprintf ((STREAM), "\t.align %d\n", (POWER)) - -/* Since instructions are 16 bit word addresses, we should lie and claim that - the dispatch vectors are in QImode. Otherwise the offset into the jump - table will be scaled by the MODE_SIZE. */ - -#define CASE_VECTOR_MODE QImode - -#undef WORD_REGISTER_OPERATIONS - -#define MOVE_MAX 1 - -#define MOVE_RATIO 3 -/* MOVE_RATIO is the number of move instructions that is better than a - block move. Make this small on the IP2k, since the code size grows very - large with each move. */ - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -#define Pmode HImode - -#define FUNCTION_MODE HImode - -#define DOLLARS_IN_IDENTIFIERS 0 - -extern int ip2k_reorg_in_progress; -/* Flag if we're in the middle of IP2k-specific reorganization. */ - -extern int ip2k_reorg_completed; -/* Flag if we've completed our IP2k-specific reorganization. If we have - then we allow quite a few more tricks than before. */ - -extern int ip2k_reorg_split_dimode; -extern int ip2k_reorg_split_simode; -extern int ip2k_reorg_split_qimode; -extern int ip2k_reorg_split_himode; -/* Flags for various split operations that we run in sequence. */ - -extern int ip2k_reorg_merge_qimode; -/* Flag to indicate that it's safe to merge QImode operands. */ - -#define TRAMPOLINE_TEMPLATE(FILE) abort () - -#define TRAMPOLINE_SIZE 4 - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant ((TRAMP), 2)), \ - CXT); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant ((TRAMP), 6)), \ - FNADDR); \ -} -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) (void)(0) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf ((FILE), "/* profiler %d */", (LABELNO)) - -#undef ENDFILE_SPEC -#undef LINK_SPEC -#undef STARTFILE_SPEC - -#if defined(__STDC__) || defined(ALMOST_STDC) -#define AS2(a,b,c) #a "\t" #b "," #c -#define AS1(a,b) #a "\t" #b -#else -#define AS1(a,b) "a b" -#define AS2(a,b,c) "a b,c" -#endif -#define OUT_AS1(a,b) output_asm_insn (AS1 (a,b), operands) -#define OUT_AS2(a,b,c) output_asm_insn (AS2 (a,b,c), operands) -#define CR_TAB "\n\t" - -#define PREDICATE_CODES \ - {"ip2k_ip_operand", {MEM}}, \ - {"ip2k_short_operand", {MEM}}, \ - {"ip2k_gen_operand", {MEM, REG, SUBREG}}, \ - {"ip2k_nonptr_operand", {REG, SUBREG}}, \ - {"ip2k_ptr_operand", {REG, SUBREG}}, \ - {"ip2k_split_dest_operand", {REG, SUBREG, MEM}}, \ - {"ip2k_sp_operand", {REG}}, \ - {"ip2k_nonsp_reg_operand", {REG, SUBREG}}, \ - {"ip2k_symbol_ref_operand", {SYMBOL_REF}}, \ - {"ip2k_binary_operator", {PLUS, MINUS, MULT, DIV, \ - UDIV, MOD, UMOD, AND, IOR, \ - XOR, COMPARE, ASHIFT, \ - ASHIFTRT, LSHIFTRT}}, \ - {"ip2k_unary_operator", {NEG, NOT, SIGN_EXTEND, \ - ZERO_EXTEND}}, \ - {"ip2k_unsigned_comparison_operator", {LTU, GTU, NE, \ - EQ, LEU, GEU}},\ - {"ip2k_signed_comparison_operator", {LT, GT, LE, GE}}, - -#define DWARF2_DEBUGGING_INFO 1 - -#define DWARF2_ASM_LINE_DEBUG_INFO 1 - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Miscellaneous macros to describe machine specifics. */ - -#define IS_PSEUDO_P(R) (REGNO (R) >= FIRST_PSEUDO_REGISTER) - -/* Default calculations would cause DWARF address sizes to be 2 bytes, - but the Harvard architecture of the IP2k and the word-addressed 64k - of instruction memory causes us to want a 32-bit "address" field. */ -#undef DWARF2_ADDR_SIZE -#define DWARF2_ADDR_SIZE 4 - diff --git a/gcc/config/ip2k/ip2k.md b/gcc/config/ip2k/ip2k.md deleted file mode 100644 index b79a8ffcb4d..00000000000 --- a/gcc/config/ip2k/ip2k.md +++ /dev/null @@ -1,6903 +0,0 @@ -;; -*- Mode: Scheme -*- -;; GCC machine description for Ubicom IP2022 Communications Controller. -;; Copyright (C) 2000, 2001, 2002, 2004 -;; Free Software Foundation, Inc. -;; Contributed by Red Hat, Inc and Ubicom, 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. */ - -;; Default all instruction lengths to two bytes (one 16-bit instruction). -;; -(define_attr "length" "" (const_int 2)) - -;; Define if we can "skip" an insn or not -(define_attr "skip" "no,yes" (const_string "no")) - -;; Define an insn clobbers WREG or not -(define_attr "clobberw" "no,yes" (const_string "yes")) - -;; Performance Issues: -;; -;; With the IP2k only having one really useful pointer register we have to -;; make most of our instruction patterns only match one offsettable address -;; before addressing becomes strict whereas afterwards of course we can use -;; any register details that have become fixed. As we've already committed -;; any reloads at this point of course we're a little late so we have to use -;; a number of peephole2 optimizations to remerge viable patterns. We can -;; do a bit more tidying up in the machine-dependent reorg pass to try and -;; make things better still. None of this is ideal, but it's *much* better -;; than nothing. - -;; Constraints: -;; -;; I - -255..-1 - all other literal values have to be loaded -;; J - 0..7 - valid bit number in a register -;; K - 0..127 - valid offset for addressing mode -;; L - 1..127 - positive count suitable for shift. -;; M - -1 as a literal value -;; N - +1 as a literal value -;; O - zero -;; P - 0..255 -;; -;; a - DP or IP registers (general address) -;; f - IP register -;; j - IPL register -;; k - IPH register -;; b - DP register -;; y - DPH register -;; z - DPL register -;; q - SP register -;; c - DP or SP registers (offsettable address) -;; d - non-pointer registers (not SP, DP, IP) -;; u - non-SP registers (everything except SP) -;; -;; R - Indirect through IP - Avoid this except for QI mode, since we -;; can't access extra bytes. -;; S - Short (stack/dp address). Pointer with 0..127 displacement -;; Note that 0(SP) has undefined contents due to post-decrement push -;; T - data-section immediate value. A CONST_INT or SYMBOL_REF into .data - -;; Special assembly-language format effectors: -;; -;; ABCD - -;; Reference up to 4 big-endian registers - %A0 is Rn+0, while %D0 is Rn+3 -;; STUVWXYZ - -;; Reference up to 8 big-endian registers - %S0 is Rn+0, while %Z0 is Rn+7 -;; -;; H - High part of 16 bit address or literal %hi8data(v) or %hi8insn(v) -;; L - Low part of 16 bit address or literal %lo8data(v) or %lo8insn(v) -;; b - print a literal value with no punctuation (typically bit selector) -;; e - print 1 << v ('exponent') -;; n - print negative number -;; x - print 16 bit hex number -;; < - interior stack push; adjust any stack-relative operands accordingly -;; > - interior stack pop; clear adjustment. - -;; -;; Basic operations to move data in and out of fr's. Also extended to -;; cover the loading of w with immediates -;; - -(define_insn "*movqi_w_gen" - [(set (reg:QI 10) - (match_operand:QI 0 "general_operand" "rSi"))] - "(ip2k_reorg_split_qimode)" - "mov\\tw,%0" - [(set_attr "skip" "yes")]) - -(define_insn "*movqi_fr_w" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS") - (reg:QI 10))] - "(ip2k_reorg_split_qimode)" - "mov\\t%0,w" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - - -;; Handle the cases where we get back to back redundant mov patterns issued. -;; This of course sounds somewhat absurd but is actually reasonably common -;; because we aren't able to match certain patterns before registers are -;; chosen. This is particularly true of memory to memory operations where -;; we can't provide patterns that will guarantee to match every time because -;; this would require reloads in the middle of instructions. If we -;; discover a case that doesn't need a reload of course then this combiner -;; operation will tidy up for us. -;; -;; Warning! Whilst it would be nice to match operand 0 as a general operand -;; we mustn't do so because this doesn't work with the REG_DEAD check. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "ip2k_gen_operand" "")) - (set (match_operand 2 "ip2k_split_dest_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) - && (REG_P (operands[2]) - || ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0])))))" - [(set (match_dup 2) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "immediate_operand" "")) - (set (match_operand 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_dup 1))] - "") - -;; -;; Move 8-bit integers. -;; - -(define_expand "movqi" - [(set (match_operand:QI 0 "" "") - (match_operand:QI 1 "" ""))] - "" - "") - -(define_insn "*pushqi" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "general_operand" "g"))] - "" - "push\\t%1" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -;; IP isn't offsettable but we can fake this behavior here and win if we would -;; otherwise use DP and require a reload from IP. This instruction is only -;; matched by peephole2 operations. -;; -(define_insn "*movqi_to_ip_plus_offs" - [(set (mem:QI (plus:HI (reg:HI 4) - (match_operand 0 "const_int_operand" "P,P"))) - (match_operand:QI 1 "general_operand" "O,g"))] - "reload_completed && (INTVAL (operands[0]) < 0x100)" - "*{ - if (INTVAL (operands[0]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %0); - OUT_AS2 (add, ipl, w); - } - - switch (which_alternative) - { - case 0: - OUT_AS1 (clr, (IP)); - break; - - case 1: - OUT_AS1 (push, %1%<); - OUT_AS1 (pop, (IP)%>); - break; - } - - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[0]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - }") - -;; IP isn't offsettable but we can fake this behavior here and win if we would -;; otherwise use DP and require a reload from IP. This instruction is only -;; matched by peephole2 operations. -;; -(define_insn "*movqi_from_ip_plus_offs" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (mem:QI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "P"))))] - "reload_completed && (INTVAL (operands[1]) < 0x100)" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %0%>); - if (!find_regno_note (insn, REG_DEAD, REG_IP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_IP, 2)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - }") - -(define_insn_and_split "*movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,roR,r, rS,roR") - (match_operand:QI 1 "general_operand" " O, ri,o,rioR,rSi"))] - "" - "@ - clr\\t%0 - # - # - # - #" - "(ip2k_reorg_split_qimode - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0))" - [(set (reg:QI 10) (match_dup 1)) - (set (match_dup 0) (reg:QI 10))] - "" - [(set_attr "skip" "yes,no,no,no,no") - (set_attr "clobberw" "no,yes,yes,yes,yes")]) - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:QI 0 "nonimmediate_operand" "") - (mem:QI (plus:HI (reg:HI 12) - (match_operand 1 "const_int_operand" ""))))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 0) - (mem:QI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (mem:QI (plus:HI (reg:HI 12) - (match_operand 0 "const_int_operand" ""))) - (match_operand:QI 1 "general_operand" ""))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && (INTVAL (operands[0]) < 0x100))" - [(set (mem:QI (plus:HI (reg:HI 4) - (match_dup 0))) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (mem:QI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "")))) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 2) - (mem:QI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn_and_split "*movqi_twice" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (match_operand:QI 1 "general_operand" "g")) - (set (match_operand:QI 2 "nonimmediate_operand" "=g") - (match_dup 1))] - "ip2k_reorg_merge_qimode" - "mov\\tw,%1\;mov\\t%0,w\;mov\\t%2,w" - "(ip2k_reorg_split_qimode)" - [(set (reg:QI 10) (match_dup 1)) - (set (match_dup 0) (reg:QI 10)) - (set (match_dup 2) (reg:QI 10))] - "") - -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 0))] - "(ip2k_reorg_merge_qimode - && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 1))] - "(ip2k_reorg_merge_qimode - && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 16-bit integers. -;; - -(define_expand "movhi" - [(set (match_operand:HI 0 "" "") - (match_operand:HI 1 "" ""))] - "" - "") - -(define_insn "*pushhi_ip" - [(set (match_operand:HI 0 "push_operand" "=<") - (mem:HI (reg:HI 4)))] - "reload_completed" - "inc\\tipl\;push\\t(IP)\;dec\\tipl\;push\\t(IP)" - [(set_attr "clobberw" "no")]) - -(define_insn "*movhi_to_ip" - [(set (mem:HI (reg:HI 4)) - (match_operand:HI 0 "general_operand" "O,roi"))] - "reload_completed" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (clr, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS1 (clr, (IP)); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - - case 1: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (mov, (IP), w); - OUT_AS2 (mov, w, %L0); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, (IP), w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - default: - abort (); - } - }") - -(define_insn "*movhi_from_ip" - [(set (match_operand:HI 0 "nonimmediate_operand" "=f,bqdo") - (mem:HI (reg:HI 4)))] - "reload_completed" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - return \"\"; - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - default: - abort (); - } - }") - -(define_insn "*movhi_from_ip_plus_offs" - [(set (match_operand:HI 0 "nonimmediate_operand" "=f,bqdo") - (mem:HI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "P, P"))))] - "reload_completed && (INTVAL (operands[1]) < 0x100)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - return \"\"; - - case 1: - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %H0%>); - OUT_AS1 (inc, ipl); - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %L0%>); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - { - OUT_AS1 (dec, ipl); - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - default: - abort (); - } - }") - -(define_insn_and_split "*movhi" - [(set - (match_operand:HI 0 "ip2k_split_dest_operand" "=<,<,uo,b, uS,uo,uo, q,u") - (match_operand:HI 1 "general_operand" "ron,i, n,T,uoi,uS,ui,ui,q"))] - "" - "@ - push\\t%L1%<\;push\\t%H1%> - push\\t%L1%<\;push\\t%H1%> - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w - loadl\\t%x1\;loadh\\t%x1 - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w" - "(ip2k_reorg_split_himode - && (GET_CODE (operands[1]) == CONST_INT - || (push_operand (operands[0], HImode) - && GET_CODE (operands[1]) == REG) - || (register_operand (operands[0], HImode) - && REGNO (operands[0]) >= 0x80 - && ip2k_gen_operand (operands[1], HImode))))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (QImode, HImode, operands); /* Split into 2=3,4=5 */ - }" - [(set_attr "clobberw" "no,no,yes,no,yes,yes,yes,yes,yes")]) - -;; We don't generally use IP for HImode indirections because it's not -;; offsettable, however if we're accessing something that's already pointed -;; to by IP and would otherwise require a reload of DP then we can win by -;; simulating HImode accesses via IP instead. - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (mem:HI (reg:HI 12)) - (match_operand:HI 0 "general_operand" ""))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (2, REG_DP))" - [(set (mem:HI (reg:HI 4)) - (match_dup 0))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:HI 0 "nonimmediate_operand" "") - (mem:HI (reg:HI 12)))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (2, REG_DP))" - [(set (match_dup 0) - (mem:HI (reg:HI 4)))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:HI 0 "nonimmediate_operand" "") - (mem:HI (plus:HI (reg:HI 12) - (match_operand 1 "const_int_operand" ""))))] - ; - ; We only match here if IP and DP both go dead because emulating - ; offsets in conjunction with IP doesn't win unless IP goes - ; dead too. - ; - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && peep2_regno_dead_p (2, REG_IP) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 0) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (reg:HI 4) - (mem:HI (plus:HI (reg:HI 12) - (match_operand 0 "const_int_operand" ""))))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && (INTVAL (operands[0]) < 0x100))" - [(set (reg:HI 4) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 0))))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (reg:HI 4))) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 2) - (mem:HI (reg:HI 4)))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "")))) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 2) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:HI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (reg:HI 4)) - (set (mem:HI (reg:HI 12)) - (match_dup 0))] - "(peep2_reg_dead_p (3, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (3, REG_DP))" - [(set (mem:HI (reg:HI 4)) - (match_dup 1))] - "") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn "*movhi_twice" - [(set (match_operand:HI 0 "ip2k_gen_operand" "=&uS,uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS,uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=&uS,uS") - (match_dup 1))] - "ip2k_reorg_split_simode" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, %L2, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, %H2, w); - - case 1: - return AS2 (mov, w, %L1) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (pop, %H0%>) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (pop, %H2%>) CR_TAB - AS2 (mov, %L2, w); - default: - abort (); - } - }") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_gen_operand" "") - (match_operand:HI 1 "ip2k_gen_operand" "")) - (set (match_operand:HI 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_simode)" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_gen_operand" "") - (match_operand:HI 1 "ip2k_gen_operand" "")) - (set (match_operand:HI 2 "ip2k_gen_operand" "") - (match_dup 1))] - "(ip2k_reorg_split_simode - && (!REG_P (operands[0]) - || ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 32-bit integers. -;; - -(define_expand "movsi" - [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" ""))] - "" - "") - -(define_insn_and_split "*movsi" - [(set (match_operand:SI 0 "ip2k_split_dest_operand" "=<, ro, S") - (match_operand:SI 1 "general_operand" "roSi,rSi,roi"))] - "" - "#" - "ip2k_reorg_split_simode" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (HImode, SImode, operands); /* Split into 2=3,4=5 */ - }") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn "*movsi_twice" - [(set (match_operand:SI 0 "ip2k_gen_operand" "=&uS,uS") - (match_operand:SI 1 "ip2k_gen_operand" "uS,uS")) - (set (match_operand:SI 2 "ip2k_gen_operand" "=&uS,uS") - (match_dup 1))] - "ip2k_reorg_split_dimode" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, %A2, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %B2, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %C2, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %D2, w); - - case 1: - return AS2 (mov, w, %D1) CR_TAB - AS1 (push, %C1%<) CR_TAB - AS1 (push, %B1%<) CR_TAB - AS1 (push, %A1%<) CR_TAB - AS1 (push, %C1%<) CR_TAB - AS1 (push, %B1%<) CR_TAB - AS1 (push, %A1%<) CR_TAB - AS1 (pop, %A0%>) CR_TAB - AS1 (pop, %B0%>) CR_TAB - AS1 (pop, %C0%>) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (pop, %A2%>) CR_TAB - AS1 (pop, %B2%>) CR_TAB - AS1 (pop, %C2%>) CR_TAB - AS2 (mov, %D2, w); - default: - abort (); - } - }") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_gen_operand" "") - (match_operand:SI 1 "ip2k_gen_operand" "")) - (set (match_operand:SI 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_dimode - && (!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), 4))) - && (!REG_P (operands[1]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[1]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[1]), 4))) - && (!REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 4) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 4))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_gen_operand" "") - (match_operand:SI 1 "ip2k_gen_operand" "")) - (set (match_operand:SI 2 "ip2k_gen_operand" "") - (match_dup 1))] - "(ip2k_reorg_split_dimode - && (!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), 4))) - && (!REG_P (operands[1]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[1]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[1]), 4))) - && (!REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 4) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 4))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 64-bit integers. -;; - -(define_expand "movdi" - [(set (match_operand:DI 0 "" "") - (match_operand:DI 1 "" ""))] - "" - "") - -(define_insn_and_split "*movdi" - [(set (match_operand:DI 0 "ip2k_split_dest_operand" "=<, ro, S") - (match_operand:DI 1 "general_operand" "roSi,rSi,roi"))] - "" - "#" - "ip2k_reorg_split_dimode" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (SImode, DImode, operands); /* Split into 2=3,4=5 */ - }") - -;; -;; Move 32-bit floating point values. -;; - -(define_expand "movsf" - [(set (match_operand:SF 0 "" "") - (match_operand:SF 1 "" ""))] - "" - "if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); - ") - -(define_insn_and_split "*movsf" - [(set (match_operand:SF 0 "ip2k_split_dest_operand" "=r<, o") - (match_operand:SF 1 "general_operand" "roi,ri"))] - "(ip2k_short_operand (operands[0], SFmode) - && ip2k_short_operand (operands[1], SFmode)) - || ! (memory_operand (operands[0], SFmode) - && memory_operand (operands[1], SFmode))" - "#" - "(reload_completed || reload_in_progress)" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5)) - (set (match_dup 6) (match_dup 7)) - (set (match_dup 8) (match_dup 9))] - "{ - /* Split into 2=3,4=5 */ - ip2k_split_words (HImode, SImode, operands); - /* Split 4=5 into 6=7,8=9 */ - ip2k_split_words (QImode, HImode, &operands[4]); - operands[0] = operands[2]; - operands[1] = operands[3]; - ip2k_split_words (QImode, HImode, operands); - }") - -;; -;; Move 64-bit floating point values. -;; - -;; -;; Block move operations. -;; - -;; Copy a block of bytes (memcpy()). We expand the definition to convert -;; our memory operand into a register pointer operand instead. -;; -(define_expand "movmemhi" - [(use (match_operand:BLK 0 "memory_operand" "")) - (use (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:HI 2 "general_operand" "")) - (use (match_operand 3 "const_int_operand" ""))] - "" - "{ - rtx addr0, addr1, count; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - if (GET_CODE (operands[2]) == CONST_INT) - count = gen_int_mode (INTVAL (operands[2]) & 0xffff, HImode); - else - count = operands[2]; - - emit_insn (gen_movmemhi_expanded (addr0, count, addr1)); - DONE; - }") - -;; Block copy instruction. We handle this by calling one of two functions in -;; libgcc. The first of these is a special case (faster) routine that handles -;; constant block sizes under 256 bytes. This one is particularly common -;; because we use it when copying data structures. The second routine handles -;; the general case where we have either a variable block size or one that is -;; greater than 255 bytes. -;; -(define_insn "movmemhi_expanded" - [(set - (mem:BLK - (match_operand:HI 0 "nonimmediate_operand" "rS,ro,rS, rS, ro, rS")) - (mem:BLK - (match_operand:HI 2 "nonimmediate_operand" "ro,rS,rS, ro, rS, rS"))) - (use - (match_operand:HI 1 "general_operand" "P, P, P,rSi,rSi,roi"))] - "" - "@ - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movmemhi_countqi\;call\\t__movmemhi_countqi - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movmemhi_countqi\;call\\t__movmemhi_countqi - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movmemhi_countqi\;call\\t__movmemhi_countqi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movmemhi_counthi\;call\\t__movmemhi_counthi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movmemhi_counthi\;call\\t__movmemhi_counthi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movmemhi_counthi\;call\\t__movmemhi_counthi") - - -;; Bit insert -;; -(define_expand "insv" - [(set (zero_extract:QI (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand 1 "immediate_operand" "") ;size - (match_operand 2 "immediate_operand" "")) ;pos - (match_operand:QI 3 "general_operand" ""))] - "" - "{ - if (! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J') - || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) - FAIL; - }") - -(define_insn "*insv" - [(set (zero_extract:QI - (match_operand:QI - 0 "nonimmediate_operand" "+roR,roR,roR,roR,&roR,&roR,&r") - (match_operand - 1 "immediate_operand" "N, N, J, J, N, J, J") ;sz - (match_operand - 2 "immediate_operand" "J, J, J, J, J, J, J"));pos - (match_operand:QI - 3 "general_operand" "MN, O, M, O, roR, rn,oR"))] - "" - "*{ - unsigned int pos = INTVAL (operands[2]), - siz = INTVAL (operands[1]), - mask = (1 << (pos + siz)) - (1 << pos); - - switch (which_alternative) - { - case 0: - return \"setb\\t%0,%b1\"; - - case 1: - return \"clrb\\t%0,%b1\"; - - case 2: - operands[3] = gen_int_mode (mask & 0xff, QImode); - return AS2 (mov, w, %3) CR_TAB - AS2 (or, %0, w); - - case 3: - operands[3] = gen_int_mode (0xff & ~mask, QImode); - return AS2 (mov, w, %3) CR_TAB - AS2 (and, %0, w); - - case 4: - return AS2 (clrb, %0,%b2) CR_TAB - AS2 (snb, %3, 0) CR_TAB - AS2 (setb, %0, %b2); - - case 5: - case 6: - { - static char buff[256]; - char *p = buff; - - /* Clear the destination field */ - - p += sprintf (buff, \"mov\\tw,#$%2.2x\;and\\t%%0,w\;\", - 0xff & ~mask); - - if (CONSTANT_P (operands[3])) - /* Constant can just be or-ed in. */ - { - p += sprintf (p, \"mov\\tw,#$%2.2x\;or\\t%%0,w\", - (int) (INTVAL (operands[3]) << pos) & mask & 0xff); - return buff; - } - - p += sprintf (p, \"mov\\tw,%%3\;\"); /* Value to deposit */ - - /* Shift and mask the value before OR-ing into the destination. */ - - if (pos != 0) - p += sprintf (p, \"mulu\\tw,#%d\;\", 1<<pos); - - p += sprintf (p, \"\;and\\tw,#$%2.2x\;or\\t%%0,w\", mask); - return buff; - } - default: - abort (); - } - }" - [(set_attr "skip" "yes,yes,no,no,no,no,no") - (set_attr "clobberw" "no,no,yes,yes,no,yes,yes")]) - -;; -;; Add bytes -;; - -(define_expand "addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (plus:QI (match_operand:QI 1 "general_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "") - -(define_insn "*push_addqi3" - [(set (match_operand:QI 0 "push_operand" "=<,<,<") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%g,g,g") - (match_operand:QI 2 "general_operand" "N,M,g")))] - "" - "@ - push\\t%1\;inc\\t1(SP) - push\\t%1\;dec\\t1(SP) - mov\\tw,%2\;add\\tw,%1\;push\\twreg" - [(set_attr "clobberw" "no,no,yes")]) - -(define_insn "*addqi3_w" - [(set - (reg:QI 10) - (plus:QI - (match_operand:QI 0 "nonimmediate_operand" "%rS, g,rS, g, rS, g,rS") - (match_operand:QI 1 "general_operand" "N, N, M, M,rSi,rSi, g")))] - "(ip2k_reorg_split_qimode)" - "@ - inc\\tw,%0 - inc\\tw,%0 - dec\\tw,%0 - dec\\tw,%0 - mov\\tw,%1\;add\\tw,%0 - mov\\tw,%1\;add\\tw,%0 - mov\\tw,%1\;add\\tw,%0" - [(set_attr "skip" "no,no,no,no,no,no,no")]) - -(define_insn_and_split "*addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=k,k,z,z,djyoR,djyoR,djyoR,djyS, g,rS, g,rS, g, rS,rS") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,0, 0, 0, 0, 0,rS, g,rS, g, rS, g,rS") - (match_operand:QI 2 "general_operand" "N,g,N,g, N, M, rSi, g, N, N, M, M,rSi,rSi, g")))] - "" - "@ - incsnz\\t%0\;dec\\tiph - mov\\tw,%2\;add\\t%0,w - incsnz\\t%0\;dec\\tdph - mov\\tw,%2\;add\\t%0,w - inc\\t%0 - dec\\t%0 - mov\\tw,%2\;add\\t%0,w - mov\\tw,%2\;add\\t%0,w - # - # - # - # - # - # - #" - "(ip2k_reorg_split_qimode - && ! rtx_equal_p (operands[0], operands[1]))" - [(set (reg:QI 10) - (plus:QI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (reg:QI 10))] - "" - [(set_attr "skip" "no,no,no,no,yes,yes,no,no,no,no,no,no,no,no,no") - (set_attr - "clobberw" "no,yes,no,yes,no,no,yes,yes,yes,yes,yes,yes,yes,yes,yes")]) - -;; -;; Add 16-bit integers. -;; - -(define_expand "addhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (plus:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "" - "if (rtx_equal_p (operands[1], operands[2])) - { - /* It is not impossible to wind up with two constants here. - If we simply emit the ashl, we'll generate unrecognizable - instructions. */ - if (! nonimmediate_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); - emit_insn (gen_ashlhi3 (operands[0], operands[1], const1_rtx)); - DONE; - } - ") - -(define_insn "*push_addhi3" ; 0 1 2 3 4 5 6 7 - [(set - (match_operand:HI 0 "push_operand" "=<,<, <, <, <, <,<,<") - (plus:HI - (match_operand:HI 1 "nonimmediate_operand" "%uo,q,uo,bf, uo, uS,q,q") - (match_operand:HI 2 "general_operand" "N,N, M, P,uSi,uoi,u,n")))] - "" - "*{ - switch (which_alternative) { - case 0: - return AS1 (push, %L1%<) CR_TAB - AS1 (push, %H1%>) CR_TAB - AS1 (incsnz, 2(SP)) CR_TAB - AS1 (inc, 1(SP)); - - case 1: - return AS2 (mov, w, %H1) CR_TAB - AS1 (push, %L1) CR_TAB - AS1 (push, wreg) CR_TAB - AS1 (incsnz, 2(SP)) CR_TAB - AS1 (inc, 1(SP)); - - case 2: - return AS1 (push, %L1%<) CR_TAB - AS1 (push, %H1%>) CR_TAB - AS2 (mov, w, #-1) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (addc, 1(SP), w); - - case 3: - OUT_AS2 (mov, w, %L2); - OUT_AS2 (add, %L1, w); - OUT_AS1 (push, %L1); - OUT_AS1 (push, %H1); - if (!find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - OUT_AS2 (sub, %L1, w); - return \"\"; - - case 4: - case 5: - return AS2 (mov, w, %L2) CR_TAB - AS2 (add, w, %L1) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H2) CR_TAB - AS2 (addc, w, %H1) CR_TAB - AS1 (push, wreg%>); - - case 6: - return AS2 (mov, w, %H1) CR_TAB - AS1 (push, %L1) CR_TAB - AS1 (push, wreg) CR_TAB - AS2 (mov, w, %L2) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (mov, w, %H2) CR_TAB - AS2 (addc, 1(SP), w); - - case 7: - { - operands[3] = GEN_INT (INTVAL (operands[2]) + 2); - return AS1 (push, %L3) CR_TAB - AS1 (push, %H3) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (addc, 1(SP), w); - } - default: - abort (); - } - }" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*push_addhi3_zero_ext" ; 0 1 2 3 - [(set (match_operand:HI 0 "push_operand" "=<, <, <, <") - (plus:HI - (zero_extend:HI - (match_operand:QI 1 "general_operand" "%roRi,roRi,roRi,rSi")) - (match_operand:HI 2 "general_operand" "N, P, rSi,roi")))] - "" - "@ - inc\\tw,%L2\;push\\twreg\;push\\t#0\;rl\\t1(SP) - mov\\tw,%L2\;add\\tw,%1\;push\\twreg\;push\\t#0\;rl\\t1(SP) - mov\\tw,%L2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,$ff\;push\\twreg%> - mov\\tw,%L2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,$ff\;push\\twreg%>") - -(define_insn "*addhi3_imm_zero_ext_w" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=rS,o,a,b,a,a,rS,o,rS,o") - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_operand 1 "immediate_operand" "O,O,M,i,P,I, P,P, i,i")))] - "" - "@ - mov\\t%L0,w\;clr\\t%H0 - mov\\t%L0,w\;clr\\t%H0 - mov\\t%L0,w\;clr\\t%H0\;dec\\t%L0 - loadh\\t%x1\;loadl\\t%x1\;add\\t%L0,w - mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%1\;add\\t%L0,w - mov\\t%L0,w\;clr\\t%H0\;mov\\tw,#%n1\;sub\\t%L0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;rl\\t%H0 - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;rl\\t%H0 - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%H1\;addc\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%H1\;addc\\t%H0,w") - -(define_insn_and_split "*addhi3_imm_zero_ext" - [(set - (match_operand:HI - 0 "nonimmediate_operand" "=rS, o, rS, o, a, b, a, a, rS, o, rS, o") - (plus:HI - (zero_extend:HI - (match_operand:QI - 1 "general_operand" "%roR,rS,roR,rS,roR,roR,roR,roR,roR,rS,roR,rS")) - (match_operand - 2 "immediate_operand" " O, O, N, N, M, i, P, I, P, P, i, i")))] - "" - "@ - # - # - clr\\t%H0\;incsnz\\tw,%1\;inc\\t%H0\;mov\\t%L0,w - clr\\t%H0\;incsnz\\tw,%1\;inc\\t%H0\;mov\\t%L0,w - # - # - # - # - # - # - # - #" - "(ip2k_reorg_split_qimode - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 1))" - [(set (reg:QI 10) - (match_dup 1)) - (set (match_dup 0) - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_dup 2)))]) - -(define_insn "*addhi3_immediate" ; 0 1 2 3 4 5 6 7 8 9 a b c d e f - [(set (match_operand:HI 0 "nonimmediate_operand" "=a,do,a,do,a,a,a,do,&uo,&uS,bf,bf,bf,&uS,&uo, u") - (plus:HI (match_operand:HI 1 "general_operand" "%0, 0,0, 0,0,0,0, 0, rS, ro,uo,uo,uo, ro, rS,uo") - (match_operand 2 "immediate_operand" "N, N,M, M,P,I,i, i, N, N, M, P, I, i, i, i")))] - "" - "@ - inc\\t%L0 - incsnz\\t%L0\;inc\\t%H0 - dec\\t%L0 - mov\\tw,#-1\;add\\t%L0,w\;addc\\t%H0,w - mov\\tw,%2\;add\\t%L0,w - mov\\tw,#%n2\;sub\\t%L0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;add\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%H1\;mov\\t%H0,w\;incsnz\\tw,%L1\;inc\\t%H0\;mov\\t%L0,w - mov\\tw,%H1\;mov\\t%H0,w\;incsnz\\tw,%L1\;inc\\t%H0\;mov\\t%L0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;dec\\t%L0 - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;mov\\tw,%2\;add\\t%L0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;mov\\tw,#%n2\;sub\\t%L0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;pop\\t%L0%>" - [(set_attr "skip" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no,no,no") - (set_attr "clobberw" "no,no,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*addhi3_nonimmediate" ; 0 1 2 3 4 5 6 7 - [(set (match_operand:HI 0 "nonimmediate_operand" "=&bf,bf,&dS,&do,d,&rS,&rS, o") - (plus:HI (match_operand:HI 1 "general_operand" "%0, 0, 0, 0,0, ro, rS,rS") - (match_operand:HI 2 "nonimmediate_operand" "ro,uo, ro, rS,r, rS, ro,rS")))] - "" - "@ - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;add\\t%H0,w - mov\\tw,%L2\;push\\t%H2%<\;add\\t%L0,w\;pop\\twreg%>\;add\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%L2\;push\\t%H2%<\;add\\t%L0,w\;pop\\twreg%>\;addc\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w") - -(define_insn "*addhi3_nonimm_zero_extend_w" - [(set (match_operand:HI 0 "nonimmediate_operand" "=a,ro,&ro,&rS,&rS, u") - (plus:HI - (zero_extend:HI (reg:QI 10)) - (match_operand:HI 1 "nonimmediate_operand" "0, 0, rS, rS, ro,uo")))] - "" - "@ - add\\t%L0,w - add\\t%L0,w\;clr\\twreg\;addc\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;push\\twreg%<\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w\;pop\\t%L0%>" - [(set_attr "skip" "yes,no,no,no,no,no") - (set_attr "clobberw" "no,yes,yes,yes,yes,yes")]) - -(define_insn_and_split "*addhi3_nonimm_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=a, ro,&ro,&rS,&rS, u") - (plus:HI - (zero_extend:HI - (match_operand:QI 1 "general_operand" "roR,roR, rS,roR, rS,rS")) - (match_operand:HI 2 "nonimmediate_operand" "0, 0, rS, rS, ro,uo")))] - "" - "#" - "(ip2k_reorg_split_qimode)" - [(set (reg:QI 10) - (match_dup 1)) - (set (match_dup 0) - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_dup 2)))]) - - -;; -;; Add 32-bit integers. -;; - -(define_expand "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (plus:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "") - -(define_insn "*push_addsi3" - [(set (match_operand:SI 0 "push_operand" "=<,<, <") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%g,g, g") - (match_operand:SI 2 "general_operand" "N,M,rSi")))] - "" - "*{ - switch (which_alternative) { - case 0: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%>%>%>); - OUT_AS1 (incsnz, 4(SP)); - OUT_AS1 (incsz, 3(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 2(SP)); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (1:,); - return \"\"; - - case 1: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%>%>%>); - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, 4(SP), w); - OUT_AS2 (addc, 3(SP), w); - OUT_AS2 (addc, 2(SP), w); - OUT_AS2 (addc, 1(SP), w); - return \"\"; - - case 2: - OUT_AS2 (mov, w, %D2); - OUT_AS2 (add, w, %D1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %C2); - OUT_AS2 (addc, w, %C1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %B2); - OUT_AS2 (addc, w, %B1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %A2); - OUT_AS2 (addc, w, %A1); - OUT_AS1 (push, wreg%>%>%>); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*addsi3" ; 0 1 2 3 4 5 6 - [(set - (match_operand:SI 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&rS") - (plus:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, 0, 0, rS, ro, rS") - (match_operand:SI 2 "general_operand" "N, M,rSi,roi,rSi,rSi,roi")))] - "" - "@ - incsnz\\t%D0\;incsz\\t%C0\;page\\t1f\;jmp\\t1f\;incsnz\\t%B0\;inc\\t%A0\;1: - mov\\tw,#-1\;add\\t%D0,w\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%D2\;add\\t%D0,w\;mov\\tw,%C2\;addc\\t%C0,w\;mov\\tw,%B2\;addc\\t%B0,w\;mov\\tw,%A2\;addc\\t%A0,w - mov\\tw,%D2\;add\\t%D0,w\;mov\\tw,%C2\;addc\\t%C0,w\;mov\\tw,%B2\;addc\\t%B0,w\;mov\\tw,%A2\;addc\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*push_addsi3_zero_extendqi" ; 0 1 - [(set (match_operand:SI 0 "push_operand" "=<, <") - (plus:SI (zero_extend:SI - (match_operand:QI 1 "general_operand" "%roRi,rSi")) - (match_operand:SI 2 "general_operand" "rSi,roi")))] - "" - "@ - mov\\tw,%D2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%> - mov\\tw,%D2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%>") - -(define_insn "*addsi3_zero_extendqi" ; - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,&ro,&rS,&rS") - (plus:SI - (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR, rS,roR, rS")) - (match_operand:SI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "@ - mov\\tw,%1\;add\\t%D0,w\;clr\\twreg\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%1\;add\\t%D0,w\;clr\\twreg\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w") - -(define_insn "*push_addsi3_zero_extendhi" ; 0 1 - [(set (match_operand:SI 0 "push_operand" "=<, <") - (plus:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%roR,rSR")) - (match_operand:SI 2 "general_operand" "rSi,roi")))] - "" - "@ - mov\\tw,%D2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,%H1\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%> - mov\\tw,%D2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,%H1\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%>") - -(define_insn "*addsi3_zero_extendhi" ; - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:SI - (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:SI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "@ - mov\\tw,%L1\;add\\t%D0,w\;mov\\tw,%H1\;addc\\t%C0,w\;clr\\twreg\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%L1\;add\\t%D0,w\;mov\\tw,%H1\;addc\\t%C0,w\;clr\\twreg\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w") - -;; -;; Add 64-bit integers. -;; - -(define_expand "adddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "" - "") - -(define_insn "*push_adddi3" - [(set (match_operand:DI 0 "push_operand" "=<,<, <") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%g,g, g") - (match_operand:DI 2 "general_operand" "N,M,rSi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (incsnz, 8(SP)); - OUT_AS1 (incsz, 7(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 6(SP)); - OUT_AS1 (incsz, 5(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 4(SP)); - OUT_AS1 (incsz, 3(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 2(SP)); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (1:,); - return \"\"; - - case 1: - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, 8(SP), w); - OUT_AS2 (addc, 7(SP), w); - OUT_AS2 (addc, 6(SP), w); - OUT_AS2 (addc, 5(SP), w); - OUT_AS2 (addc, 4(SP), w); - OUT_AS2 (addc, 3(SP), w); - OUT_AS2 (addc, 2(SP), w); - OUT_AS2 (addc, 1(SP), w); - return \"\"; - - case 2: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, w, %Z1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %Y1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %X1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %W1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, %V1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, %U1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, %T1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, %S1); - OUT_AS1 (push, wreg%>%>%>%>%>%>%>); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*adddi3" ; 0 1 2 3 4 5 6 - [(set - (match_operand:DI 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&rS") - (plus:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, 0, 0, rS, ro, rS") - (match_operand:DI 2 "general_operand" "N, M,rSi,roi,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (incsnz, %Z0); - OUT_AS1 (incsz, %Y0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %X0); - OUT_AS1 (incsz, %W0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %V0); - OUT_AS1 (incsz, %U0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %T0); - OUT_AS1 (inc, %S0); - OUT_AS1 (1:, ); - return \"\"; - - case 1: - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 4: - case 5: - case 6: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, w, %Z1); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %Y1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %X1); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %W1); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, %V1); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, %U1); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, %T1); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, %S1); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*adddi3_zero_extendqi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR, rS,roR, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, %Z0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -(define_insn "*adddi3_zero_extendhi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %L1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (addc, %Y0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %L1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %H1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -(define_insn "*adddi3_zero_extendsi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %D1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (addc, %W0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %D1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %C1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %B1); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %A1); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -;; -;; Subtract bytes. -;; - -(define_expand "subqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (minus:QI (match_operand:QI 1 "general_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_addqi3 (operands[0], operands[1], - gen_int_mode (-INTVAL (operands[2]), QImode))); - DONE; - } - ") - -(define_insn "*push_subqi3" - [(set (match_operand:QI 0 "push_operand" "=<, <") - (minus:QI (match_operand:QI 1 "general_operand" "g,rSn") - (match_operand:QI 2 "general_operand" "rSn, g")))] - "" - "@ - push\\t%1%<\;mov\\tw,%2\;sub\\t1(SP),w%> - push\\t%1%<\;mov\\tw,%2\;sub\\t1(SP),w%>") - -(define_insn "*subqi3_w" - [(set (reg:QI 10) - (minus:QI (match_operand:QI 0 "general_operand" "rS,rSi, g,rSi") - (match_operand:QI 1 "general_operand" "rSi, rS,rSi, g")))] - "(ip2k_reorg_split_qimode)" - "@ - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0") - -(define_insn_and_split "*subqi3" - [(set - (match_operand:QI - 0 "nonimmediate_operand" "=k,k,z,z,djyoR,djyoR,djyS,djyoR, g, g, rS, rS") - (minus:QI - (match_operand:QI - 1 "general_operand" "0,0,0,0, 0, 0, 0, 0, rS,rSi, g,rSi") - (match_operand:QI - 2 "general_operand" "M,g,M,g, M, N, g, rSi,rSi, rS,rSi, g")))] - "" - "@ - incsnz\\t%0\;dec\\tiph - mov\\tw,%2\;sub\\t%0,w - incsnz\\t%0\;dec\\tdph - mov\\tw,%2\;sub\\t%0,w - inc\\t%0 - dec\\t%0 - mov\\tw,%2\;sub\\t%0,w - mov\\tw,%2\;sub\\t%0,w - # - # - # - #" - "(ip2k_reorg_split_qimode - && ! rtx_equal_p (operands[0], operands[1]))" - [(set (reg:QI 10) - (minus:QI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (reg:QI 10))] - "" - [(set_attr "skip" "no,no,no,no,yes,yes,no,no,no,no,no,no") - (set_attr "clobberw" "no,yes,no,yes,no,no,yes,yes,yes,yes,yes,yes")]) - -;; -;; Subtract 16-bit integers. -;; - -(define_expand "subhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (minus:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "" - "if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_addhi3 (operands[0], operands[1], - gen_int_mode (-INTVAL (operands[2]), HImode))); - DONE; - } - ") - -(define_insn "*push_subhi3" - [(set (match_operand:HI 0 "push_operand" "=<, <") - (minus:HI (match_operand:HI 1 "general_operand" "ron,rSn") - (match_operand:HI 2 "general_operand" "rSn,ron")))] - "" - "@ - push\\t%L1%<\;mov\\tw,%L2\;sub\\t1(SP),w\;push\\t%H1%<\;mov\\tw,%H2\;subc\\t1(SP),w%>%> - push\\t%L1%<\;mov\\tw,%L2\;sub\\t1(SP),w\;push\\t%H1%<\;mov\\tw,%H2\;subc\\t1(SP),w%>%>") - -(define_insn "*subhi3_imm" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,a,a,a,do,&r,&ro,&rS") - (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0, 0,ro, rS, ro") - (match_operand 2 "immediate_operand" "N,M,P,i, i, O, i, i")))] - "" - "@ - dec\\t%L0 - inc\\t%L0 - mov\\tw,%2\;sub\\t%L0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;sub\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w" - [(set_attr "skip" "yes,yes,no,no,no,no,no,no") - (set_attr "clobberw" "no,no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*subhi3_ximm_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (minus:HI (match_operand:HI 1 "immediate_operand" "i, i") - (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "rS,roR"))))] - "" - "@ - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;clr\\twreg\;subc\\t%H0,w") - -(define_insn "*subhi3_ximm" - [(set (match_operand:HI 0 "nonimmediate_operand" "=&uo,&ro,&rS") - (minus:HI (match_operand:HI 1 "immediate_operand" "i, i, i") - (match_operand:HI 2 "nonimmediate_operand" "0, rS, ro")))] - "" - "@ - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;push\\t%H2%<\;mov\\tw,%H1\;mov\\t%H0,w\;pop\\twreg%>\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%H2\;subc\\t%H0,w") - -(define_insn "*subhi3_nonimm_zero_extend" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,ro, rS,&ro,&rS,&rS") - (minus:HI - (match_operand:HI 1 "nonimmediate_operand" "0, 0, 0, rS, ro, rS") - (zero_extend:HI - (match_operand:QI 2 "general_operand" "roR,rS,roR, rS, rS,roR"))))] - "" - "@ - mov\\tw,%2\;sub\\t%L0,w - mov\\tw,%2\;sub\\t%L0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\t%L0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w") - -(define_insn "*subhi3_nonimm" ; 0 1 2 3 4 5 6 - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,dS, o,&rS,&rS,&rS, o") - (minus:HI - (match_operand:HI 1 "nonimmediate_operand" "0, 0, 0, ro, ro, rS,rS") - (match_operand:HI 2 "nonimmediate_operand" "ro,ro,rS, 0, rS, ro,rS")))] - "" - "@ - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;sub\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w") - -;; -;; Subtract 32-bit integers. -;; - -(define_insn "subsi3" ; 0 1 2 3 4 5 6 7 8 9 a b - [(set - (match_operand:SI - 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&ro,&rS,&rS,&ro,&ro,&rS") - (minus:SI - (match_operand:SI - 1 "general_operand" "0, 0, 0, 0, i, ro, rS, rS, ro, rS, i, i") - (match_operand:SI - 2 "general_operand" "M, N,rSi,roi, 0, 0, 0,roi,rSi,rSi, rS, ro")))] - "" - "*{ - switch (which_alternative) { - case 0: - return AS2 (mov, w, #1) CR_TAB - AS2 (add, %D0, w) CR_TAB - AS1 (clr, wreg) CR_TAB - AS2 (addc, %C0, w) CR_TAB - AS2 (addc, %B0, w) CR_TAB - AS2 (addc, %A0, w); - - case 1: - return AS2 (mov, w, #-1) CR_TAB - AS2 (sub, %D0, w) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (subc, %A0, w); - - case 2: - case 3: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, %D0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, %A0, w); - - case 4: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (push, %C2%<) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS1 (push, %B2%<) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS1 (push, %A2%<) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %A0, w); - - case 5: - case 6: - case 7: - case 8: - case 9: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, w, %A1) CR_TAB - AS2 (mov, %A0, w); - - case 10: - case 11: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, %A0, w); - default: - abort (); - } - }") - -;; -;; Subtract 64-bit integers. -;; - -(define_insn "subdi3" ; 0 1 2 3 4 5 6 7 8 9 a b - [(set - (match_operand:DI - 0 "nonimmediate_operand" "=ro,ro, ro, rS,ro,&rS,&ro,&rS,&rS,&ro,&ro,&rS") - (minus:DI - (match_operand:DI - 1 "general_operand" "0, 0, 0, 0, i, ro, rS, rS, ro, rS, i, i") - (match_operand:DI - 2 "general_operand" "M, N,rSi,roi, 0, 0, 0,roi,rSi,rSi, rS, ro")))] - "" - "*{ - switch (which_alternative) { - case 0: - return AS2 (mov, w, #1) CR_TAB - AS2 (add, %Z0, w) CR_TAB - AS1 (clr, wreg) CR_TAB - AS2 (addc, %Y0, w) CR_TAB - AS2 (addc, %X0, w) CR_TAB - AS2 (addc, %W0, w) CR_TAB - AS2 (addc, %V0, w) CR_TAB - AS2 (addc, %U0, w) CR_TAB - AS2 (addc, %T0, w) CR_TAB - AS2 (addc, %S0, w); - - case 1: - return AS2 (mov, w, #-1) CR_TAB - AS2 (sub, %Z0, w) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (subc, %S0, w); - - case 2: - case 3: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, %Z0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, %S0, w); - - case 4: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS1 (push, %Y2%<) CR_TAB - AS2 (mov, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS1 (push, %X2%<) CR_TAB - AS2 (mov, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS1 (push, %W2%<) CR_TAB - AS2 (mov, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS1 (push, %V2%<) CR_TAB - AS2 (mov, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS1 (push, %U2%<) CR_TAB - AS2 (mov, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS1 (push, %T2%<) CR_TAB - AS2 (mov, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS1 (push, %S2%<) CR_TAB - AS2 (mov, w, %S1) CR_TAB - AS2 (mov, %S0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %S0, w); - - case 5: - case 6: - case 7: - case 8: - case 9: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, w, %S1) CR_TAB - AS2 (mov, %S0, w); - - case 10: - case 11: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS2 (mov, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (mov, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (mov, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (mov, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (mov, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (mov, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (mov, w, %S1) CR_TAB - AS2 (mov, %S0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, %S0, w); - default: - abort (); - } - }") - -;; -;; Bitwise and instructions. -;; - -(define_expand "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (and:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "") - -(define_insn "*andqi3_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR") - (and:QI (match_dup 0) - (match_operand:QI 1 "const_int_operand" "n")))] - "(find_one_clear_bit_p (INTVAL (operands[1]) | 0xffffff00UL) != -1)" - "*{ - operands[2] = GEN_INT (find_one_clear_bit_p (INTVAL (operands[1]) - | 0xffffff00UL)); - return AS2 (clrb, %0, %b2); - }" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -(define_insn "*andqi3_w_fr" - [(set (reg:QI 10) - (and:QI (match_operand:QI 0 "general_operand" "roRn") - (reg:QI 10)))] - "(ip2k_reorg_split_qimode)" - "and\\tw,%0" - [(set_attr "skip" "yes")]) - -(define_insn_and_split "*andqi3_fr_w" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,rS,roR, rS,rS") - (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR,rS") - (reg:QI 10)))] - "(ip2k_reorg_split_qimode)" - "@ - and\\t%0,w - and\\t%0,w - # - # - #" - "(ip2k_reorg_split_qimode - && ! rtx_equal_p (operands[0], operands[1]))" - [(set (reg:QI 10) - (and:QI (match_dup 1) - (reg:QI 10))) - (set (match_dup 0) - (reg:QI 10))] - "" - [(set_attr "skip" "yes,yes,no,no,no") - (set_attr "clobberw" "no,no,yes,yes,yes")]) - -(define_insn_and_split "*andqi3" ; 0 1 2 3 4 - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS,roR, rS, rS") - (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSn,roRn,rSn,rSn,roRn")))] - "" - "@ - mov\\tw,%2\;and\\t%0,w - # - # - # - #" - "(ip2k_reorg_split_qimode - && (! rtx_equal_p (operands[0], operands[1]) - || GET_CODE (operands[2]) != CONST_INT - || find_one_clear_bit_p (INTVAL (operands[2]) | 0xffffff00UL) == -1))" - [(set (reg:QI 10) - (match_dup 2)) - (set (match_dup 0) - (and:QI (match_dup 1) - (reg:QI 10)))]) - -(define_insn_and_split "andhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (and:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "andsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (and:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "anddi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (and:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Bitwise or instructions. -;; - -(define_expand "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "") - -(define_insn "*iorqi3_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR") - (ior:QI (match_dup 0) - (match_operand:QI 1 "const_int_operand" "n")))] - "(find_one_set_bit_p (INTVAL (operands[1]) & 0xff) != -1)" - "*{ - operands[2] = GEN_INT (find_one_set_bit_p (INTVAL (operands[1]) & 0xff)); - return AS2 (setb, %0, %b2); - }" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -(define_insn "*iorqi3" ; 0 1 2 3 4 - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS,roR, rS, rS") - (ior:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSi,roRi,rSi,rSi,roRi")))] - "" - "@ - mov\\tw,%2\;or\\t%0,w - mov\\tw,%2\;or\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w") - -(define_insn_and_split "iorhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (ior:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "iorsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (ior:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "iordi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (ior:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Bitwise xor instructions -;; -;; TODO: xor ops can also use "not w, fr"! -;; - -(define_insn "xorqi3" - [(set - (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS, rS") - (xor:QI (match_operand:QI 1 "general_operand" "%0, 0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "M,rSi,roRi,rSi,rSi,roRi")))] - "" - "@ - not\\t%0 - mov\\tw,%2\;xor\\t%0,w - mov\\tw,%2\;xor\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes")]) - -(define_insn_and_split "xorhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (xor:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "xorsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (xor:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "xordi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (xor:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Multiply instructions. -;; - -(define_insn "umulqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi")))] - "" - "mov\\tw,%1\;mulu\\tw,%2\;mov\\t%0,w") - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:HI - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (sign_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))))] - "" - "@ - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w") - -(define_insn_and_split "umulqihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (zero_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))))] - "" - "#" - "ip2k_reorg_split_qimode" - [(set (match_dup 3) - (mult:QI (match_dup 1) - (match_dup 2))) - (set (reg:QI 10) - (reg:QI 15)) - (set (match_dup 4) - (reg:QI 10))] - "{ - operands[3] = ip2k_get_low_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[0], QImode); - }") - -(define_insn "*mulhi3_by2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "0, rS, ro") - (zero_extend:HI (const_int 2))))] - "" - "@ - clrb\\tSTATUS,0\;rl\\t%L0\;rl\\t%H0 - clrb\\tSTATUS,0\;rl\\tw,%L1\;mov\\t%L0,w\;rl\\tw,%H1\;mov\\t%H0,w - clrb\\tSTATUS,0\;rl\\tw,%L1\;mov\\t%L0,w\;rl\\tw,%H1\;mov\\t%H0,w" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*mulhi3_byqi" - [(set (match_operand:HI - 0 "nonimmediate_operand" "=ro,&ro,&rS, &rS") - (mult:HI (match_operand:HI - 1 "nonimmediate_operand" "0, rS, ro, rS") - (zero_extend:HI (match_operand:QI - 2 "general_operand" "rSi,rSi,rSi,roRi"))))] - "" - "@ - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;push\\tmulh%<\;mov\\tw,%H1\;mulu\\tw,%2\;pop\\t%H0%>\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w") - -(define_insn "smulqi_highpart" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS, rS") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (sign_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))) - (const_int 8))))] - "" - "@ - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w") - -(define_insn "umulqi_highpart" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS, rS") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (zero_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))) - (const_int 8))))] - "" - "@ - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w") - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS, uS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rS, ro, rS") - (match_operand:HI 2 "general_operand" "rSi,rSi,roi")))] - "" - "push\\t%L2%<\;push\\t%H2%<\;push\\t%L1%<\;push\\t%H1%>\;page\\t__mulhi3\;call\\t__mulhi3\;pop\\t%H0%>\;pop\\t%L0%>") - -;; If we find that we're multiplying by a constant that's less than 256 we -;; can replace a full "mulhi3" with one of the lighter weight variants -;; that multiplies an HImode value by a QImode one. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:HI 2 "const_int_operand" "P, P")))] - "(INTVAL (operands[2]) < 0x100)" - [(set (match_dup 0) - (mult:HI (match_dup 1) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (INTVAL (operands[2]), QImode);") - -;; -;; Divide/Modulus functions. -;; - -(define_expand "udivmodhi4" - [(parallel [(set (reg:HI 128) - (udiv:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (reg:HI 130) - (umod:HI (match_dup 1) (match_dup 2))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133))]) - (set (match_operand:HI 0 "general_operand" "") (reg:HI 128)) - (set (match_operand:HI 3 "general_operand" "") (reg:HI 130))] - "" - "") - -(define_insn "*udivmodhi4_call" - [(set (reg:HI 128) - (udiv:HI (match_operand:HI 0 "general_operand" "uSi,uoi") - (match_operand:HI 1 "general_operand" "uoi,uSi"))) - (set (reg:HI 130) - (umod:HI (match_dup 0) (match_dup 1))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133))] - "" - "push\\t%L1%<\;push\\t%H1%<\;push\\t%L0%<\;push\\t%H0%>%>%>\;page\\t__udivmodhi4\;call\\t__udivmodhi4") - -(define_expand "divmodhi4" - [(parallel [(set (reg:HI 128) - (div:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (reg:HI 130) - (mod:HI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133)) - (clobber (reg:QI 134)) - (clobber (reg:QI 135))]) - (set (match_operand:HI 0 "general_operand" "") (reg:HI 128)) - (set (match_operand:HI 3 "general_operand" "") (reg:HI 130))] - "" - "") - -(define_insn "*divmodhi4_call" - [(set (reg:HI 128) - (div:HI (match_operand:HI 0 "general_operand" "uSi,uoi") - (match_operand:HI 1 "general_operand" "uoi,uSi"))) - (set (reg:HI 130) - (mod:HI (match_dup 0) (match_dup 1))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133)) - (clobber (reg:QI 134)) - (clobber (reg:QI 135))] - "" - "push\\t%L1%<\;push\\t%H1%<\;push\\t%L0%<\;push\\t%H0%>%>%>\;page\\t__divmodhi4\;call\\t__divmodhi4") - -(define_expand "udivmodsi4" - [(parallel [(set (reg:SI 128) - (udiv:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (reg:SI 132) - (umod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 128)) - (set (match_operand:SI 3 "general_operand" "") (reg:SI 132))] - "" - "") - -(define_insn "*udivmodsi4_call" - [(set (reg:SI 128) - (udiv:SI (match_operand:SI 0 "general_operand" "rSi,roi") - (match_operand:SI 1 "general_operand" "roi,rSi"))) - (set (reg:SI 132) - (umod:SI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;push\\t%D0%<\;push\\t%C0%<\;push\\t%B0%<\;push\\t%A0%>%>%>%>%>%>%>\;page\\t__udivmodsi4\;call\\t__udivmodsi4") - -(define_expand "divmodsi4" - [(parallel [(set (reg:SI 128) - (div:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (reg:SI 132) - (mod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139)) - (clobber (reg:QI 140)) - (clobber (reg:QI 141))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 128)) - (set (match_operand:SI 3 "general_operand" "") (reg:SI 132))] - "" - "") - -(define_insn "*divmodsi4_call" - [(set (reg:SI 128) - (div:SI (match_operand:SI 0 "general_operand" "rSn,ron") - (match_operand:SI 1 "general_operand" "ron,rSn"))) - (set (reg:SI 132) - (mod:SI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139)) - (clobber (reg:QI 140)) - (clobber (reg:QI 141))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;push\\t%D0%<\;push\\t%C0%<\;push\\t%B0%<\;push\\t%A0%>%>%>%>%>%>%>\;page\\t__divmodsi4\;call\\t__divmodsi4") - -(define_expand "udivmoddi4" - [(parallel [(set (reg:DI 128) - (udiv:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (set (reg:DI 136) - (umod:DI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))]) - (set (match_operand:DI 0 "general_operand" "") (reg:DI 128)) - (set (match_operand:DI 3 "general_operand" "") (reg:DI 136))] - "" - "") - -(define_insn "*udivmoddi4_call" - [(set (reg:DI 128) - (udiv:DI (match_operand:DI 0 "general_operand" "rSi,roi") - (match_operand:DI 1 "general_operand" "roi,rSi"))) - (set (reg:DI 136) - (umod:DI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))] - "" - "push\\t%Z1%<\;push\\t%Y1%<\;push\\t%X1%<\;push\\t%W1%<\;push\\t%V1%<\;push\\t%U1%<\;push\\t%T1%<\;push\\t%S1%<\;push\\t%Z0%<\;push\\t%Y0%<\;push\\t%X0%<\;push\\t%W0%<\;push\\t%V0%<\;push\\t%U0%<\;push\\t%T0%<\;push\\t%S00%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>\;page\\t__udivmoddi4\;call\\t__udivmoddi4") - -(define_expand "divmoddi4" - [(parallel [(set (reg:DI 128) - (div:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (set (reg:DI 136) - (mod:DI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))]) - (set (match_operand:DI 0 "general_operand" "") (reg:DI 128)) - (set (match_operand:DI 3 "general_operand" "") (reg:DI 136))] - "" - "") - -(define_insn "*divmoddi4_call" - [(set (reg:DI 128) - (div:DI (match_operand:DI 0 "general_operand" "rSn,ron") - (match_operand:DI 1 "general_operand" "ron,rSn"))) - (set (reg:DI 136) - (mod:DI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))] - "" - "push\\t%Z1%<\;push\\t%Y1%<\;push\\t%X1%<\;push\\t%W1%<\;push\\t%V1%<\;push\\t%U1%<\;push\\t%T1%<\;push\\t%S1%<\;push\\t%Z0%<\;push\\t%Y0%<\;push\\t%X0%<\;push\\t%W0%<\;push\\t%V0%<\;push\\t%U0%<\;push\\t%T0%<\;push\\t%S00%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>\;page\\t__divmoddi4\;call\\t__divmoddi4") - -;; -;; Arithmetic shift left instructions. -;; - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS") - (ashift:QI - (match_operand:QI 1 "nonimmediate_operand" "0, rS,roR, 0, 0") - (match_operand:QI 2 "general_operand" "N, L, L, rS,roR")))] - "" - "@ - clrb status,0\;rl\\t%0 - mov\\tw,%e2\;mulu\\tw,%1\;mov\\t%0,w - mov\\tw,%e2\;mulu\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;snz\;page\\t1f\;jmp\\t1f\;2:clrb\\tstatus,0\;rl\\t%0\;decsz\\twreg\;page\\t2b\;jmp\\t2b\;1: - mov\\tw,%2\;snz\;page\\t1f\;jmp\\t1f\;2:clrb\\tstatus,0\;rl\\t%0\;decsz\\twreg\;page\\t2b\;jmp\\t2b\;1:" - [(set_attr "clobberw" "no,yes,yes,yes,yes")]) - -;; Convert simple fixed-size shift of a zero-extended QImode value into a -;; multiply as our multiplier is much faster. We also do this so that the -;; multiply can possibly be merged into a much faster multiply-and-accumulate -;; operation. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (match_operand:QI 2 "const_int_operand" "J, J")))] - "(INTVAL (operands[2]) < 8)" - [(set (match_dup 0) - (mult:HI (zero_extend:HI (match_dup 1)) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (1 << INTVAL (operands[2]), QImode);") - -(define_insn_and_split "*ashlhi3_by8_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (const_int 8)))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], QImode); - operands[3] = ip2k_get_low_half (operands[0], QImode); - }") - -(define_insn "*ashlhi3_zero_extend" ; 0 1 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (match_operand:QI 2 "const_int_operand" "n, n")))] - "" - "*{ - if (INTVAL (operands[2]) < 8) - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - else - { - operands[3] = GEN_INT (INTVAL (operands[2]) - 8); - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e3) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (clr, %L0); - } - }") - -;; Convert simple fixed-size shift of a HImode value into a multiply as -;; our multiplier is much faster. We also do this so that the multiply can -;; possibly be merged into a much faster multiply-and-accumulate operation. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "J, J")))] - "(INTVAL (operands[2]) < 8)" - [(set (match_dup 0) - (mult:HI (match_dup 1) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (1 << INTVAL (operands[2]), QImode);") - -(define_insn_and_split "ashlhi3_split" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "n, n")))] - "(INTVAL (operands[2]) >= 8)" - "#" - "&& ip2k_reorg_split_himode" - [(set (match_dup 4) (const_int 0))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_low_half (operands[0], QImode); - operands[5] = ip2k_get_low_half (operands[1], QImode); - - if (INTVAL (operands[2]) == 8) - emit_insn (gen_movqi (operands[3], operands[5])); - else - { - operands[6] = gen_int_mode (INTVAL (operands[2]) - 8, QImode); - emit_insn (gen_ashlqi3 (operands[3], operands[5], operands[6])); - } - }") - -(define_insn "ashlhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (ashift:HI - (match_operand:HI 1 "nonimmediate_operand" "0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 3: - case 4: - case 5: - case 6: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (push, MULH%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, 1(SP), w) CR_TAB - AS1 (pop, %H0%>); - - case 7: - return AS1 (rr, %H0) CR_TAB - AS2 (mov, w, %L0) CR_TAB - AS1 (clr, %L0) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (mov, %H0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 3: - case 4: - case 5: - case 6: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (push, MULH%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, 1(SP), w) CR_TAB - AS1 (pop, %H0%>); - - case 7: - return AS2 (rr, w, %H1) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS1 (clr, %L0) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn_and_split "*ashlsi3_by16_zero_extend" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS") - (ashift:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro")) - (const_int 16)))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn_and_split "ashlsi3_split" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "(INTVAL (operands[2]) >= 16)" - "#" - "&& ip2k_reorg_split_simode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_low_half (operands[0], HImode); - operands[5] = ip2k_get_low_half (operands[1], HImode); - - if (INTVAL (operands[2]) == 16) - { - emit_insn (gen_movhi (operands[3], operands[5])); - emit_insn (gen_movhi (operands[4], const0_rtx)); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 16); - emit_insn (gen_ashlhi3 (operands[3], operands[5], operands[6])); - emit_insn (gen_movhi (operands[4], const0_rtx)); - } - }") - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (ashift:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 8: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %D0); - - case 16: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 23: - return AS2 (rr, w, %C0) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0); - - case 24: - return AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 31: - return AS2 (rr, w, %D0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rl, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rl, w, %A1) CR_TAB - AS2 (mov, %A0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rl, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rl, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 8: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %D0); - - case 16: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 23: - return AS2 (rr, w, %C1) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0); - - case 24: - return AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 31: - return AS2 (rr, w, %D1) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -(define_insn_and_split "ashldi3_split" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "((INTVAL (operands[2]) >= 32) || (INTVAL (operands[2]) == 16))" - "#" - "&& ip2k_reorg_split_dimode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_low_half (operands[0], SImode); - operands[5] = ip2k_get_low_half (operands[1], SImode); - - if (INTVAL (operands[2]) == 16) - { - operands[6] = ip2k_get_high_half (operands[1], SImode); - operands[7] = ip2k_get_high_half (operands[3], HImode); - operands[8] = ip2k_get_low_half (operands[3], HImode); - operands[9] = ip2k_get_high_half (operands[4], HImode); - operands[10] = ip2k_get_low_half (operands[4], HImode); - operands[11] = ip2k_get_low_half (operands[6], HImode); - operands[12] = ip2k_get_high_half (operands[5], HImode); - operands[13] = ip2k_get_low_half (operands[5], HImode); - emit_insn (gen_movhi (operands[7], operands[11])); - emit_insn (gen_movhi (operands[8], operands[12])); - emit_insn (gen_movhi (operands[9], operands[13])); - emit_insn (gen_movhi (operands[10], const0_rtx)); - } - else if (INTVAL (operands[2]) == 32) - { - emit_insn (gen_movsi (operands[3], operands[5])); - emit_insn (gen_movsi (operands[4], const0_rtx)); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 32); - emit_insn (gen_ashlsi3 (operands[3], operands[5], operands[6])); - emit_insn (gen_movsi (operands[4], const0_rtx)); - } - }") - -;; -;; Arithmetic shift right instructions. -;; - -(define_expand "ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "if (operands[2] == const0_rtx) - { - emit_move_insn (operands[0], operands[1]); - DONE; - } - ") - -(define_insn "*ashrqi3" - [(set - (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS,roR, rS") - (ashiftrt:QI - (match_operand:QI 1 "nonimmediate_operand" "0, 0, 0, rS,roR, rS,roR") - (match_operand:QI 2 "general_operand" "N, rS,roR, N, N, L, L")))] - "" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (rl, w, %0) CR_TAB - AS1 (rr, %0); - - case 3: - case 4: - return AS2 (rl, w, %1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %1) CR_TAB - AS2 (mov, %0, w); - - case 5: - case 6: - /* Do >> by left-shifting partially into MULH. */ - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %1) CR_TAB - AS2 (muls, w, %e2) CR_TAB - AS2 (mov, w, mulh) CR_TAB - AS2 (mov, %0, w); - - case 1: - case 2: - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - } - }") - -(define_insn "ashrhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (ashiftrt:HI - (match_operand:HI 1 "nonimmediate_operand" "0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 2: - return AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 8: - return AS2 (mov, w, %H0) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, %L0, 7) CR_TAB - AS1 (not, %H0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %H1) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w); - - case 2: - return AS2 (rl, w, %H1) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 8: - return AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, %L0, 7) CR_TAB - AS1 (not, %H0); - - default: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (ashiftrt:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %A0) CR_TAB /* dup the sign bit */ - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 2: - return AS2 (rl, w, %A0) CR_TAB /* dup the sign bit */ - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS2 (rl, w, %A0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0) CR_TAB - AS2 (snb, %B0, 7) CR_TAB - AS1 (not, %A0); - - case 16: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %C0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 23: - return AS2 (rl, w, %B0) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 31: - return AS2 (rl, w, %A0) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %A0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, WREG) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, WREG) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %A1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w); - - case 2: - return AS2 (rl, w, %A1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %A0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0) CR_TAB - AS2 (snb, %B0, 7) CR_TAB - AS1 (not, %A0); - - case 16: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %C0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 23: - return AS2 (rl, w, %B1) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 31: - return AS2 (rl, w, %A1) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %A1, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -;; -;; Logical shift right instructions. -;; - -(define_insn "lshrqi3" - [(set (match_operand:QI - 0 "nonimmediate_operand" "=roR, rS,roR,roR, rS,&roR,roR, rS") - (lshiftrt:QI - (match_operand:QI - 1 "nonimmediate_operand" "0, 0, 0, rS,roR, rS, rS,roR") - (match_operand:QI - 2 "general_operand" "N,roR, rS, N, N, rS, L, L")))] - "" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0); - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %1) CR_TAB - AS2 (mov, %0, w); - - case 5: - return AS2 (mov, w, %1) CR_TAB - AS2 (mov, %0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 6: - case 7: - /* Do >> by left-shifting partially into MULH. */ - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, mulh) CR_TAB - AS2 (mov, %0, w); - default: - abort (); - } - }") - -(define_insn_and_split "lshrhi3_split" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "n, n")))] - "(INTVAL (operands[2]) >= 8)" - "#" - "&& ip2k_reorg_split_himode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_low_half (operands[0], QImode); - operands[5] = ip2k_get_high_half (operands[1], QImode); - - if (INTVAL (operands[2]) == 8) - emit_insn (gen_movqi (operands[4], operands[5])); - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 8); - emit_insn (gen_lshrqi3 (operands[4], operands[5], operands[6])); - } - emit_insn (gen_movqi (operands[3], const0_rtx)); - }") - -(define_insn "lshrhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (lshiftrt:HI - (match_operand:HI 1 "nonimmediate_operand" " 0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 3: - case 4: - case 5: - case 6: - case 7: - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %L0) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H0) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 3: - case 4: - case 5: - case 6: - case 7: - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn_and_split "lshrsi3_split" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "(INTVAL (operands[2]) >= 16)" - "#" - "&& ip2k_reorg_split_simode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_low_half (operands[0], HImode); - operands[5] = ip2k_get_high_half (operands[1], HImode); - - if (INTVAL (operands[2]) == 16) - emit_insn (gen_movhi (operands[4], operands[5])); - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 16); - emit_insn (gen_lshrhi3 (operands[4], operands[5], operands[6])); - } - emit_insn (gen_movhi (operands[3], const0_rtx)); - }") - -;; This occurs frequently in supporting FP among other things, -;; and out-of-line is almost as big as inline, so.... -;; -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (lshiftrt:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0); - - case 16: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 23: - return AS2 (rl, w, %B0) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 31: - return AS2 (rl, w, %A0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0); - - case 16: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 23: - return AS2 (rl, w, %B1) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 31: - return AS2 (rl, w, %A1) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -(define_insn_and_split "lshrdi3_split" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "((INTVAL (operands[2]) >= 32) || (INTVAL (operands[2]) == 16))" - "#" - "&& ip2k_reorg_split_dimode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_low_half (operands[0], SImode); - operands[5] = ip2k_get_high_half (operands[1], SImode); - - if (INTVAL (operands[2]) == 16) - { - operands[6] = ip2k_get_low_half (operands[1], SImode); - operands[7] = ip2k_get_high_half (operands[3], HImode); - operands[8] = ip2k_get_low_half (operands[3], HImode); - operands[9] = ip2k_get_high_half (operands[4], HImode); - operands[10] = ip2k_get_low_half (operands[4], HImode); - operands[11] = ip2k_get_high_half (operands[6], HImode); - operands[12] = ip2k_get_low_half (operands[5], HImode); - operands[13] = ip2k_get_high_half (operands[5], HImode); - emit_insn (gen_movhi (operands[10], operands[11])); - emit_insn (gen_movhi (operands[9], operands[12])); - emit_insn (gen_movhi (operands[8], operands[13])); - emit_insn (gen_movhi (operands[7], const0_rtx)); - } - else if (INTVAL (operands[2]) == 32) - { - emit_insn (gen_movsi (operands[4], operands[5])); - emit_insn (gen_movsi (operands[3], const0_rtx)); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 32); - emit_insn (gen_lshrsi3 (operands[4], operands[5], operands[6])); - emit_insn (gen_movsi (operands[3], const0_rtx)); - } - }") - -;; -;; Absolute value conversion instructions. -;; - -(define_insn "absqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (abs:QI (match_operand:QI 1 "nonimmediate_operand" "g")))] - "" - "mov\\tw,%1\;snb\\twreg,7\;sub\\tw,#0\;mov\\t%0,w") - -(define_insn "abssf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=ro") - (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0")))] - "" - "clrb %A0,7" - [(set_attr "clobberw" "no")]) - -;; -;; Negate (X = 0 - Y) instructions. -;; - -(define_insn_and_split "negqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:QI (match_dup 1))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "neghi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:HI (match_dup 1))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "negsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:SI (match_dup 1))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "negdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:DI (match_dup 1))) - (set (match_dup 0) - (plus:DI (match_dup 0) - (const_int 1)))] - "") - -;; -;; Bitwise not (one's complement) instructions. -;; - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g,roR, rS") - (not:QI (match_operand:QI 1 "general_operand" "0, rS,roR")))] - "" - "@ - not\\t%0 - not\\tw,%1\;mov\\t%0,w - not\\tw,%1\;mov\\t%0,w" - [(set_attr "skip" "yes,no,no") - (set_attr "clobberw" "no,yes,yes")]) - -(define_insn_and_split "one_cmplhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:HI (match_operand:HI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (not:QI (match_dup 4))) - (set (match_dup 5) - (not:QI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_low_half (operands[0], QImode); - operands[6] = ip2k_get_low_half (operands[1], QImode); - }") - -(define_insn_and_split "one_cmplsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:SI (match_operand:SI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (not:HI (match_dup 4))) - (set (match_dup 5) - (not:HI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_low_half (operands[0], HImode); - operands[6] = ip2k_get_low_half (operands[1], HImode); - }") - -(define_insn_and_split "one_cmpldi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:DI (match_operand:DI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (not:SI (match_dup 4))) - (set (match_dup 5) - (not:SI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_low_half (operands[0], SImode); - operands[6] = ip2k_get_low_half (operands[1], SImode); - }") - -;; -;; Sign extension instructions. -;; - -(define_insn "*push_extendqihi2" - [(set (match_operand:HI 0 "push_operand" "=<,<") - (sign_extend:HI (match_operand:QI 1 "general_operand" "roR,n")))] - "" - "@ - push\\t%1%<\;push\\t#0%<\;snb\\t%1,7\;not\\t1(SP)%>%> - push\\t%L1\;push\\t%H1" - [(set_attr "clobberw" "no,no")]) - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS,ro,ro") - (sign_extend:HI (match_operand:QI 1 "general_operand" "roR,rS, n")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - if (register_operand (operands[0], HImode) - && register_operand (operands[1], QImode) - && REGNO (operands[0]) == (REGNO (operands[1]) - 1)) - return AS1 (clr, %H0) CR_TAB - AS2 (snb, %1, 7) CR_TAB - AS1 (not, %H0); - else - return AS2 (mov, w, %1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, wreg, 7) CR_TAB - AS1 (not, %H0); - - case 2: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w); - default: - abort (); - } - }") - -(define_insn "*push_extendhisi2" - [(set (match_operand:SI 0 "push_operand" "=<,<,<") - (sign_extend:SI (match_operand:HI 1 "general_operand" "roS,n,s")))] - "" - "@ - push\\t%L1%<\;push\\t%H1%<\;clr\\twreg\;snb\\t%H1,7\;not\\twreg\;push\\twreg\;push\\twreg%>%> - push\\t%D1\;push\\t%C1\;push\\t%B1\;push\\t%A1 - push\\t%L1\;push\\t%H1\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "yes,no,no")]) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS,ro,ro") - (sign_extend:SI (match_operand:HI 1 "general_operand" "rS,ro, n, s")))] - "" - "@ - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\twreg\;snb\\t%C0,7\;not\\twreg\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\twreg\;snb\\t%C0,7\;not\\twreg\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A1\;mov\\t%A0,w - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\t%B0\;clr\\t%A0") - -(define_insn "*push_extendqisi2" - [(set (match_operand:SI 0 "push_operand" "=<,<") - (sign_extend:SI (match_operand:QI 1 "general_operand" "roR,n")))] - "" - "@ - push\\t%1%<\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;push\\twreg\;push\\twreg\;push\\twreg%> - push\\t%D1\;push\\t%C1\;push\\t%B1\;push\\t%A1" - [(set_attr "clobberw" "yes,no")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro") - (sign_extend:SI (match_operand:QI 1 "general_operand" "rS,roR, n")))] - "" - "@ - mov\\tw,%1\;mov\\t%D0,w\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;mov\\t%C0,w\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%1\;mov\\t%D0,w\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;mov\\t%C0,w\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A1\;mov\\t%A0,w") - -;; -;; Zero extension instructions. -;; - -(define_insn "*push_zero_extendqihi2" - [(set (match_operand:HI 0 "push_operand" "=<") - (zero_extend:HI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:HI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], QImode); - operands[3] = ip2k_get_low_half (operands[0], QImode); - }") - -(define_insn "*push_zero_extendhisi2" - [(set (match_operand:SI 0 "push_operand" "=<") - (zero_extend:SI (match_operand:HI 1 "general_operand" "roSi")))] - "" - "push\\t%L1%<\;push\\t%H1%>\;push\\t#0\;push\\t#0") - -(define_insn_and_split "zero_extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:SI (match_operand:HI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn "*push_zero_extendqisi2" - [(set (match_operand:SI 0 "push_operand" "=<") - (zero_extend:SI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:SI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:HI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn "*push_zero_extendsidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:SI 1 "general_operand" "roSi")))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%>%>%>\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0") - -(define_insn_and_split "zero_extendsidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:SI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -(define_insn "*push_zero_extendhidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:HI 1 "general_operand" "roSi")))] - "" - "push\\t%L1%<\;push\\t%H1%>\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendhidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:HI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:SI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -(define_insn "*push_zero_extendqidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:SI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -;; -;; Truncation instructions. -;; - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS, ro") - (truncate:HI (match_operand:SI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%D1\;push\\t%C1%<\;pop\\t%H0%>\;mov\\t%L0,w - mov\\tw,%D1\;push\\t%C1%<\;pop\\t%H0%>\;mov\\t%L0,w") - -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS, ro") - (truncate:QI (match_operand:SI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%D1\;mov\\t%0,w - mov\\tw,%D1\;mov\\t%0,w") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS, ro") - (truncate:QI (match_operand:HI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%L1\;mov\\t%0,w - mov\\tw,%L1\;mov\\t%0,w") - -;; -;; Compare with zero (test) instructions. -;; -;; As we don't have a particularly good set of condition codes we simply -;; tagging our comparison operands for use later within our "compare -;; and branch" instructions. -;; - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "roR"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tstdi" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -;; -;; General value comparison instructions. -;; -;; As we don't have a particularly good set of condition codes we simply -;; tagging our comparison operands for use later within our "compare -;; and branch" instructions. -;; - -(define_insn "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "roR, rS") - (match_operand:QI 1 "general_operand" "rSn,roRn")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "ro, rS") - (match_operand:HI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "ro, rS") - (match_operand:SI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "ro, rS") - (match_operand:DI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -;; -;; Conditional jump instructions. -;; - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - -;; Implementation of conditional jumps. -;; -;; The assumption is that a previous test or compare instruction will have -;; provided the arguments to be compared to form cc0 and then we perform -;; a compare and branch operation here. -;; -(define_insn "*unsigned_cmp_branch" - [(set (pc) - (if_then_else (match_operator 1 "ip2k_unsigned_comparison_operator" - [(cc0) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return ip2k_gen_unsigned_comp_branch (insn, GET_CODE (operands[1]), - operands[0]);") - -;; Signed branches use Z, N or synthesized V. -;; result is generated as 0 (LT), 1 (EQ), 2 (GT) -;; -(define_insn "*signed_cmp_branch" - [(set (pc) - (if_then_else (match_operator 1 "ip2k_signed_comparison_operator" - [(cc0) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return ip2k_gen_signed_comp_branch (insn, GET_CODE (operands[1]), - operands[0]);") - -;; Reverse branch - reverse our comparison condition so that we can -;; branch in the opposite sense. -;; -(define_insn_and_split "*rvbranch" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" [(cc0) - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "#" - "reload_completed" - [(set (pc) - (if_then_else (match_dup 2) - (label_ref (match_operand 0 "" "")) - (pc)))] - "{ - operands[2] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), - GET_MODE (operands[1]), - cc0_rtx, const0_rtx); - }") - -;; This is a bit test and jump sequence. -;; -(define_insn "*bit_cmpqi_branch" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(zero_extract - (match_operand:QI 1 "nonimmediate_operand" "roR") - (const_int 1) - (match_operand 2 "immediate_operand" "i")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)" - "*{ - if (GET_CODE (operands[0]) == EQ) - OUT_AS2 (sb, %1, %b2); - else - OUT_AS2 (snb, %1, %b2); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }" - [(set_attr "clobberw" "no")]) - -;; This is a bit test and jump sequence but for 16-bit operands. It's pretty -;; certain that there must be a way to do this using a zero_extract operation, -;; but this didn't seem to want to work so we use a bitwise and instead. This -;; is exactly as efficient but the combiner handles this OK - the implementation -;; here isn't quite as nice though. -;; -(define_insn "*bit_cmphi_branch" - [(set - (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(and:HI (match_operand:HI 1 "nonimmediate_operand" "roS") - (match_operand 2 "const_int_operand" "n")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "((GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) - && find_one_set_bit_p (INTVAL (operands[2])) != -1)" - "*{ - int bp = find_one_set_bit_p (INTVAL (operands[2])); - if (INTVAL (operands[2]) >= 8) - operands[4] = GEN_INT (bp - 8); - else - operands[4] = GEN_INT (bp); - - if (GET_CODE (operands[0]) == EQ) - { - if (INTVAL (operands[2]) >= 8) - OUT_AS2 (sb, %H1, %b4); - else - OUT_AS2 (sb, %L1, %b4); - } - else - { - if (INTVAL (operands[2]) >= 8) - OUT_AS2 (snb, %H1, %b4); - else - OUT_AS2 (snb, %L1, %b4); - } - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }" - [(set_attr "clobberw" "no")]) - -;; Add two operands, compare with a third and branch if equal or not-equal. -;; -(define_insn "*add_and_comp_branch" - [(set - (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(plus:HI - (match_operand:HI 1 "nonimmediate_operand" "ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn")) - (match_operand:HI 3 "general_operand" "rSn,rSn,ron")]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)" - "*{ - OUT_AS2 (mov, w, %L2); - OUT_AS2 (add, w, %L1); - OUT_AS2 (cse, w, %L3); - if (GET_CODE (operands[0]) == EQ) - { - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - } - else - { - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - } - OUT_AS2 (mov, w, %H2); - OUT_AS2 (addc, w, %H1); - if (GET_CODE (operands[0]) == EQ) - OUT_AS2 (csne, w, %H3); - else - OUT_AS2 (cse, w, %H3); - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - return AS1 (1:, ); - }") - -;; Unconditional jump -;; -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "page\\t%0\;jmp\\t%0" - [(set_attr "clobberw" "no")]) - -;; Indirect jump -;; -(define_insn "indirect_jump" - [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "ro"))] - "" - "page\\t1f\;call\\t1f\;1:mov\\tw,%H0\;mov\\tcallh,w\;mov\\tw,%L0\;mov\\tcalll,w\;ret") - -;; -;; Function call instructions. -;; - -(define_expand "call" - [(call (match_operand 0 "" "") - (match_operand:HI 1 "" ""))] - "" - "") - -(define_insn "*call" - [(call (mem:HI (match_operand:HI 0 "general_operand" "i,roS")) - (match_operand:HI 1 "" ""))] - "" - "@ - page\\t%b0\;call\\t%b0 - push\\t%L0%<\;push\\t%H0%>\;page\\t__indcall\;call\\t__indcall") - -(define_expand "call_pop" - [(parallel [(call (match_operand 0 "" "") - (match_operand:HI 1 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))])] - "" - "") - -(define_insn "*call_pop" - [(call (mem:HI (match_operand:HI 0 "general_operand" "i,roS")) - (match_operand:HI 1 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 2 "immediate_operand" "")))] - "" - "@ - page\\t%b0\;call\\t%b0 - push\\t%L0%<\;push\\t%H0%>\;page\\t__indcall\;call\\t__indcall") - -;; Undo any splitting of operands that lead to redundant movhi3 instructions. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (parallel [(call (mem:HI (match_dup 0)) - (match_operand:HI 2 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))])] - "" - [(parallel [(call (mem:HI (match_dup 1)) - (match_dup 2)) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_dup 3)))])] - "") - -(define_expand "call_value" - [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand:HI 2 "" "")))] - "" - "") - -(define_insn "*call_value" - [(set (match_operand 0 "" "") - (call (mem:HI (match_operand:HI 1 "general_operand" "i,roS")) - (match_operand:HI 2 "" "")))] - "" - "@ - page\\t%b1\;call\\t%b1 - push\\t%L1%<\;push\\t%H1%>\;page\\t__indcall\;call\\t__indcall") - -(define_expand "call_value_pop" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand:HI 2 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 4 "immediate_operand" "")))])] - "" - "") - -(define_insn "*call_value_pop" - [(set (match_operand 0 "" "") - (call (mem:HI (match_operand:HI 1 "general_operand" "i,roS")) - (match_operand:HI 2 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))] - "" - "@ - page\\t%b1\;call\\t%b1 - push\\t%L1%<\;push\\t%H1%>\;page\\t__indcall\;call\\t__indcall") - -;; Undo any splitting of operands that lead to redundant movhi3 instructions. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (parallel [(set (match_operand 2 "" "") - (call (mem:HI (match_dup 0)) - (match_operand:HI 3 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 4 "immediate_operand" "")))])] - "" - [(parallel [(set (match_dup 2) - (call (mem:HI (match_dup 1)) - (match_dup 3))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_dup 4)))])] - "") - -;; Nop instruction. -;; -;; We don't really want nops to appear in our code so just insert a comment. -;; -(define_insn "nop" - [(const_int 0)] - "" - "; nop") - - -;; SEQ instruction -;; -(define_insn "seq" - [(set (match_operand:QI 0 "register_operand" "=r") - (eq:QI (cc0) (const_int 0)))] - "" - "* return ip2k_gen_sCOND (insn, EQ, operands[0]);") - -;; Tweak SEQ if we can adjust the output operand. Note that we have to do -;; this via a peephole because we need to ensure that any reloads have taken -;; place before we try to do this. If there's a reload in order to get our -;; actual result operand then this peephole won't match. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (match_operand:QI 1 "nonimmediate_operand" "") - (reg:QI 10))] - "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" - "* return ip2k_gen_sCOND (insn, EQ, operands[1]);") - -;; Another peephole match handles the same merge as above but for cases where -;; we're emulating memory accesses via IP and an offset. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (mem:QI (plus:HI (reg:HI 4) - (match_operand:QI 1 "const_int_operand" ""))) - (reg:QI 10))] - "(find_regno_note (insn, REG_DEAD, REGNO (operands[0])) - && (INTVAL (operands[1]) < 0x100))" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - ip2k_gen_sCOND (insn, EQ, - gen_rtx_MEM (QImode, gen_rtx_REG (HImode, REG_IP))); - if (find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (sub, ipl, w); - } - } - return \"\"; - }") - -;; SNE instruction -;; -(define_insn "sne" - [(set (match_operand:QI 0 "register_operand" "=r") - (ne:QI (cc0) (const_int 0)))] - "" - "* return ip2k_gen_sCOND (insn, NE, operands[0]);") - -;; Tweak SNE if we can adjust the output operand. Note that we have to do -;; this via a peephole because we need to ensure that any reloads have taken -;; place before we try to do this. If there's a reload in order to get our -;; actual result operand then this peephole won't match. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (match_operand:QI 1 "nonimmediate_operand" "") - (reg:QI 10))] - "find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0]))" - "* return ip2k_gen_sCOND (insn, NE, operands[1]);") - -;; Another peephole match handles the same merge as above but for cases where -;; we're emulating memory accesses via IP and an offset. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (mem:QI (plus:HI (reg:HI 4) - (match_operand:QI 1 "const_int_operand" ""))) - (reg:QI 10))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (INTVAL (operands[1]) < 0x100))" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - ip2k_gen_sCOND (insn, NE, - gen_rtx_MEM (QImode, gen_rtx_REG (HImode, REG_IP))); - if (find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (sub, ipl, w); - } - } - return \"\"; - }") - - - -;; Case Dispatch Table Support. -;; -;; Called with 5 arguments: -;; -;; 0. case index -;; 1. lower bound (const_int) -;; 2. range (const_int) -;; 3. label before dispatch table -;; 4. out-of-bounds label -;; -;; With the IP2k we actually really want to do a caseqi but that -;; doesn't exist so we cheat and make it look (to the core of gcc) -;; like we're going to do the SImode stuff but then truncate it -;; away when it's no longer looking :-) -;; -(define_expand "casesi" - [(set (match_dup 5) - (truncate:QI (match_operand:SI 0 "general_operand" "g"))) - (set (match_dup 5) - (minus:QI (match_dup 5) - (match_operand 1 "const_int_operand" "n"))) - (set (cc0) - (compare (match_dup 5) - (match_operand 2 "const_int_operand" "n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 5)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 2))])] - "" - "{ - operands[5] = gen_reg_rtx (QImode); - }") - -;; There are TWO instructions per dispatch entry (page & jump), so we -;; multiply by two even though our RTL only indicates a simple addition. -;; Subsequent linker relaxation may well restore this back to what the -;; RTL says though! -;; -;; Note that we handle tables with 128 or more entries differently! -;; -(define_insn "*casedispatch" - [(set (pc) - (plus:HI (pc) (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "roR,roR")))) - (use (label_ref (match_operand 0 "" ""))) - (use (match_operand 1 "const_int_operand" "K, n"))] - "" - "@ - mov\\tw,%2\;add\\tw,wreg\;add\\tpcl,w - mov\\tw,%2\;push\\t%0%<\;push\\t#0%<\;add\\tw,wreg\;snc\;inc\\t1(SP)\;add\\t2(SP),w\;snc\;inc\\t1(SP)\;page\\t__indcall\;jmp\\t__indcall%>%>") - -;; Handle cleaning up the switch statement stuff. We can eliminate some -;; register moves in some cases. Note that our pattern is slightly different -;; to the casesi pattern because our minus has become a plus! -;; -;; Note that as of 07-FEB-2002 we must have this pattern as it is because -;; linker relaxation will not work any other way. -;; -(define_peephole - [(set (reg:QI 10) - (plus:QI (match_operand 5 "nonimmediate_operand" "rS,rS,rS,rS") - (match_operand 1 "const_int_operand" "M, n, M, n"))) - (set (match_operand:QI 0 "register_operand" "+r, r, r, r") - (reg:QI 10)) - (set (cc0) - (compare (match_dup 0) - (match_operand 2 "const_int_operand" "K, K, n, n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 0)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 2))])] - "(INTVAL (operands[1]) != 0 - && find_regno_note (insn, REG_DEAD, REGNO (operands[0])))" - "*{ - switch (which_alternative) - { - case 0: - case 2: - OUT_AS2 (dec, w, %5); - break; - - case 1: - case 3: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, w, %5); - break; - default: - abort (); - } - - OUT_AS2 (cmp, w, %2); - OUT_AS1 (sc, ); - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (add, w, WREG); - OUT_AS2 (add, pcl, w); - return \"\"; - - case 2: - case 3: - OUT_AS1 (push, %0%<); - OUT_AS1 (push, #0%<); - OUT_AS2 (add, w, WREG); - OUT_AS1 (snc, ); - OUT_AS1 (inc, 1(SP)); - OUT_AS2 (add, 2(SP), w); - OUT_AS1 (snc, ); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (page, __indcall); - OUT_AS1 (jmp, __indcall%>%>); - return \"\"; - default: - abort (); - } - }") - -(define_peephole - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "rS,rS") - (match_operand 1 "const_int_operand" "K, n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 0)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 1))])] - "" - "@ - mov\\tw,%0\;cmp\\tw,%1\;sc\;page\\t%2\;jmp\\t%2\;add\\tw,wreg\;add\\tpcl,w - mov\\tw,%0\;cmp\\tw,%1\;sc\;page\\t%2\;jmp\\t%2\;push\\t%0%<\;push\\t#0%<\;add\\tw,wreg\;snc\;inc\\t1(SP)\;add\\t2(SP),w\;snc\;inc\\t1(SP)\;page\\t__indcall\;jmp\\t__indcall%>%>") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+roR") - (plus:HI (match_dup 0) - (const_int -1))) - (set (cc0) - (compare (match_dup 0) - (match_operand 3 "const_int_operand" "n"))) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "((GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE) - && ((INTVAL (operands[3]) == -1) || (INTVAL (operands[3]) == 65535)))" - "*{ - OUT_AS2 (mov, w, #255); - OUT_AS2 (add, %L0, w); - if ((GET_CODE (operands[0]) == REG) - && ((REGNO (operands[0]) == REG_DP) - || (REGNO (operands[0]) == REG_IP) - || (REGNO (operands[0]) == REG_SP))) - { - OUT_AS2 (add, %H0, w); - } - else - { - OUT_AS2 (addc, %H0, w); - } - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (sc, ); - else - OUT_AS1 (snc, ); - return AS1 (page, %1) CR_TAB - AS1 (jmp, %1); - }") - -(define_peephole - [(set (match_operand:QI 0 "nonimmediate_operand" "+rS") - (plus:QI (match_dup 0) - (const_int -1))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (decsnz, %0); - else - OUT_AS1 (decsz, %0); - return AS1 (page, %1) CR_TAB - AS1 (jmp, %1); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (set (match_operand:QI 0 "nonimmediate_operand" "=rS") - (reg:QI 10)) - (set (cc0) - (match_operand:QI 2 "nonimmediate_operand" "rS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], operands[2]) - || rtx_equal_p (operands[1], operands[2])))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "uS")) - (set (match_operand:QI 0 "nonimmediate_operand" "+uS") - (reg:QI 10)) - (set (cc0) - (match_operand:SI 2 "nonimmediate_operand" "uS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], - ip2k_get_high_half (ip2k_get_high_half (operands[2], - HImode), QImode)) - || rtx_equal_p (operands[1], - ip2k_get_high_half (ip2k_get_high_half (operands[2], - HImode), - QImode))))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - OUT_AS2 (or, w, %B2); - OUT_AS2 (or, w, %C2); - OUT_AS2 (or, w, %D2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "uS")) - (set (match_operand:QI 0 "nonimmediate_operand" "+uS") - (reg:QI 10)) - (set (cc0) - (match_operand:HI 2 "nonimmediate_operand" "uS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[0], ip2k_get_low_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_low_half (operands[2],QImode))))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - if (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_high_half (operands[2], QImode))) - OUT_AS2 (or, w, %L2); - else - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %L0); - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_dup 1)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %L0); - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+f,bqdo") - (mem:HI (reg:HI 4))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "(GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - OUT_AS2 (or, w, iph); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - OUT_AS2 (or, w, %H0); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - default: - abort (); - } - }") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+f,bqdo") - (mem:HI (reg:HI 4))) - (set (cc0) - (mem:HI (reg:HI 4))) - (set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "(GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - OUT_AS2 (or, w, iph); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - OUT_AS2 (or, w, %H0); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - default: - abort (); - } - }") - -;; Handle move-twice and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(parallel [(set (match_operand:HI 0 "ip2k_gen_operand" "=uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=uS") - (match_dup 1))]) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - OUT_AS2 (mov, w, %L1); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (pop, %H0%>); - OUT_AS2 (mov, %L0, w); - OUT_AS1 (pop, %H2%>); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (mov, %L0, w); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (mov, %H2, w); - OUT_AS2 (or, w, %L2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - }") - -(define_peephole - [(parallel [(set (match_operand:HI 0 "ip2k_gen_operand" "=uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=uS") - (match_dup 1))]) - (set (cc0) - (match_dup 2)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - OUT_AS2 (mov, w, %L1); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (pop, %H0%>); - OUT_AS2 (mov, %L0, w); - OUT_AS1 (pop, %H2%>); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (mov, %L0, w); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (mov, %H2, w); - OUT_AS2 (or, w, %L2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_operand:SI 2 "nonimmediate_operand" "uo")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], HImode)) - || rtx_equal_p (operands[1], - ip2k_get_high_half (operands[2], HImode))))" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle bitwise-and and compare-with-zero operations on bytes. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 2 "general_operand" " g")) - (set (reg:QI 10) - (and:QI (match_operand:QI 1 "general_operand" "g") - (reg:QI 10))) - (set (match_operand:QI 0 "register_operand" "+r") - (reg:QI 10)) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (and, w, %2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle bitwise-xor and compare-with-zero operations on bytes. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "+r") - (xor:QI (match_operand:QI 1 "general_operand" "g") - (match_operand:QI 2 "general_operand" "g"))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (xor, w, %2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Cope with reload's vagaries. -;; - -(define_insn "*pushqi_reload_popqi" - [(set (match_operand:QI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:QI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:QI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%3%> - push\\t%1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%3%>" -) - -(define_peephole2 - [(set (match_operand:QI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:QI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:QI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_himode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && !(ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 126)) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushhi_reload_pophi" - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:HI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:HI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%L1%<\;push\\t%H1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%H3%>\;pop\\t%L3%> - push\\t%L1%<\;push\\t%H1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%H3%>\;pop\\t%L3%>" -) - -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:HI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:HI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_simode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && !(ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 125)) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushsi_reload_popsi" - [(set (match_operand:SI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:SI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:SI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%A3%>\;pop\\t%B3%>\;pop\\t%C3%>\;pop\\t%D3%> - push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%A3%>\;pop\\t%B3%>\;pop\\t%C3%>\;pop\\t%D3%>" -) - -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:SI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:SI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_dimode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && ! (ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 123)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushdi_reload_popdi" - [(set (match_operand:DI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:DI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:DI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%S1%<\;push\\t%T1%<\;push\\t%U1%<\;push\\t%V1%<\;push\\t%W1%<\;push\\t%X1%<\;push\\t%Y1%<\;push\\t%Z1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%Z3%>\;pop\\t%Y3%>\;pop\\t%X3%>\;pop\\t%W3%>\;pop\\t%V3%>\;pop\\t%U3%>\;pop\\t%T3%>\;pop\\t%S3%> - push\\t%S1%<\;push\\t%T1%<\;push\\t%U1%<\;push\\t%V1%<\;push\\t%W1%<\;push\\t%X1%<\;push\\t%Y1%<\;push\\t%Z1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%Z3%>\;pop\\t%Y3%>\;pop\\t%X3%>\;pop\\t%W3%>\;pop\\t%V3%>\;pop\\t%U3%>\;pop\\t%T3%>\;pop\\t%S3%>" -) - -(define_peephole2 - [(set (match_operand:DI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:DI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:DI 3 "ip2k_short_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && ! (ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 119)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -;; FIXME: Disabled because in lshiftrt:SI op1 must match op0 -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "0 && (peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 1 "general_operand" "")) - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(zero_extend:HI (match_dup 1)) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (zero_extend:HI - (match_operand 2 "general_operand" ""))])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (zero_extend:HI (match_dup 2))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 1 "general_operand" "")) - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(zero_extend:SI (match_dup 1)) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (zero_extend:SI - (match_operand 2 "general_operand" ""))])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (zero_extend:SI (match_dup 2))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 4 "general_operand" "") - (match_dup 0)]))] - "0 && ((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 4) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 4 "general_operand" "")) - (match_dup 0)]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(zero_extend:HI (match_dup 4)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 4 "general_operand" "")) - (match_dup 0)]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(zero_extend:SI (match_dup 4)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (match_operand 4 "general_operand" "")]))] - "0 && ((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (match_dup 4)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:HI - (match_operand 4 "general_operand" ""))]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (zero_extend:HI (match_dup 4))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:SI - (match_operand 4 "general_operand" ""))]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (zero_extend:SI (match_dup 4))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_operand 3 "general_operand" "") - (match_dup 0)]))] - "0 && (peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 3) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 3 "general_operand" "")) - (match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(zero_extend:HI (match_dup 3)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 3 "general_operand" "")) - (match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(zero_extend:SI (match_dup 3)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (match_operand 3 "general_operand" "")]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (match_dup 3)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:HI - (match_operand 3 "general_operand" ""))]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (zero_extend:HI (match_dup 3))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:SI - (match_operand 3 "general_operand" ""))]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (zero_extend:SI (match_dup 3))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_unary_operator" - [(match_operand 1 "general_operand" "")])) - (set (match_operand 2 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_unary_operator" [(match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_dup 0))] - "peep2_reg_dead_p (2, operands[0])" - [(set (cc0) - (match_dup 1))] - "") - -;; Look for places where we can shorten a compare operation. -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (const_int 0)) - (set (cc0) - (match_operand:HI 1 "nonimmediate_operand" "")) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(rtx_equal_p (ip2k_get_high_half (operands[1], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (cc0) - (match_dup 4)) - (set (pc) - (if_then_else (match_op_dup 2 - [(cc0) (const_int 0)]) - (label_ref (match_dup 3)) - (pc)))] - "{ - operands[4] = ip2k_get_low_half (operands[1], QImode); - }") - -;; Look for places where we can shorten a compare operation. -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (const_int 0)) - (set (cc0) - (compare (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand 2 "const_int_operand" ""))) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(rtx_equal_p (ip2k_get_high_half (operands[1], QImode), operands[0]) - && (abs (INTVAL (operands[2]) <= 127)))" - [(set (match_dup 0) - (const_int 0)) - (set (cc0) - (compare (match_dup 5) - (match_dup 6))) - (set (pc) - (if_then_else (match_op_dup 3 - [(cc0) (const_int 0)]) - (label_ref (match_dup 4)) - (pc)))] - "{ - operands[5] = ip2k_get_low_half (operands[1], QImode); - operands[6] = gen_int_mode (INTVAL (operands[2]) & 0xff, QImode); - }") - -;; This is one of those cases where gcc just can't untangle our wishes. We -;; want to add some values but get two copies of the result. In this instance -;; however, the seconds copy can be made more cheaply by combining things. -;; -(define_peephole - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "+&u") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (match_operand:HI 2 "general_operand" "rSi"))) - (set (match_operand:HI 3 "ip2k_gen_operand" "=&uS") - (match_dup 0))] - "(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && (!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))))" - "mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\t%L3,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;mov\\t%H3,w") - -(define_peephole - [(set (match_operand:HI 0 "ip2k_short_operand" "+&S") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (match_operand:HI 2 "general_operand" "rSi"))) - (set (match_operand:HI 3 "ip2k_nonsp_reg_operand" "=&u") - (match_dup 0))] - "(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ! rtx_equal_p (operands[0], operands[1]) - && ! rtx_equal_p (operands[0], operands[2]))" - "mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\t%L3,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;mov\\t%H3,w") - -;; Some splits zero the MSByte of a word that we then use for shifting. We -;; can therefore replace full shifts with zero-extended ones. These are -;; cheaper for us. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 2 "register_operand" "") - (match_operand 3 "const_int_operand" "")))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 1) - (ashift:HI (zero_extend:HI (match_dup 4)) - (match_dup 3)))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 2 "register_operand" "") - (match_operand 3 "const_int_operand" "")))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (match_dup 1) - (ashift:HI (zero_extend:HI (match_dup 4)) - (match_dup 3)))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -;; Some splits zero the MSByte of a word that we then use for multiplying. We -;; can therefore replace the full multiplies with zero-extended ones. -;; These are cheaper for us. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (mult:HI (match_operand:HI 2 "register_operand" "") - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - && (peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[1], operands[2])))" - [(set (match_dup 1) - (mult:HI (zero_extend:HI (match_dup 4)) - (zero_extend:HI (match_dup 3))))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (mult:HI (match_operand:HI 2 "register_operand" "") - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (match_dup 1) - (mult:HI (zero_extend:HI (match_dup 4)) - (zero_extend:HI (match_dup 3))))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -;; Merge in a redundant move before a zero-extended multiply. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (mult:HI (zero_extend:HI (match_dup 0)) - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - || rtx_equal_p (ip2k_get_low_half (operands[2], QImode), operands[0]))" - [(set (match_dup 2) - (mult:HI (zero_extend:HI (match_dup 1)) - (zero_extend:HI (match_dup 3))))] - "") - -;; Pick up redundant clears followed by adds - these can just become moves. -;; -(define_peephole2 - [(set (match_operand 0 "register_operand" "") - (const_int 0)) - (set (match_operand 2 "nonimmediate_operand" "") - (plus (match_dup 0) - (match_operand 1 "general_operand" "")))] - "peep2_reg_dead_p (2, operands[0])" - [(set (match_dup 2) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand 0 "register_operand" "") - (const_int 0)) - (set (match_dup 0) - (plus (match_dup 0) - (match_operand 1 "general_operand" "")))] - "" - [(set (match_dup 0) - (match_dup 1))] - "") - -;; Clear up an add followed by a push of the result. The fact that this -;; isn't picked up consistently within the combiner suggests a bug somewhere. -;; -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (mem:HI (post_dec:HI (reg:HI 6))) - (match_dup 0))] - "peep2_reg_dead_p (2, operands[0])" - [(set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 1) - (match_dup 2)))] - "") - -;; Tidy up stack slot addressing where we've eliminated some registers. -;; This looks like something strange going on though as gcc-2.97 didn't -;; exhibit this behavior, whereas gcc-3.0.4 does. -;; -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand 2 "const_int_operand" ""))) - (set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 0) - (match_operand 3 "const_int_operand" "")))] - "peep2_reg_dead_p (2, operands[0])" - [(set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 1) - (match_dup 4)))] - "{ - operands[4] = gen_int_mode (INTVAL (operands[2]) + INTVAL (operands[3]), - HImode); - }") - -;; Match duplicate loads of a symbol ref. This isn't something that we want to -;; do at the peephole2 stage because more often than not we'll make one of the -;; two loads redundant after we run peephole2. We catch the remaining cases -;; here though -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uS") - (match_operand 1 "ip2k_symbol_ref_operand" "i")) - (set (match_operand:HI 2 "nonimmediate_operand" "=uS") - (match_dup 1))] - "((!REG_P (operands[0]) || (REGNO (operands[0]) != REG_DP)) - && (!REG_P (operands[2]) || (REGNO (operands[2]) != REG_DP)))" - "mov\\tw,%L1\;mov\\t%L0,w\;mov\\t%L2,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\t%H2,w") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+&uS") - (match_operand 1 "ip2k_symbol_ref_operand" "i")) - (set (match_operand:HI 2 "nonimmediate_operand" "=&uS") - (match_dup 0))] - "" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - return AS2 (mov, w, %L1) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (pop, %H0%>) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (pop, %H2%>) CR_TAB - AS2 (mov, %L2, w); - } - else - { - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, %L2, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, %H2, w); - } - }") - -;; Handle the common array indexing pattern. -;; This is of the form A = X + (Y * C). -;; We use splits earlier in this file to get our interesting cases into the -;; same form (i.e. zero-extended multiply and add). -;; -(define_insn "*mulacchi" - [(set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n"))) - (match_operand:HI 0 "general_operand" "rSi")))] - "" - "*{ - if (immediate_operand (operands[0], HImode) - && REG_P (operands[3]) - && (REGNO (operands[3]) == REG_DP) - && (INTVAL (operands[2]) == 2)) - return AS2 (mov, w, %1) CR_TAB - AS1 (loadl, %x0) CR_TAB - AS1 (loadh, %x0) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (add, dpl, w); - else - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L0) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H0) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w); - }") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")) - (zero_extend:HI - (match_operand 2 "const_int_operand" "")))) - (set (match_operand:HI 3 "nonimmediate_operand" "") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "")))] - "(((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 3) - (plus:HI (mult:HI (zero_extend:HI - (match_dup 1)) - (zero_extend:HI - (match_dup 2))) - (match_dup 4)))] - "") - -(define_insn "*mulhi_and_accumulate" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3])))))" - "*{ - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - }") - -(define_peephole2 - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")) - (zero_extend:HI - (match_operand 2 "const_int_operand" "")))) - (set (match_operand:HI 3 "nonimmediate_operand" "") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "")))] - "((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3])))))" - [(parallel [(set (match_dup 0) - (mult:HI (zero_extend:HI - (match_dup 1)) - (zero_extend:HI - (match_dup 2)))) - (set (match_dup 3) - (plus:HI (match_dup 0) - (match_dup 4)))])] - "") - -;; Handle the common array indexing pattern. -;; This is of the form A = X + (Y * C). -;; We use splits earlier in this file to get our interesting cases into the -;; same form (i.e. multiply and add). -;; -(define_peephole - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && find_regno_note (insn, REG_DEAD, REGNO (operands[0])))" - "*{ - if (immediate_operand (operands[4], HImode) - && REG_P (operands[3]) - && (REGNO (operands[3]) == REG_DP) - && (INTVAL (operands[2]) == 2) - && ip2k_xexp_not_uses_reg_p (operands[1], REG_DP, - GET_MODE_SIZE (HImode))) - return AS2 (clrb, STATUS, 0) CR_TAB - AS1 (loadl, %x4) CR_TAB - AS1 (loadh, %x4) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (add, dph, w); - else if (!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H3, w); - else - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS1 (pop, %H3%>) CR_TAB - AS1 (pop, %L3%>) CR_TAB - AS2 (add, %H3, w); - }") - -;; Handle the more complex variant of the preceding multiply and accumulate -;; variant of the preceding multiply-and-add operation. This one would -;; otherwise fail to match because the result never goes dead. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (match_operand:HI 3 "general_operand" "%rSi")))] - "(!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0])))))" - "*{ - if (immediate_operand (operands[3], HImode) - && REG_P (operands[0]) - && (REGNO (operands[0]) == REG_DP) - && (INTVAL (operands[2]) == 2)) - return AS2 (clrb, STATUS, 0) CR_TAB - AS1 (loadl, %x3) CR_TAB - AS1 (loadh, %x3) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (add, dph, w); - else - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L3) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H3) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H0, w); - }") - -;; Handle the a complex variant of the preceding multiply and add -;; operations where the intermediate result is also required. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && (INTVAL (operands[2]) != 2))" - "* return AS2 (mov, w, %H4) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (addc, %H3, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H3, w) CR_TAB - AS2 (add, %H0, w);") - -;; Byte swapping! -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (set (match_operand:QI 0 "register_operand" "=r") - (reg:QI 10)) - (set (reg:QI 10) - (match_operand:QI 2 "nonimmediate_operand" "rS")) - (set (match_dup 1) - (reg:QI 10)) - (set (reg:QI 10) - (match_dup 0)) - (set (match_dup 2) - (reg:QI 10))] - "find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0]))" - "push\\t%1%<\;push\\t%2%<\;pop\\t%1%>\;pop\\t%2%>") - - diff --git a/gcc/config/ip2k/libgcc.S b/gcc/config/ip2k/libgcc.S deleted file mode 100644 index 624037608fe..00000000000 --- a/gcc/config/ip2k/libgcc.S +++ /dev/null @@ -1,1516 +0,0 @@ -; -; Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. -; Contributed by Red Hat, Inc and Ubicom, 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. -; -; 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.) -; -; 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. */ - -/******************************************************* - load byte from arbitrary memory - address passed in first bank register, result in W - -*******************************************************/ - .macro movb to, from - mov w, \from - mov \to, w - .endm - - -#if defined (L_indcall) -/* __indcall - given register containing an address, call the function - * at that address. - */ - - .sect .pram.libgcc,"ax" - .global __indcall - .func _indcall,__indcall - -__indcall: - page 1f - call 1f -1: pop callh ; Get the call target - pop calll - ret ; Transfer to new function - - .endfunc -#endif - - -#if defined (L_mulhi3) - .sect .pram.libgcc,"ax" - .global __mulhi3 - .func _mulhi3, __mulhi3 - -__mulhi3: - mov w, 2(SP) ; First upper half partial product - mulu w, 3(SP) - mov 3(SP), w - mov w, 1(SP) ; Second upper half partial product - mulu w, 4(SP) - add 3(SP), w - mov w, 2(SP) ; Lower half partial product - mulu w, 4(SP) - mov 4(SP), w - mov w, MULH - add 3(SP), w - - mov w, #2 ; Adjust the stack leaving the result to - add spl, w ; be popped off later. - ret - - .endfunc - -#endif /* defined (L_mulhi3) */ - -#if defined (L_mulsi3) -/******************************************************* - Multiplication 32 x 32 -*******************************************************/ - - .sect .text.libgcc,"ax" - .global __mulsi3 - .func _mulsi3, __mulsi3 - -__mulsi3: - clr $80 ; Assume zero result - clr $81 - clr $82 - clr $83 - -2: mov w, 1(sp) - or w, 2(sp) - or w, 3(sp) - or w, 4(sp) - snz ; Any more significant bits to multiply? - page 3f - jmp 3f - - sb 4(sp), 0 ; Check LSB of multiplier - page 1f ; zero => scale multiplicand & multiplier - jmp 1f - - mov w, 8(sp) ; Accumulate product - add $83, w - mov w, 7(sp) - addc $82, w - mov w, 6(sp) - addc $81, w - mov w, 5(sp) - addc $80, w -1: clrb status, 0 ; scale multiplier down - rr 1(sp) - rr 2(sp) - rr 3(sp) - rr 4(sp) - clrb status, 0 - rl 8(sp) - rl 7(sp) - rl 6(sp) - rl 5(sp) - page 2b - jmp 2b - -3: mov w, #8 - add spl ,w - ret - - .endfunc - -#endif /* defined (L_mulsi3) */ - -#if defined (L_muldi3) -/******************************************************* - Multiplication 64 x 64 -*******************************************************/ - - .sect .text.libgcc,"ax" - .global __muldi3 - .func _muldi3, __muldi3 - -__muldi3: - clr $80 ; Assume zero result - clr $81 - clr $82 - clr $83 - clr $84 - clr $85 - clr $86 - clr $87 - -2: mov w, 1(sp) - or w, 2(sp) - or w, 3(sp) - or w, 4(sp) - or w, 5(sp) - or w, 6(sp) - or w, 7(sp) - or w, 8(sp) - snz ; Any more significant bits to multiply? - page 3f - jmp 3f - - sb 8(sp), 0 ; Check LSB of multiplier - page 1f ; zero => scale multiplicand & multiplier - jmp 1f - - mov w, 16(sp) ; Accumulate product - add $87, w - mov w, 15(sp) - addc $86, w - mov w, 14(sp) - addc $85, w - mov w, 13(sp) - addc $84, w - mov w, 12(sp) - addc $83, w - mov w, 11(sp) - addc $82, w - mov w, 10(sp) - addc $81, w - mov w, 9(sp) - addc $80, w - -1: clrb status, 0 ; scale multiplier down - rr 1(sp) - rr 2(sp) - rr 3(sp) - rr 4(sp) - rr 5(sp) - rr 6(sp) - rr 7(sp) - rr 8(sp) - clrb status, 0 - rl 16(sp) - rl 15(sp) - rl 14(sp) - rl 13(sp) - rl 12(sp) - rl 11(sp) - rl 10(sp) - rl 9(sp) - page 2b - jmp 2b - -3: mov w, #16 - add spl, w - ret - - .endfunc - -#endif /* defined (L_muldi3) */ - -#if defined (L_divmodhi4) -#define arg1h 1(SP) -#define arg1l 2(SP) -#define arg2h 3(SP) -#define arg2l 4(SP) -#define resl $81 -#define resh $80 -#define reml $83 -#define remh $82 -#define tmp_var $84 -#define cnt $85 -#define arg1_sign $86 -#define res_sign $87 - - .sect .text.libgcc,"ax" - .global __divmodhi4 - .func _divmodhi4, __divmodhi4 - -__divmodhi4: - mov w,arg2h - mov res_sign,w - mov w,arg1h - mov arg1_sign,w - xor res_sign,w - - sb arg1h,7 - page 1f - jmp 1f - - not arg1h - not arg1l - incsnz arg1l - inc arg1h - -1: sb arg2h, 7 - page 1f - jmp 1f - - not arg2h - not arg2l - incsnz arg2l - inc arg2h - -1: page __udivmodhi4 ; Do the unsigned div/mod - call __udivmodhi4 - - sb arg1_sign, 7 - page 1f - jmp 1f - - not reml - not remh - incsnz reml - inc remh - -1: sb res_sign, 7 - ret - - not resl - not resh - incsnz resl - inc resh - ret - - .endfunc - -#undef arg1h -#undef arg1l -#undef arg2h -#undef arg2l -#undef resl -#undef resh -#undef reml -#undef remh -#undef tmp_var -#undef cnt -#undef arg1_sign -#undef res_sign - -#endif /* defined (L_divmodhi4) */ - -#if defined (L_udivmodhi4) - -#define arg1h 1(SP) -#define arg1l 2(SP) -#define arg2h 3(SP) -#define arg2l 4(SP) -#define resl $81 -#define resh $80 -#define reml $83 -#define remh $82 -#define tmp_var $84 -#define cnt $85 - - .sect .text.libgcc,"ax" - .global __udivmodhi4 - .func _udivmodhi4, __udivmodhi4 - -__udivmodhi4: - clr reml - clr remh - mov w, #17 - mov cnt,w - clrb status, 0 - page 1f - jmp 1f - -2: rl reml - rl remh - mov w, arg2l - sub w, reml - mov tmp_var, w - mov w, arg2h - subc w, remh - sc - page 1f - jmp 1f - mov remh, w - mov w, tmp_var - mov reml, w - -1: rl arg1l - rl arg1h - decsz cnt - page 2b - jmp 2b - - pop resh - pop resl - mov w, #2 - add spl, w - ret - - .endfunc - -#undef arg1h -#undef arg1l -#undef arg2h -#undef arg2l -#undef resl -#undef resh -#undef reml -#undef remh -#undef tmp_var -#undef cnt - -#endif /* defined (L_udivmodhi4) */ - -#if defined (L_divmodsi4) - -#define arg1a 1(SP) -#define arg1b 2(SP) -#define arg1c 3(SP) -#define arg1d 4(SP) - -#define arg2a 5(SP) -#define arg2b 6(SP) -#define arg2c 7(SP) -#define arg2d 8(SP) - -#define resa $80 -#define resb $81 -#define resc $82 -#define resd $83 - -#define rema $84 -#define remb $85 -#define remc $86 -#define remd $87 - -#define tmp_var $88 -#define tmp_var1 $89 -#define tmp_var2 $8a -#define cnt $8b -#define arg1_sign $8c -#define res_sign $8d - - .sect .text.libgcc,"ax" - .global __divmodsi4 - .func _divmodsi4, __divmodsi4 - -__divmodsi4: - mov w, arg2a - mov res_sign, w - mov w, arg1a - mov arg1_sign, w - xor res_sign, w - - sb arg1a, 7 - page 1f - jmp 1f - - not arg1d - not arg1c - not arg1b - not arg1a - incsnz arg1d - incsz arg1c - page 1f - jmp 1f - incsnz arg1b - inc arg1a - -1: sb arg2a, 7 - page 1f - jmp 1f - - not arg2d - not arg2c - not arg2b - not arg2a - incsnz arg2d - incsz arg2c - page 1f - jmp 1f - incsnz arg2b - inc arg2a - -1: page __udivmodsi4 ; Do the unsigned div/mod. - call __udivmodsi4 - - sb arg1_sign, 7 - page 1f - jmp 1f - - not remd - not remc - not remb - not rema - incsnz remd - incsz remc - page 1f - jmp 1f - incsnz remb - inc rema - -1: sb res_sign, 7 - ret - - not resd - not resc - not resb - not resa - incsnz resd - incsz resc - ret - incsnz resb - inc resa - ret - - .endfunc - -#undef arg1a -#undef arg1b -#undef arg1c -#undef arg1d - -#undef arg2a -#undef arg2b -#undef arg2c -#undef arg2d - -#undef resa -#undef resb -#undef resc -#undef resd - -#undef rema -#undef remb -#undef remc -#undef remd - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef cnt -#undef arg1_sign -#undef res_sign - -#endif /* defined (L_divmodsi4) */ - -#if defined (L_udivmodsi4) -#define arg1a 1(SP) -#define arg1b 2(SP) -#define arg1c 3(SP) -#define arg1d 4(SP) - -#define arg2a 5(SP) -#define arg2b 6(SP) -#define arg2c 7(SP) -#define arg2d 8(SP) - -#define resa $80 -#define resb $81 -#define resc $82 -#define resd $83 - -#define rema $84 -#define remb $85 -#define remc $86 -#define remd $87 - -#define tmp_var $88 -#define tmp_var1 $89 -#define tmp_var2 $8a -#define cnt $8b - - .sect .text.libgcc,"ax" - .global __udivmodsi4 - .func _udivmodsi4, __udivmodsi4 - -__udivmodsi4: - clr remd - clr remc - clr remb - clr rema - mov w, #33 - mov cnt, w - clrb status, 0 - page 1f - jmp 1f - -2: rl remd - rl remc - rl remb - rl rema - mov w, arg2d - sub w, remd - mov tmp_var, w - mov w, arg2c - subc w, remc - mov tmp_var1, w - mov w, arg2b - subc w, remb - mov tmp_var2, w - mov w, arg2a - subc w, rema - sc - page 1f - jmp 1f - - mov rema, w - mov w, tmp_var2 - mov remb, w - mov w, tmp_var1 - mov remc, w - mov w, tmp_var - mov remd, w - -1: rl arg1d - rl arg1c - rl arg1b - rl arg1a - decsz cnt - page 2b - jmp 2b - - pop resa - pop resb - pop resc - pop resd - mov w, #4 - add spl, w - ret - - .endfunc - -#undef arg1a -#undef arg1b -#undef arg1c -#undef arg1d - -#undef arg2a -#undef arg2b -#undef arg2c -#undef arg2d - -#undef resa -#undef resb -#undef resc -#undef resd - -#undef rema -#undef remb -#undef remc -#undef remd - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef cnt - -#endif /* defined (L_udivmodsi4) */ - -#if defined (L_divmoddi4) - -#define arg1s 1(SP) -#define arg1t 2(SP) -#define arg1u 3(SP) -#define arg1v 4(SP) -#define arg1w 5(SP) -#define arg1x 6(SP) -#define arg1y 7(SP) -#define arg1z 8(SP) - -#define arg2s 9(SP) -#define arg2t 10(SP) -#define arg2u 11(SP) -#define arg2v 12(SP) -#define arg2w 13(SP) -#define arg2x 14(SP) -#define arg2y 15(SP) -#define arg2z 16(SP) - -#define ress $80 -#define rest $81 -#define resu $82 -#define resv $83 -#define resw $84 -#define resx $85 -#define resy $86 -#define resz $87 - -#define rems $88 -#define remt $89 -#define remu $8a -#define remv $8b -#define remw $8c -#define remx $8d -#define remy $8e -#define remz $8f - -#define tmp_var $90 -#define tmp_var1 $91 -#define tmp_var2 $92 -#define tmp_var3 $93 -#define tmp_var4 $94 -#define tmp_var5 $95 -#define tmp_var6 $96 -#define cnt $97 - - .sect .text.libgcc,"ax" - .global __divmoddi4 - .func _divmoddi4, __divmoddi4 - -__divmoddi4: - rl w, arg2s ; Use MULH to track sign bits. - rl MULH - rl w, arg1s - rl WREG - xor MULH, w - rl w, arg1s - rl MULH - - sb arg1s, 7 - page 1f - jmp 1f - - not arg1s - not arg1t - not arg1u - not arg1v - not arg1w - not arg1x - not arg1y - not arg1z - incsnz arg1z - incsz arg1y - page 1f - jmp 1f - incsnz arg1x - incsz arg1w - page 1f - jmp 1f - incsnz arg1v - incsz arg1u - page 1f - jmp 1f - incsnz arg1t - inc arg1s - -1: sb arg2s, 7 - page 1f - jmp 1f - - not arg2s - not arg2t - not arg2u - not arg2v - not arg2w - not arg2x - not arg2y - not arg2z - incsnz arg2z - incsz arg2y - page 1f - jmp 1f - incsnz arg2x - incsz arg2w - page 1f - jmp 1f - incsnz arg2v - incsz arg2u - page 1f - jmp 1f - incsnz arg2t - inc arg2s - -1: page __udivmoddi4 ; Do the unsigned div/mod. - call __udivmoddi4 - - sb MULH, 0 ; Look at the save sign bit for arg 1. - page 1f - jmp 1f - - not rems - not remt - not remu - not remv - not remw - not remx - not remy - not remz - incsnz remz - incsz remy - page 1f - jmp 1f - incsnz remx - incsz remw - page 1f - jmp 1f - incsnz remv - incsz remu - page 1f - jmp 1f - incsnz remt - inc rems - -1: sb MULH, 1 - ret - - not ress - not rest - not resu - not resv - not resw - not resx - not resy - not resz - incsnz resz - incsz resy - ret - incsnz resx - incsz resw - ret - incsnz resv - incsz resu - ret - incsnz rest - inc ress - ret - - .endfunc - -#undef arg1s -#undef arg1t -#undef arg1u -#undef arg1v -#undef arg1w -#undef arg1x -#undef arg1y -#undef arg1z - -#undef arg2s -#undef arg2t -#undef arg2u -#undef arg2v -#undef arg2w -#undef arg2x -#undef arg2y -#undef arg2z - -#undef ress -#undef rest -#undef resu -#undef resv -#undef resw -#undef resx -#undef resy -#undef resz - -#undef rems -#undef remt -#undef remu -#undef remv -#undef remw -#undef remx -#undef remy -#undef remz - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef tmp_var3 -#undef tmp_var4 -#undef tmp_var5 -#undef tmp_var6 -#undef cnt - -#endif /* defined (L_divmoddi4) */ - -#if defined (L_udivmoddi4) -#define arg1s 1(SP) -#define arg1t 2(SP) -#define arg1u 3(SP) -#define arg1v 4(SP) -#define arg1w 5(SP) -#define arg1x 6(SP) -#define arg1y 7(SP) -#define arg1z 8(SP) - -#define arg2s 9(SP) -#define arg2t 10(SP) -#define arg2u 11(SP) -#define arg2v 12(SP) -#define arg2w 13(SP) -#define arg2x 14(SP) -#define arg2y 15(SP) -#define arg2z 16(SP) - -#define ress $80 -#define rest $81 -#define resu $82 -#define resv $83 -#define resw $84 -#define resx $85 -#define resy $86 -#define resz $87 - -#define rems $88 -#define remt $89 -#define remu $8a -#define remv $8b -#define remw $8c -#define remx $8d -#define remy $8e -#define remz $8f - -#define tmp_var $90 -#define tmp_var1 $91 -#define tmp_var2 $92 -#define tmp_var3 $93 -#define tmp_var4 $94 -#define tmp_var5 $95 -#define tmp_var6 $96 -#define cnt $97 - - .sect .text.libgcc,"ax" - .global __udivmoddi4 - .func _udivmoddi4, __udivmoddi4 - -__udivmoddi4: - clr rems - clr remt - clr remu - clr remv - clr remw - clr remx - clr remy - clr remz - mov w, #65 - mov cnt, w - clrb status, 0 - page 1f - jmp 1f - -2: rl remz - rl remy - rl remx - rl remw - rl remv - rl remu - rl remt - rl rems - mov w, arg2z - sub w, remz - mov tmp_var, w - mov w, arg2y - subc w, remy - mov tmp_var1, w - mov w, arg2x - subc w, remx - mov tmp_var2, w - mov w, arg2w - subc w, remw - mov tmp_var3, w - mov w, arg2v - subc w, remv - mov tmp_var4, w - mov w, arg2u - subc w, remu - mov tmp_var5, w - mov w, arg2t - subc w, remt - mov tmp_var6, w - mov w, arg2s - subc w, rems - sc - page 1f - jmp 1f - - mov rems, w - mov w, tmp_var6 - mov remt, w - mov w, tmp_var5 - mov remu, w - mov w, tmp_var4 - mov remv, w - mov w, tmp_var3 - mov remw, w - mov w, tmp_var2 - mov remx, w - mov w, tmp_var1 - mov remy, w - mov w, tmp_var - mov remz, w - -1: rl arg1z - rl arg1y - rl arg1x - rl arg1w - rl arg1v - rl arg1u - rl arg1t - rl arg1s - decsz cnt - page 2b - jmp 2b - - pop ress - pop rest - pop resu - pop resv - pop resw - pop resx - pop resy - pop resz - mov w, #8 - add spl, w - ret - - .endfunc - -#undef arg1s -#undef arg1t -#undef arg1u -#undef arg1v -#undef arg1w -#undef arg1x -#undef arg1y -#undef arg1z - -#undef arg2s -#undef arg2t -#undef arg2u -#undef arg2v -#undef arg2w -#undef arg2x -#undef arg2y -#undef arg2z - -#undef ress -#undef rest -#undef resu -#undef resv -#undef resw -#undef resx -#undef resy -#undef resz - -#undef rems -#undef remt -#undef remu -#undef remv -#undef remw -#undef remx -#undef remy -#undef remz - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef tmp_var3 -#undef tmp_var4 -#undef tmp_var5 -#undef tmp_var6 -#undef cnt - -#endif /* defined (L_udivmoddi4) */ - -#define LT #0 -#define EQ #1 -#define GT #2 - -#if defined(L_cmphi2) -#define arg1l 2(sp) -#define arg1h 1(sp) -#define arg2l 4(sp) -#define arg2h 3(sp) - - .sect .text.libgcc,"ax" - .global __cmphi2 - .global __cmp_ret - .global __cmpqi_ret - .func _cmphi2, __cmphi2 - -__cmphi2: - mov w,arg1l - sub w,arg2l - snz - page 2f - jmp 2f - mov w,arg1h -1: - subc w,arg2h - clr arg2l - rl arg2l - snb arg1h,7 - setb arg2l,2 - snb arg2h,7 - setb arg2l,1 - mov w,#3 - -__cmp_ret: - add spl,w ; sign1 - pop wreg ; sign2 - -__cmpqi_ret: - add pcl,w ; carry of arg1 - arg2 - retw GT ; [000] arg1 > arg2 - retw LT ; [001] arg1 < arg2 - retw GT ; [010] arg1 > arg2 - retw GT ; [011] arg1 > arg2 - retw LT ; [100] arg1 < arg2 - retw LT ; [101] arg1 < arg2 - retw GT ; [110] arg1 > arg2 - retw LT ; [111] arg1 < arg2 -2: - mov w,arg1h - cse w,arg2h - page 1b - jmp 1b - mov w,#4 - add spl,w - retw EQ - - .endfunc -#undef arg1l -#undef arg1h -#undef arg2l -#undef arg2h -#endif /* L_cmphi2 */ - -#if defined(L_cmpqi2) -#define arg1 1(sp) -#define arg2 2(sp) - - .sect .text.libgcc,"ax" - .global __cmpqi2 - .func _cmpqi2, __cmpqi2 - -__cmpqi2: - mov w, arg1 - sub w, arg2 - snz - page 2f - jmp 2f - - clr wreg - rl wreg - snb arg1, 7 - setb wreg, 2 - snb arg2, 7 - setb wreg, 1 - inc spl - inc spl - page __cmpqi_ret - jmp __cmpqi_ret - -2: mov w, #2 - add spl, w - retw EQ - - .endfunc -#undef arg1l -#undef arg2l -#endif /* L_cmpqi2 */ - -#if defined(L_cmpsi2) -#define arg1d 4(sp) -#define arg1c 3(sp) -#define arg1b 2(sp) -#define arg1a 1(sp) -#define arg2d 8(sp) -#define arg2c 7(sp) -#define arg2b 6(sp) -#define arg2a 5(sp) - - .sect .text.libgcc,"ax" - .global __cmpsi2 - .func _cmpsi2, __cmpsi2 - -__cmpsi2: - mov w, arg1d - sub w, arg2d - snz - page 2f - jmp 2f - -1: mov w, arg1c - subc w, arg2c - mov w, arg1b - subc w, arg2b - mov w, arg1a - subc w, arg2a - - clr arg2d - rl arg2d - snb arg1a, 7 - setb arg2d, 2 - snb arg2a, 7 - setb arg2d, 1 - mov w, #7 - page __cmp_ret - jmp __cmp_ret - -2: mov w, arg1c - cse w, arg2c - page 1b - jmp 1b - - mov w, arg1b - cse w, arg2b - page 1b - jmp 1b - - mov w, arg1a - cse w, arg2a - page 1b - jmp 1b - - mov w, #8 - add spl, w - retw EQ - - .endfunc - -#undef arg1d -#undef arg1c -#undef arg1b -#undef arg1a -#undef arg2d -#undef arg2c -#undef arg2b -#undef arg2a -#endif /* L_cmpsi2 */ - -#if defined(L_cmpdi2) -#define arg1z 8(sp) -#define arg1y 7(sp) -#define arg1x 6(sp) -#define arg1w 5(sp) -#define arg1v 4(sp) -#define arg1u 3(sp) -#define arg1t 2(sp) -#define arg1s 1(sp) - -#define arg2z 16(sp) -#define arg2y 15(sp) -#define arg2x 14(sp) -#define arg2w 13(sp) -#define arg2v 12(sp) -#define arg2u 11(sp) -#define arg2t 10(sp) -#define arg2s 9(sp) - - .sect .text.libgcc,"ax" - .global __cmpdi2 - .func _cmpdi2, __cmpdi2 - -__cmpdi2: - mov w, arg1z - sub w, arg2z - snz - page 2f - jmp 2f - -1: mov w, arg1y - subc w, arg2y - mov w, arg1x - subc w, arg2x - mov w, arg1w - subc w, arg2w - mov w, arg1v - subc w, arg2v - mov w, arg1u - subc w, arg2u - mov w, arg1t - subc w, arg2t - mov w, arg1s - subc w, arg2s - clr arg2z - rl arg2z - snb arg1s, 7 - setb arg2z, 2 - snb arg2s, 7 - setb arg2z, 1 - mov w, #15 - page __cmp_ret - jmp __cmp_ret - -2: mov w, arg1y - cse w, arg2y - page 1b - jmp 1b - - mov w, arg1x - cse w, arg2x - page 1b - jmp 1b - - mov w, arg1w - cse w, arg2w - page 1b - jmp 1b - - mov w, arg1v - cse w, arg2v - page 1b - jmp 1b - - mov w, arg1u - cse w, arg2u - page 1b - jmp 1b - - mov w, arg1t - cse w, arg2t - page 1b - jmp 1b - - mov w, arg1s - cse w, arg2s - page 1b - jmp 1b - - mov w, #16 - add spl, w - retw EQ - - .endfunc - -#undef arg1z -#undef arg1y -#undef arg1x -#undef arg1w -#undef arg1v -#undef arg1u -#undef arg1t -#undef arg1s -#undef arg2z -#undef arg2y -#undef arg2x -#undef arg2w -#undef arg2v -#undef arg2u -#undef arg2t -#undef arg2s - -#endif /* L_cmpdi2 */ - -#if defined(L_cmpdi2_dp) - .sect .text.libgcc,"ax" - .global __cmpdi2_dp - .func _cmpdi2_dp, __cmpdi2_dp - -__cmpdi2_dp: - push 7(dp) - push 6(dp) - push 5(dp) - push 4(dp) - push 3(dp) - push 2(dp) - push 1(dp) - push (dp) - page __cmpdi2 - jmp __cmpdi2 - - .endfunc -#endif /* L_cmpdi2_dp */ - -#if defined(L_fp_pop_args_ret) - .sect .pram.libgcc,"ax" - .global __fp_pop_args_ret - .global __pop_args_ret - .global __pop2_args_ret - .func __fp_pop2_args_ret, __fp_pop2_args_ret - -__fp_pop2_args_ret: - mov w, #2 -__fp_pop_args_ret: - pop 0xfd - pop 0xfe -__pop_args_ret: - pop callh - pop calll - add spl, w - ret - - .endfunc -#endif /* L_fp_pop_args_ret */ - -#if defined(L__pop2_args_ret) - .sect .pram.libgcc,"ax" - .global __pop2_args_ret - .func __pop2_args_ret, __pop2_args_ret - -__pop2_args_ret: - mov w, #2 - pop callh - pop calll - add spl, w - ret - - .endfunc -#endif /* L__pop2_args_ret */ - -#if defined(L_leaf_fp_pop_args_ret) - .sect .pram.libgcc,"ax" - .global __leaf_fp_pop_args_ret, __leaf_fp_pop2_args_ret - .func __leaf_fp2_pop_args_ret, __leaf_fp_pop2_args_ret - -__leaf_fp_pop2_args_ret: - mov w, #2 -__leaf_fp_pop_args_ret: - pop 0xfd - pop 0xfe - add spl, w - ret - - .endfunc -#endif /* L_leaf_fp_pop_args_ret */ - -#if defined(L_movmemhi_countqi) - .sect .pram.libgcc,"ax" - .global __movmemhi_countqi - .func _movmemhi_countqi, __movmemhi_countqi - -__movmemhi_countqi: - push dph ; Save our pointer regs - push dpl - push iph - push ipl - - mov w, 5(SP) ; Get our dest pointer - mov dph, w - mov w, 6(SP) - mov dpl, w - mov w, 7(SP) ; And our source pointer - mov iph, w - mov w, 8(SP) - mov ipl, w - -1: push (IP) ; *dest++ = *src++ - pop 0(DP) - inc ipl - inc dpl - decsz 9(SP) ; Loop until completed - page 1b - jmp 1b - - pop ipl ; Restore our pointer regs - pop iph - pop dpl - pop dph - - mov w, #5 ; Tidy up our stack args - add spl, w - ret - - .endfunc -#endif - -#if defined(L_movmemhi_counthi) - .sect .text.libgcc,"ax" - .global __movmemhi_counthi - .func _movmemhi_counthi, __movmemhi_counthi - -__movmemhi_counthi: - push dph ; Save our pointer regs - push dpl - push iph - push ipl - - mov w, 5(SP) ; Get our dest pointer - mov dph, w - mov w, 6(SP) - mov dpl, w - mov w, 7(SP) ; And our source pointer - mov iph, w - mov w, 8(SP) - mov ipl, w - - test 10(SP) ; If we have a nonzero LSB then adjust the - sz ; MSB of the loop count to allow us to use - inc 9(SP) ; skip tricks! - -1: push (IP) ; *dest++ = *src++ - pop 0(DP) - inc ipl - inc dpl - decsnz 10(SP) ; Loop until completed - note the skip trick - decsz 9(SP) ; on the MSB! - page 1b - jmp 1b - - pop ipl ; Restore our pointer regs - pop iph - pop dpl - pop dph - - mov w, #6 ; Tidy up our stacked args. - add spl, w - ret - - .endfunc -#endif - -#if defined(L_exit) - .sect .text.libgcc,"ax" - .global __exit - .global _exit - .func _exit, __exit - .weak __exit - .weak _exit - -_exit: -__exit: - pop $88 - pop wreg - or w, $88 - push wreg - push #0 - push #1 - system ; Exit wreg - page __exit ; Never return - jmp __exit - - .endfunc -#endif - -#if defined(Labort) - .sect .text.libgcc,"ax" - .global _abort - .func abort, _abort - -_abort: - push #1 - push #0 - push #1 - system ; Exit 1 - ret - - .endfunc -#endif - -#if defined(Lwrite) - /* Dummy entry point to suppress problems with glue code. */ - .sect .text.libgcc,"ax" - .global _write - .func write, _write -;; -;; write (fil,buf,len) - say that write succeeds.... -;; -_write: - movb $80, 5(SP) - movb $81, 6(SP) ; Return length written - mov w, #6 - add spl, w - ret - - .endfunc -#endif diff --git a/gcc/config/ip2k/t-ip2k b/gcc/config/ip2k/t-ip2k deleted file mode 100644 index f3d93542c3a..00000000000 --- a/gcc/config/ip2k/t-ip2k +++ /dev/null @@ -1,49 +0,0 @@ -LIB1ASMSRC = ip2k/libgcc.S - -LIB1ASMFUNCS = \ - _indcall \ - _mulhi3 \ - _mulsi3 \ - _muldi3 \ - _udivmodhi4 \ - _divmodhi4 \ - _udivmodsi4 \ - _divmodsi4 \ - _udivmoddi4 \ - _divmoddi4 \ - _cmpqi2 \ - _cmphi2 \ - _cmpsi2 \ - _cmpdi2 \ - _cmpdi2_dp \ - _fp_pop_args_ret \ - _pop2_args_ret \ - _leaf_fp_pop_args_ret \ - _movmemhi_countqi \ - _movmemhi_counthi \ - abort \ - _exit - -# libgcc2.h thinks that nobody would have SI mode when -# MIN_UNITS_PER_WORD == 1, so lie to keep from major compiler errors. - -TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -DDF=SF -g -DMIN_UNITS_PER_WORD=2 - -fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/ip2k/t-ip2k crt0.o - echo '#define FLOAT' > fp-bit.c - echo '#define FLOAT_ONLY' >> fp-bit.c - echo '#define DF SF' >> fp-bit.c - echo '#define DI SI' >> fp-bit.c - echo '#define CMPtype QItype' >> fp-bit.c - echo '#define SMALL_MACHINE' >> fp-bit.c - echo 'typedef int QItype __attribute__ ((mode (QI)));' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - - -FPBIT = fp-bit.c - -# Our crt0 is written in assembler and we don't really support profiling. - -CRT0_S = $(srcdir)/config/ip2k/crt0.S -MCRT0_S = $(CRT0_S) - diff --git a/gcc/config/ns32k/NOTES b/gcc/config/ns32k/NOTES deleted file mode 100644 index 32e9704d95f..00000000000 --- a/gcc/config/ns32k/NOTES +++ /dev/null @@ -1,97 +0,0 @@ -Copyright (C) 2002 -Free Software Foundation, Inc. - - Implementation Notes - ==================== - -IEEE floating point comparisons - -Ian Dall <ian@beware.dropbear.id.au> ------------------------------------- - -The ns32x81 fpu handles most operands in hardware, but traps on NaN, -Inf and Denormalized numbers. The correct behavior can be handled by -the trap handler. This is mostly transparent to the compiler, but in -the case of floating point comparisons, the trap handler and the -compiler must co-operate. - -Comparing a Nan with anything (including another Nan) is an unordered -comparison and a NE test should be true and any other test should be -false. There is nothing the trap handler can do to the condition codes -to make, for example ble and bgt (the machine instructions, not the -gcc insn's) both fail. - -The L flag (normally used for unsigned comparisons) is cleared by a floating -point compare. So, it is possible for the trap handler to communicate that -it has seen a NaN by setting this flag. - -This can get confusing so the following documents the reasoning. There -are only 3 flags of significance, N, Z and L. In what follows AB is -the conjunction of A and B ("and") A+B is the disjunction of A and B -("or"), upper case represents true and lower case represents false. So -"Zl" is "Z AND (NOT L)". - -Also, we can require that the trap handler clears N and Z, whenever it -sets L. This means that in many cases, we do not need to test if L is -set or clear. The operations we require are: - - Operator Expression Check L - GT Nl No - LT znl Yes - GE (Z+N)l No - LE nl Yes - EQ Zl No - NE z+L No - - -For example, the emitted code for the case of LT is - - bhi 0f - blt %0 - 0: - -which is, in effect, "branch if ordered and less than." - -We also need insns for the reverse branches. These have the PC and -the label ref operands reversed. Thus the reverse bgt has a pattern: - - (set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) - -This is identical to a normal branch with the test complimented: - - (set (pc) - (if_then_else (not (gt (cc0) - (const_int 0))) - (label_ref (match_operand 0 "" "") - (pc)))) - -Thus we need a family of (NOT cond) tests. For integers this is easy, -a reverse blt becomes bge. However, the possibility of unordered -comparison complicates the floating point case. So, we need to -compliment the above expressions, using deMorgan's theorem, for the reverse -branch: - - Operator Expression Check L - RGT n+L Yes - RLT Z+N+L Yes - RGE zn+L Yes - RLE N+L Yes - REQ z+L No - RNE Zl No - -For example the emitted code for the case of RLT is - - bge %0 - bhi %0 - -which is, in effect "branch if not less than and not unordered." - -These extra comparisons are safe if the trap handler doesn't set the -L flag, since in that case the additional "bhi" instructions are never -taken. Also, these extra branch instructions are controlled by the -"-mieee-compare" option. - diff --git a/gcc/config/ns32k/STATUS b/gcc/config/ns32k/STATUS deleted file mode 100644 index 54672558013..00000000000 --- a/gcc/config/ns32k/STATUS +++ /dev/null @@ -1,68 +0,0 @@ -NS32K Port Status Last updated 19 Dec 2002 - -Recent development of the ns32k port has been as a cross compiler. As -such a native bootstrap has not been performed. Currently the -compiler successfully builds a NetBSD kernel and has been tested on -the testsuite with "make check" configured to remotely execute -tests on a pc532-netbsd. - -There are a few remaining failures in the testsuite, none of which -result in incorrect code generation or unexpected ICEs. - -Here follows comments on the outstanding testsuite failures: - -gcc.c-torture/compile/20001226-1.c, -Os -This typically fails due to a time out or exhausting available memory. -In the past it has been found to eventually compile in under 6 -minutes, with consuming up to 90MB. The timeout in dejagnu is 5 -minutes. - -gcc.c-torture/execute/builtin-constant.c -I don't understand why this fails. Looking at the generated assembler, -the first invocation of btest returns "1" and the second "0". Presumably -the flow analysis is meant to indicate this is a "builtin constant". -The documentation for __builtin_constant says it is allowed to fail if the -compiler can't deduce that something is a constant, so the compiler is -correct if not ideal. - -gcc.dg/debug/debug-1.c scan-assembler xyzzy: -At -O3 level of optimization, variable xyzzy gets eliminated. Isn't it -reasonable that the debugging info is gone too? Indeed, the -documentation says this is expected behavior. - -gcc.dg/debug/debug-2.c scan-assembler xyzzy: -As for the above. - -gcc.dg/20010912-1.c -PIC is supported for the compiler, but we get a link error until we get a -cross linker which can handle dynamic linking. - -gcc.dg/20020304-1.c -O -fssa -fssa-ccp -ICE -fssa and -fssa-ccp are "experimental" options. Assume not a -backend problem. - -gcc.dg/20021014-1.c (test for excess errors) -This is a test of the "-p" option. Fails due to lack of mcrt0.o. This -platform support "-pg" but not "-p" - -gcc.dg/20021018-1.c (test for excess errors) -Fail due to lack of dynamic link support at link time. - -gcc.dg/bitfld-3.c (test for excess errors) -Execution passes, but compilation produces excessive warnings. These warnings -actually seem reasonable. The code uses __attribute__((aligned (8)), and -the maximum alignment which makes any sense for this architecture is 4. - -gcc.dg/duff-2.c (test for excess errors) -Execution passes, but compilation produces excessive warnings. Doesn't look -like a backend problem. - -gcc.dg/uninit-A.c -O2 -Wall -S -Bogus warnings, almost certainly not backend. - -gcc.dg/special/weak-1.c execution test -X This fails for i386 too. I don't understand what the correct behavior -for this test is. - -gcc.dg/special/gcsec-1.c (test for excess errors) -a.out deficiency. -ffunction-sections and -fdata-sections not supported. diff --git a/gcc/config/ns32k/__unorddf2.c b/gcc/config/ns32k/__unorddf2.c deleted file mode 100644 index 27e218c5bb3..00000000000 --- a/gcc/config/ns32k/__unorddf2.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Lightweight function to test for ieee unordered comparison - Copyright (C) 2002 - Free Software Foundation, Inc. - Contributed by Ian Dall <ian@beware.dropbear.id.au> - -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. */ - -# define ISNAN(x) ( \ - { \ - union u { double d; unsigned int i[2]; } *t = (union u *)&(x); \ - ((t->i[1] & 0x7ff00000) == 0x7ff00000) && \ - (t->i[0] != 0 || (t->i[1] & 0xfffff) != 0); \ - }) - -int __unorddf2 (double, double); -int __unorddf2 (double a, double b) -{ - return ISNAN(a) || ISNAN(b); -} diff --git a/gcc/config/ns32k/__unordsf2.c b/gcc/config/ns32k/__unordsf2.c deleted file mode 100644 index 1c186cee4d7..00000000000 --- a/gcc/config/ns32k/__unordsf2.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Lightweight function to test for ieee unordered comparison - Copyright (C) 2002 - Free Software Foundation, Inc. - Contributed by Ian Dall <ian@beware.dropbear.id.au> - -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. */ - -# define ISNAN(x) ( \ - { \ - union u { float f; unsigned int i; } *t = (union u *)&(x); \ - ((t->i & 0x7f800000) == 0x7f800000) && \ - ((t->i & 0x7fffff) != 0); \ - }) - -int __unordsf2 ( float, float); -int __unordsf2 ( float a, float b) -{ - return ISNAN(a) || ISNAN(b); -} diff --git a/gcc/config/ns32k/netbsd.h b/gcc/config/ns32k/netbsd.h deleted file mode 100644 index 04c97262477..00000000000 --- a/gcc/config/ns32k/netbsd.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Configuration for a ns32532 running NetBSD as the target machine. - Copyright (C) 1988, 1994, 1995, 1996, 1998, 2002, 2004, 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. */ - - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - NETBSD_OS_CPP_BUILTINS_AOUT(); \ - builtin_define ("__ns32k__"); \ - } \ - while (0) - -/* Compile for the floating point unit & 32532 by default; - Don't assume SB is zero; - Don't use bit-field instructions; - FPU is 32381; - Use multiply-add instructions */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT \ - (MASK_32532 | MASK_32381 | MASK_IEEE_COMPARE | MASK_MULT_ADD) - -/* 32-bit alignment for efficiency */ - -#undef POINTER_BOUNDARY -#define POINTER_BOUNDARY 32 - -/* 32-bit alignment for efficiency */ - -#undef FUNCTION_BOUNDARY -#define FUNCTION_BOUNDARY 32 - -/* 32532 spec says it can handle any alignment. Rumor from tm-ns32k.h - tells this might not be actually true (but it's for 32032, perhaps - National has fixed the bug for 32532). You might have to change this - if the bug still exists. */ - -#undef STRICT_ALIGNMENT -#define STRICT_ALIGNMENT 0 - -/* Use pc relative addressing whenever possible, - it's more efficient than absolute (ns32k.c) - You have to fix a bug in gas 1.38.1 to make this work with gas, - patch available from jkp@cs.hut.fi. - (NetBSD's gas version has this patch already applied) */ - -#define PC_RELATIVE - -/* Operand of bsr or jsr should be just the address. */ - -#define CALL_MEMREF_IMPLICIT - -/* movd insns may have floating point constant operands. */ - -#define MOVD_FLOAT_OK - -/* Define a CPP_SPEC appropriate for NetBSD. */ - -#undef CPP_SPEC -#define CPP_SPEC NETBSD_CPP_SPEC - -/* Make gcc agree with <machine/ansi.h> */ - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -/* This is BSD, so it wants DBX format. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#define DBX_CONTIN_CHAR '?' - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ - -#undef PCC_STATIC_STRUCT_RETURN -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Until they use ELF or something that handles dwarf2 unwinds - and initialization stuff better. */ -#define DWARF2_UNWIND_INFO 0 diff --git a/gcc/config/ns32k/ns32k-protos.h b/gcc/config/ns32k/ns32k-protos.h deleted file mode 100644 index 6103f8fb3a4..00000000000 --- a/gcc/config/ns32k/ns32k-protos.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions of target machine for GNU compiler. NS32000 version. - Copyright (C) 2000, 2004 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@cygnus.com) - -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. */ - -/* Prototypes for functions in ns32k.c */ - -#ifdef RTX_CODE -extern enum reg_class secondary_reload_class (enum reg_class, - enum machine_mode, rtx); -extern int reg_or_mem_operand (rtx, enum machine_mode); - -extern void split_di (rtx[], int, rtx[], rtx[]); -extern void expand_block_move (rtx[]); -extern int global_symbolic_reference_mentioned_p (rtx, int); -extern void print_operand (FILE *, rtx, int); -extern void print_operand_address (FILE *, rtx); -extern const char *output_move_double (rtx *); -extern const char *output_shift_insn (rtx *); -extern int symbolic_reference_mentioned_p (rtx); -extern void ns32k_notice_update_cc (rtx, rtx); -#endif /* RTX_CODE */ - -#ifdef TREE_CODE -extern int ns32k_return_pops_args (tree, tree, int); -#endif /* TREE_CODE */ - -extern int hard_regno_mode_ok (int, enum machine_mode); -extern int register_move_cost (enum reg_class, enum reg_class); -extern const char *output_move_dconst (int, const char *); diff --git a/gcc/config/ns32k/ns32k.c b/gcc/config/ns32k/ns32k.c deleted file mode 100644 index a8aff906ca9..00000000000 --- a/gcc/config/ns32k/ns32k.c +++ /dev/null @@ -1,1706 +0,0 @@ -/* Subroutines for assembler code output on the NS32000. - Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2004, 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. */ - -#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 "output.h" -#include "insn-attr.h" -#include "tree.h" -#include "function.h" -#include "expr.h" -#include "flags.h" -#include "recog.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" -#include "toplev.h" - -#ifdef OSF_OS -int ns32k_num_files = 0; -#endif - -/* This duplicates reg_class_contents in reg_class.c, but maybe that isn't - initialized in time. Also this is more convenient as an array of ints. - We know that HARD_REG_SET fits in an unsigned int */ - -const unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1] = REG_CLASS_CONTENTS; - -const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = -{ - GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, - GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, - FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS, - FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, - LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS, - LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS, - FRAME_POINTER_REG, STACK_POINTER_REG -}; - -static const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES; - -static bool ns32k_handle_option (size_t, const char *, int); -static rtx gen_indexed_expr (rtx, rtx, rtx); -static const char *singlemove_string (rtx *); -static void move_tail (rtx[], int, int); -static tree ns32k_handle_fntype_attribute (tree *, tree, tree, int, bool *); -const struct attribute_spec ns32k_attribute_table[]; -static void ns32k_output_function_prologue (FILE *, HOST_WIDE_INT); -static void ns32k_output_function_epilogue (FILE *, HOST_WIDE_INT); -static bool ns32k_rtx_costs (rtx, int, int, int *); -static int ns32k_address_cost (rtx); -static rtx ns32k_struct_value_rtx (tree, int); -static int ns32k_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); - -/* Initialize the GCC target structure. */ -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table - -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" - -#ifdef ENCORE_ASM -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP "\t.double\t" -#endif - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue - -#undef TARGET_DEFAULT_TARGET_FLAGS -#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT -#undef TARGET_HANDLE_OPTION -#define TARGET_HANDLE_OPTION ns32k_handle_option - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS ns32k_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST ns32k_address_cost - -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX ns32k_struct_value_rtx - -#undef TARGET_ARG_PARTIAL_BYTES -#define TARGET_ARG_PARTIAL_BYTES ns32k_arg_partial_bytes - -#undef TARGET_ASM_FILE_START_APP_OFF -#define TARGET_ASM_FILE_START_APP_OFF true - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Implement TARGET_HANDLE_OPTION. */ - -static bool -ns32k_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, - int value ATTRIBUTE_UNUSED) -{ - switch (code) - { - case OPT_m32081: - target_flags &= ~MASK_32381; - return true; - - case OPT_msoft_float: - target_flags &= ~(MASK_32081 | MASK_32381); - return true; - - case OPT_m32332: - target_flags &= ~MASK_32532; - return true; - - case OPT_m32032: - target_flags &= ~(MASK_32332 | MASK_32532); - return true; - - default: - return true; - } -} - -/* Generate the assembly code for function entry. FILE is a stdio - stream to output the code to. SIZE is an int: how many units of - temporary storage to allocate. - - Refer to the array `regs_ever_live' to determine which registers to - save; `regs_ever_live[I]' is nonzero if register number I is ever - used in the function. This function is responsible for knowing - which registers should not be saved even if used. */ - -/* - * The function prologue for the ns32k is fairly simple. - * If a frame pointer is needed (decided in reload.c ?) then - * we need assembler of the form - * - * # Save the oldframe pointer, set the new frame pointer, make space - * # on the stack and save any general purpose registers necessary - * - * enter [<general purpose regs to save>], <local stack space> - * - * movf fn, tos # Save any floating point registers necessary - * . - * . - * - * If a frame pointer is not needed we need assembler of the form - * - * # Make space on the stack - * - * adjspd <local stack space + 4> - * - * # Save any general purpose registers necessary - * - * save [<general purpose regs to save>] - * - * movf fn, tos # Save any floating point registers necessary - * . - * . - */ - -#if !defined (MERLIN_TARGET) && !defined (UTEK_ASM) - -#if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX -#define ADJSP(FILE, N) \ - fprintf (FILE, "\tadjspd %c" HOST_WIDE_INT_PRINT_DEC "\n", IMMEDIATE_PREFIX, (N)) -#else -#define ADJSP(FILE, N) \ - fprintf (FILE, "\tadjspd " HOST_WIDE_INT_PRINT_DEC "\n", (N)) -#endif - -static void -ns32k_output_function_prologue (FILE *file, HOST_WIDE_INT size) -{ - register int regno, g_regs_used = 0; - int used_regs_buf[8], *bufp = used_regs_buf; - int used_fregs_buf[17], *fbufp = used_fregs_buf; - - for (regno = R0_REGNUM; regno < F0_REGNUM; regno++) - if (regs_ever_live[regno] - && ! call_used_regs[regno]) - { - *bufp++ = regno; g_regs_used++; - } - *bufp = -1; - - for (; regno < FRAME_POINTER_REGNUM; regno++) - if (regs_ever_live[regno] && !call_used_regs[regno]) - { - *fbufp++ = regno; - } - *fbufp = -1; - - bufp = used_regs_buf; - if (frame_pointer_needed) - fprintf (file, "\tenter ["); - else - { - if (size) - ADJSP (file, size + 4); - if (g_regs_used && g_regs_used > 4) - fprintf (file, "\tsave ["); - else - { - while (*bufp >= 0) - fprintf (file, "\tmovd r%d,tos\n", *bufp++); - g_regs_used = 0; - } - } - - while (*bufp >= 0) - { - fprintf (file, "r%d", *bufp++); - if (*bufp >= 0) - fputc (',', file); - } - - if (frame_pointer_needed) - fprintf (file, "]," HOST_WIDE_INT_PRINT_DEC "\n", size); - else if (g_regs_used) - fprintf (file, "]\n"); - - fbufp = used_fregs_buf; - while (*fbufp >= 0) - { - if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) - fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]); - else - { - fprintf (file, "\tmovl %s,tos\n", - ns32k_out_reg_names[fbufp[0]]); - fbufp += 2; - } - } - - if (flag_pic && current_function_uses_pic_offset_table) - { - fprintf (file, "\tsprd sb,tos\n"); - if (TARGET_REGPARM) - { - fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n"); - fprintf (file, "\tlprd sb,tos\n"); - } - else - { - fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n"); - fprintf (file, "\tlprd sb,r0\n"); - } - } -} - -#else /* MERLIN_TARGET || UTEK_ASM */ - -/* This differs from the standard one above in printing a bitmask - rather than a register list in the enter or save instruction. */ - -static void -ns32k_output_function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size; -{ - register int regno, g_regs_used = 0; - int used_regs_buf[8], *bufp = used_regs_buf; - int used_fregs_buf[8], *fbufp = used_fregs_buf; - - for (regno = 0; regno < 8; regno++) - if (regs_ever_live[regno] - && ! call_used_regs[regno]) - { - *bufp++ = regno; g_regs_used++; - } - *bufp = -1; - - for (; regno < 16; regno++) - if (regs_ever_live[regno] && !call_used_regs[regno]) { - *fbufp++ = regno; - } - *fbufp = -1; - - bufp = used_regs_buf; - if (frame_pointer_needed) - fprintf (file, "\tenter "); - else if (g_regs_used) - fprintf (file, "\tsave "); - - if (frame_pointer_needed || g_regs_used) - { - char mask = 0; - while (*bufp >= 0) - mask |= 1 << *bufp++; - fprintf (file, "$0x%x", (int) mask & 0xff); - } - - if (frame_pointer_needed) -#ifdef UTEK_ASM - fprintf (file, ",$%d\n", size); -#else - fprintf (file, ",%d\n", size); -#endif - else if (g_regs_used) - fprintf (file, "\n"); - - fbufp = used_fregs_buf; - while (*fbufp >= 0) - { - if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) - fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8); - else - { - fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8); - fbufp += 2; - } - } -} - -#endif /* MERLIN_TARGET || UTEK_ASM */ - -/* This function generates the assembly code for function exit, - on machines that need it. - - The function epilogue should not depend on the current stack pointer, - if EXIT_IGNORE_STACK is nonzero. That doesn't apply here. - - If a frame pointer is needed (decided in reload.c ?) then - we need assembler of the form - - movf tos, fn # Restore any saved floating point registers - . - . - - # Restore any saved general purpose registers, restore the stack - # pointer from the frame pointer, restore the old frame pointer. - exit [<general purpose regs to save>] - - If a frame pointer is not needed we need assembler of the form - # Restore any general purpose registers saved - - movf tos, fn # Restore any saved floating point registers - . - . - . - restore [<general purpose regs to save>] - - # reclaim space allocated on stack - - adjspd <-(local stack space + 4)> */ - -#if !defined (MERLIN_TARGET) && !defined (UTEK_ASM) - -static void -ns32k_output_function_epilogue (FILE *file, HOST_WIDE_INT size) -{ - register int regno, g_regs_used = 0, f_regs_used = 0; - int used_regs_buf[8], *bufp = used_regs_buf; - int used_fregs_buf[17], *fbufp = used_fregs_buf; - - if (flag_pic && current_function_uses_pic_offset_table) - fprintf (file, "\tlprd sb,tos\n"); - - *fbufp++ = -2; - for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++) - if (regs_ever_live[regno] && !call_used_regs[regno]) - { - *fbufp++ = regno; f_regs_used++; - } - fbufp--; - - for (regno = 0; regno < F0_REGNUM; regno++) - if (regs_ever_live[regno] - && ! call_used_regs[regno]) - { - *bufp++ = regno; g_regs_used++; - } - - while (fbufp > used_fregs_buf) - { - if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) - { - fprintf (file, "\tmovl tos,%s\n", - ns32k_out_reg_names[fbufp[-1]]); - fbufp -= 2; - } - else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]); - } - - if (frame_pointer_needed) - fprintf (file, "\texit ["); - else - { - if (g_regs_used && g_regs_used > 4) - fprintf (file, "\trestore ["); - else - { - while (bufp > used_regs_buf) - fprintf (file, "\tmovd tos,r%d\n", *--bufp); - g_regs_used = 0; - } - } - - while (bufp > used_regs_buf) - { - fprintf (file, "r%d", *--bufp); - if (bufp > used_regs_buf) - fputc (',', file); - } - - if (g_regs_used || frame_pointer_needed) - fprintf (file, "]\n"); - - if (size && !frame_pointer_needed) - ADJSP (file, -(size + 4)); - - if (current_function_pops_args) - fprintf (file, "\tret %d\n", current_function_pops_args); - else - fprintf (file, "\tret 0\n"); -} - -#else /* MERLIN_TARGET || UTEK_ASM */ - -/* This differs from the standard one above in printing a bitmask - rather than a register list in the exit or restore instruction. */ - -static void -ns32k_output_function_epilogue (file, size) - FILE *file; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - register int regno, g_regs_used = 0, f_regs_used = 0; - int used_regs_buf[8], *bufp = used_regs_buf; - int used_fregs_buf[8], *fbufp = used_fregs_buf; - - *fbufp++ = -2; - for (regno = 8; regno < 16; regno++) - if (regs_ever_live[regno] && !call_used_regs[regno]) { - *fbufp++ = regno; f_regs_used++; - } - fbufp--; - - for (regno = 0; regno < 8; regno++) - if (regs_ever_live[regno] - && ! call_used_regs[regno]) - { - *bufp++ = regno; g_regs_used++; - } - - while (fbufp > used_fregs_buf) - { - if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) - { - fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8); - fbufp -= 2; - } - else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8); - } - - if (frame_pointer_needed) - fprintf (file, "\texit "); - else if (g_regs_used) - fprintf (file, "\trestore "); - - if (g_regs_used || frame_pointer_needed) - { - char mask = 0; - - while (bufp > used_regs_buf) - { - /* Utek assembler takes care of reversing this */ - mask |= 1 << *--bufp; - } - fprintf (file, "$0x%x\n", (int) mask & 0xff); - } - -#ifdef UTEK_ASM - if (current_function_pops_args) - fprintf (file, "\tret $%d\n", current_function_pops_args); - else - fprintf (file, "\tret $0\n"); -#else - if (current_function_pops_args) - fprintf (file, "\tret %d\n", current_function_pops_args); - else - fprintf (file, "\tret 0\n"); -#endif -} - -#endif /* MERLIN_TARGET || UTEK_ASM */ - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ -int -hard_regno_mode_ok (int regno, enum machine_mode mode) -{ - int size = GET_MODE_UNIT_SIZE (mode); - - if (FLOAT_MODE_P (mode)) - { - if (size == UNITS_PER_WORD && regno < L1_REGNUM) - return 1; - if (size == UNITS_PER_WORD * 2 - && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM))) - return 1; - return 0; - } - if (size == UNITS_PER_WORD * 2 - && (regno & 1) == 0 && regno < F0_REGNUM) - return 1; - if (size <= UNITS_PER_WORD - && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM - || regno == STACK_POINTER_REGNUM)) - return 1; - return 0; -} - -static bool -ns32k_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total) -{ - switch (code) - { - case CONST_INT: - if (INTVAL (x) <= 7 && INTVAL (x) >= -8) - *total = 0; - else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000) - *total = 1; - else - *total = 3; - return true; - - case CONST: - case LABEL_REF: - case SYMBOL_REF: - *total = 3; - return true; - - case CONST_DOUBLE: - *total = 5; - return true; - - default: - return false; - } -} - -int -register_move_cost (enum reg_class CLASS1, enum reg_class CLASS2) -{ - if (CLASS1 == NO_REGS || CLASS2 == NO_REGS) - return 2; - if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS)) - || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS))) - return 8; - if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS)) - || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS))) - return 6; - if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS)) - || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS))) - return 6; - return 2; -} - -#if 0 -/* We made the insn definitions copy from floating point to general - registers via the stack. */ -int -secondary_memory_needed (enum reg_class CLASS1, - enum reg_class CLASS2, - enum machine_mode M) -{ - int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS)) - || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS))); - return ret; -} -#endif - - -/* TARGET_ADDRESS_COST calls this. This function is not optimal - for the 32032 & 32332, but it probably is better than - the default. */ - -static int -ns32k_address_cost (rtx operand) -{ - int cost = 0; - - switch (GET_CODE (operand)) - { - case REG: - cost += 1; - break; - - case POST_DEC: - case PRE_DEC: - break; - - case CONST_INT: - if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8) - break; - if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000) - { - cost +=1; - break; - } - case CONST: - case LABEL_REF: - case SYMBOL_REF: - cost +=3; - break; - case CONST_DOUBLE: - cost += 5; - break; - - case MEM: - cost += ns32k_address_cost (XEXP (operand, 0)) + 3; - break; - - case MULT: - cost += 2; - /* FALLTHRU */ - case PLUS: - cost += ns32k_address_cost (XEXP (operand, 0)); - cost += ns32k_address_cost (XEXP (operand, 1)); - break; - - default: - break; - } - - return cost; -} - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -enum reg_class -secondary_reload_class (enum reg_class class, - enum machine_mode mode ATTRIBUTE_UNUSED, - rtx in) -{ - int regno = true_regnum (in); - - if (regno >= FIRST_PSEUDO_REGISTER) - regno = -1; - - if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM) - || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM)) - return GENERAL_REGS; - else - return NO_REGS; -} - -/* Generate the rtx that comes from an address expression in the md file */ -/* The expression to be build is BASE[INDEX:SCALE]. To recognize this, - scale must be converted from an exponent (from ASHIFT) to a - multiplier (for MULT). */ - -static rtx -gen_indexed_expr (rtx base, rtx index, rtx scale) -{ - rtx addr; - - /* This generates an invalid addressing mode, if BASE is - fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */ - if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT) - base = gen_rtx_MEM (SImode, base); - addr = gen_rtx_MULT (SImode, index, - GEN_INT (1 << INTVAL (scale))); - addr = gen_rtx_PLUS (SImode, base, addr); - return addr; -} - - -/* Split one or more DImode RTL references into pairs of SImode - references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to - split and "num" is its length. lo_half and hi_half are output arrays - that parallel "operands". */ - -void -split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) -{ - while (num--) - { - if (GET_CODE (operands[num]) == REG) - { - lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num])); - hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1); - } - else if (CONSTANT_P (operands[num])) - { - split_double (operands[num], &lo_half[num], &hi_half[num]); - } - else if (offsettable_memref_p (operands[num])) - { - lo_half[num] = operands[num]; - hi_half[num] = adjust_address (operands[num], SImode, 4); - } - else - abort (); - } -} - -/* Return the best assembler insn template - for moving operands[1] into operands[0] as a fullword. */ - -static const char * -singlemove_string (rtx *operands) -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) <= 7 - && INTVAL (operands[1]) >= -8) - return "movqd %1,%0"; - return "movd %1,%0"; -} - -const char * -output_move_double (rtx *operands) -{ - enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1; - rtx latehalf[2]; - - /* First classify both operands. */ - - if (REG_P (operands[0])) - optype0 = REGOP; - else if (offsettable_memref_p (operands[0])) - optype0 = OFFSOP; - else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - optype0 = PUSHOP; - else - optype0 = RNDOP; - - if (REG_P (operands[1])) - optype1 = REGOP; - else if (CONSTANT_P (operands[1]) - || GET_CODE (operands[1]) == CONST_DOUBLE) - optype1 = CNSTOP; - else if (offsettable_memref_p (operands[1])) - optype1 = OFFSOP; - else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) - optype1 = PUSHOP; - else - optype1 = RNDOP; - - /* Check for the cases that the operand constraints are not - supposed to allow to happen. Abort if we get one, - because generating code for these cases is painful. */ - - if (optype0 == RNDOP || optype1 == RNDOP) - abort (); - - /* Ok, we can do one word at a time. - Normally we do the low-numbered word first, - but if either operand is autodecrementing then we - do the high-numbered word first. - - In either case, set up in LATEHALF the operands to use - for the high-numbered word and in some cases alter the - operands in OPERANDS to be suitable for the low-numbered word. */ - - if (optype0 == REGOP) - latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else if (optype0 == OFFSOP) - latehalf[0] = adjust_address (operands[0], SImode, 4); - else - latehalf[0] = operands[0]; - - if (optype1 == REGOP) - latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); - else if (optype1 == OFFSOP) - latehalf[1] = adjust_address (operands[1], SImode, 4); - else if (optype1 == CNSTOP) - split_double (operands[1], &operands[1], &latehalf[1]); - else - latehalf[1] = operands[1]; - - /* If insn is effectively movd N(sp),tos then we will do the - high word first. We should use the adjusted operand 1 (which is N+4(sp)) - for the low word as well, to compensate for the first decrement of sp. - Given this, it doesn't matter which half we do "first". */ - if (optype0 == PUSHOP - && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM - && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) - operands[1] = latehalf[1]; - - /* If one or both operands autodecrementing, - do the two words, high-numbered first. */ - else if (optype0 == PUSHOP || optype1 == PUSHOP) - { - output_asm_insn (singlemove_string (latehalf), latehalf); - return singlemove_string (operands); - } - - /* If the first move would clobber the source of the second one, - do them in the other order. */ - - /* Overlapping registers. */ - if (optype0 == REGOP && optype1 == REGOP - && REGNO (operands[0]) == REGNO (latehalf[1])) - { - /* Do that word. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - /* Do low-numbered word. */ - return singlemove_string (operands); - } - /* Loading into a register which overlaps a register used in the address. */ - else if (optype0 == REGOP && optype1 != REGOP - && reg_overlap_mentioned_p (operands[0], operands[1])) - { - if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) - && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) - { - /* If both halves of dest are used in the src memory address, - load the destination address into the low reg (operands[0]). - Then it works to load latehalf first. */ - rtx xops[2]; - xops[0] = XEXP (operands[1], 0); - xops[1] = operands[0]; - output_asm_insn ("addr %a0,%1", xops); - operands[1] = gen_rtx_MEM (DImode, operands[0]); - latehalf[1] = adjust_address (operands[1], SImode, 4); - /* The first half has the overlap, Do the late half first. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - /* Then clobber. */ - return singlemove_string (operands); - } - if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) - { - /* The first half has the overlap, Do the late half first. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - /* Then clobber. */ - return singlemove_string (operands); - } - } - - /* Normal case. Do the two words, low-numbered first. */ - - output_asm_insn (singlemove_string (operands), operands); - - operands[0] = latehalf[0]; - operands[1] = latehalf[1]; - return singlemove_string (operands); -} - - -#define MAX_UNALIGNED_COPY (32) -/* Expand string/block move operations. - - operands[0] is the pointer to the destination. - operands[1] is the pointer to the source. - operands[2] is the number of bytes to move. - operands[3] is the alignment. */ - -static void -move_tail (rtx operands[], int bytes, int offset) -{ - if (bytes & 2) - { - emit_move_insn (adjust_address (operands[0], HImode, offset), - adjust_address (operands[1], HImode, offset)); - offset += 2; - } - if (bytes & 1) - emit_move_insn (adjust_address (operands[0], QImode, offset), - adjust_address (operands[1], QImode, offset)); -} - -void -expand_block_move (rtx operands[]) -{ - rtx bytes_rtx = operands[2]; - rtx align_rtx = operands[3]; - int constp = (GET_CODE (bytes_rtx) == CONST_INT); - int bytes = (constp ? INTVAL (bytes_rtx) : 0); - int align = INTVAL (align_rtx); - rtx src_reg = gen_rtx_REG (Pmode, 1); - rtx dest_reg = gen_rtx_REG (Pmode, 2); - rtx count_reg = gen_rtx_REG (SImode, 0); - - if (constp && bytes <= 0) - return; - - if (constp && bytes < 20) - { - int words = bytes >> 2; - - if (words) - { - if (words < 3) - { - int offset = 0; - - for (; words; words--, offset += 4) - emit_move_insn (adjust_address (operands[0], SImode, offset), - adjust_address (operands[1], SImode, offset)); - } - else - { - /* Use movmd. It is slower than multiple movd's but more - compact. It is also slower than movsd for large copies - but causes less registers reloading so is better than movsd - for small copies. */ - rtx src, dest; - dest = copy_addr_to_reg (XEXP (operands[0], 0)); - src = copy_addr_to_reg (XEXP (operands[1], 0)); - - emit_insn (gen_movmemsi2(dest, src, GEN_INT (words))); - } - } - move_tail (operands, bytes & 3, bytes & ~3); - return; - } - - if (align > UNITS_PER_WORD) - align = UNITS_PER_WORD; - - /* Move the address into scratch registers. */ - emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg)); - emit_move_insn (dest_reg, XEXP (operands[0], 0)); - operands[0] = gen_rtx_MEM (SImode, dest_reg); - emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg)); - emit_move_insn (src_reg, XEXP (operands[1], 0)); - operands[1] = gen_rtx_MEM (SImode, src_reg); - emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg)); - - if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY)) - { - /* constant no of bytes and aligned or small enough copy to not bother - * aligning. Emit insns to copy by words. - */ - if (bytes >> 2) - { - emit_move_insn (count_reg, GEN_INT (bytes >> 2)); - emit_insn (gen_movmemsi1 (GEN_INT (4))); - } - /* insns to copy rest */ - move_tail (operands, bytes & 3, 0); - } - else if (align == UNITS_PER_WORD) - { - /* insns to copy by words */ - emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, const2_rtx)); - emit_insn (gen_movmemsi1 (GEN_INT (4))); - if (constp) - { - move_tail (operands, bytes & 3, 0); - } - else - { - /* insns to copy rest */ - emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3))); - emit_insn (gen_movmemsi1 (const1_rtx)); - } - } - else - { - /* Not aligned and we may have a lot to copy so it is worth - * aligning. - */ - rtx aligned_label = gen_label_rtx (); - rtx bytes_reg; - - bytes_reg = copy_to_mode_reg (SImode, bytes_rtx); - if (!constp) - { - /* Emit insns to test and skip over the alignment if it is - * not worth it. This doubles as a test to ensure that the alignment - * operation can't copy too many bytes - */ - emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY))); - emit_jump_insn (gen_blt (aligned_label)); - } - - /* Emit insns to do alignment at run time */ - emit_insn (gen_negsi2 (count_reg, src_reg)); - emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3))); - emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg)); - emit_insn (gen_movmemsi1 (const1_rtx)); - if (!constp) - emit_label (aligned_label); - - /* insns to copy by words */ - emit_insn (gen_lshrsi3 (count_reg, bytes_reg, const2_rtx)); - emit_insn (gen_movmemsi1 (GEN_INT (4))); - - /* insns to copy rest */ - emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3))); - emit_insn (gen_movmemsi1 (const1_rtx)); - } -} - - -/* Returns 1 if OP contains a global symbol reference */ - -int -global_symbolic_reference_mentioned_p (rtx op, int f) -{ - register const char *fmt; - register int i; - - if (GET_CODE (op) == SYMBOL_REF) - { - if (! SYMBOL_REF_LOCAL_P (op)) - return 1; - else - return 0; - } - else if (f && GET_CODE (op) != CONST) - return 0; - - fmt = GET_RTX_FORMAT (GET_CODE (op)); - for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) - { - if (fmt[i] == 'E') - { - register int j; - - for (j = XVECLEN (op, i) - 1; j >= 0; j--) - if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0)) - return 1; - } - else if (fmt[i] == 'e' - && global_symbolic_reference_mentioned_p (XEXP (op, i), 0)) - return 1; - } - - return 0; -} - - -/* Returns 1 if OP contains a symbol reference */ - -int -symbolic_reference_mentioned_p (rtx op) -{ - register const char *fmt; - register int i; - - if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) - return 1; - - fmt = GET_RTX_FORMAT (GET_CODE (op)); - for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) - { - if (fmt[i] == 'E') - { - register int j; - - for (j = XVECLEN (op, i) - 1; j >= 0; j--) - if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) - return 1; - } - else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) - return 1; - } - - return 0; -} - -/* Table of machine-specific attributes. */ - -const struct attribute_spec ns32k_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - /* Stdcall attribute says callee is responsible for popping arguments - if they are not variable. */ - { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute }, - /* Cdecl attribute says the callee is a normal C declaration */ - { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - -/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL; - arguments as in struct attribute_spec.handler. */ -static tree -ns32k_handle_fntype_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FUNCTION_TYPE - && TREE_CODE (*node) != FIELD_DECL - && TREE_CODE (*node) != TYPE_DECL) - { - warning (OPT_Wattributes, "%qs attribute only applies to functions", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; -} - - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. - - On the ns32k, the RET insn may be used to pop them if the number - of args is fixed, but if the number is variable then the caller - must pop them all. RET can't be used for library calls now - because the library is compiled with the Unix compiler. - Use of RET is a selectable option, since it is incompatible with - standard Unix calling sequences. If the option is not selected, - the caller must always pop the args. - - The attribute stdcall is equivalent to RET on a per module basis. */ - -int -ns32k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED, tree funtype, int size) -{ - int rtd = TARGET_RTD; - - if (TREE_CODE (funtype) == IDENTIFIER_NODE) - return rtd ? size : 0; - - /* Cdecl functions override -mrtd, and never pop the stack */ - if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) - return 0; - - /* Stdcall functions will pop the stack if not variable args */ - if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))) - rtd = 1; - - if (rtd) - { - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)) - return size; - } - - return 0; -} - -/* PRINT_OPERAND is defined to call this function, - which is easier to debug than putting all the code in - a macro definition in ns32k.h. */ - -/* XXX time 12% of cpu time is in fprintf for non optimizing */ -void -print_operand (FILE *file, rtx x, int code) -{ - if (code == '$') - PUT_IMMEDIATE_PREFIX (file); - else if (code == '?') - PUT_EXTERNAL_PREFIX (file); - else if (GET_CODE (x) == REG) - fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]); - else if (GET_CODE (x) == MEM) - { - output_address (XEXP (x, 0)); - } - else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode) - { - REAL_VALUE_TYPE r; - - REAL_VALUE_FROM_CONST_DOUBLE (r, x); - PUT_IMMEDIATE_PREFIX (file); - if (GET_MODE (x) == DFmode) - { -#ifdef SEQUENT_ASM - /* Sequent likes its floating point constants as integers */ - long l[2]; - REAL_VALUE_TO_TARGET_DOUBLE (r, l); - fprintf (file, "0Dx%08x%08x", - l[!WORDS_BIG_ENDIAN], l[WORDS_BIG_ENDIAN]); -#else - char s[30]; - real_to_decimal (s, &r, sizeof (s), 0, 1); -#ifdef ENCORE_ASM - fprintf (file, "0f%s", s); -#else - fprintf (file, "0d%s", s); -#endif -#endif - } - else - { -#ifdef SEQUENT_ASM - long l; - REAL_VALUE_TO_TARGET_SINGLE (r, l); - fprintf (file, "0Fx%08lx", l); -#else - char s[30]; - real_to_decimal (s, &r, sizeof (s), 0, 1); - fprintf (file, "0f%s", s); -#endif - } - } - else - { - if (flag_pic - && GET_CODE (x) == CONST - && symbolic_reference_mentioned_p (x)) - { - fprintf (stderr, "illegal constant for pic-mode: \n"); - print_rtl (stderr, x); - fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n", - GET_CODE (x), CONST, symbolic_reference_mentioned_p (x)); - abort (); - } - else if (flag_pic - && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)) - { - output_addr_const (file, x); - fprintf (file, "(sb)"); - } - else - { -#ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC - if (GET_CODE (x) == CONST_INT) -#endif - PUT_IMMEDIATE_PREFIX (file); - output_addr_const (file, x); - } - } -} - -/* PRINT_OPERAND_ADDRESS is defined to call this function, - which is easier to debug than putting all the code in - a macro definition in ns32k.h . */ - -/* Completely rewritten to get this to work with Gas for PC532 Mach. - This function didn't work and I just wasn't able (nor very willing) to - figure out how it worked. - 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */ - -void -print_operand_address (register FILE *file, register rtx addr) -{ - static const char scales[] = { 'b', 'w', 'd', 0, 'q', }; - rtx offset, base, indexexp, tmp; - int scale; - extern int flag_pic; - - if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC) - { - fprintf (file, "tos"); - return; - } - - offset = NULL; - base = NULL; - indexexp = NULL; - while (addr != NULL) - { - if (GET_CODE (addr) == PLUS) - { - if (GET_CODE (XEXP (addr, 0)) == PLUS) - { - tmp = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - else - { - tmp = XEXP (addr,0); - addr = XEXP (addr,1); - } - } - else - { - tmp = addr; - addr = NULL; - } - switch (GET_CODE (tmp)) - { - case PLUS: - abort (); - case MEM: - if (base) - { - indexexp = base; - base = tmp; - } - else - base = tmp; - break; - case REG: - if (REGNO (tmp) < F0_REGNUM) - if (base) - { - indexexp = tmp; - } - else - base = tmp; - else - if (base) - { - indexexp = base; - base = tmp; - } - else - base = tmp; - break; - case MULT: - indexexp = tmp; - break; - case SYMBOL_REF: - if (flag_pic && ! SYMBOL_REF_LOCAL_P (tmp)) - { - if (base) - { - if (indexexp) - abort (); - indexexp = base; - } - base = tmp; - break; - } - case CONST: - if (flag_pic && GET_CODE (tmp) == CONST) - { - rtx sym, off, tmp1; - tmp1 = XEXP (tmp,0); - if (GET_CODE (tmp1) != PLUS) - abort (); - - sym = XEXP (tmp1,0); - if (GET_CODE (sym) != SYMBOL_REF) - { - off = sym; - sym = XEXP (tmp1,1); - } - else - off = XEXP (tmp1,1); - if (GET_CODE (sym) == SYMBOL_REF) - { - if (GET_CODE (off) != CONST_INT) - abort (); - - if (! SYMBOL_REF_LOCAL_P (sym)) - { - if (base) - { - if (indexexp) - abort (); - - indexexp = base; - } - - if (offset != 0) - abort (); - - base = sym; - offset = off; - break; - } - } - } - case CONST_INT: - case LABEL_REF: - if (offset) - offset = gen_rtx_PLUS (SImode, tmp, offset); - else - offset = tmp; - break; - default: - abort (); - } - } - if (! offset) - offset = const0_rtx; - - if (base -#ifndef INDEX_RATHER_THAN_BASE - && (flag_pic || TARGET_HIMEM) - && GET_CODE (base) != SYMBOL_REF - && GET_CODE (offset) != CONST_INT -#else - /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */ -#endif - && !indexexp && GET_CODE (base) == REG - && REG_OK_FOR_INDEX_P (base)) - { - indexexp = base; - base = NULL; - } - - /* now, offset, base and indexexp are set */ -#ifndef BASE_REG_NEEDED - if (! base) - { -#if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC) - if (GET_CODE (offset) == CONST_INT) -#endif - PUT_ABSOLUTE_PREFIX (file); - } -#endif - - output_addr_const (file, offset); - if (base) /* base can be (REG ...) or (MEM ...) */ - switch (GET_CODE (base)) - { - /* now we must output base. Possible alternatives are: - (rN) (REG ...) - (sp) (REG ...) - (fp) (REG ...) - (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output - (disp(fp)) (MEM ...) just before possible [rX:y] - (disp(sp)) (MEM ...) - (disp(sb)) (MEM ...) - */ - case REG: - fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]); - break; - case SYMBOL_REF: - if (! flag_pic) - abort (); - - fprintf (file, "("); - output_addr_const (file, base); - fprintf (file, "(sb))"); - break; - case MEM: - addr = XEXP (base,0); - base = NULL; - offset = NULL; - while (addr != NULL) - { - if (GET_CODE (addr) == PLUS) - { - if (GET_CODE (XEXP (addr, 0)) == PLUS) - { - tmp = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - else - { - tmp = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - } - else - { - tmp = addr; - addr = NULL; - } - switch (GET_CODE (tmp)) - { - case REG: - base = tmp; - break; - case CONST: - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - if (offset) - offset = gen_rtx_PLUS (SImode, tmp, offset); - else - offset = tmp; - break; - default: - abort (); - } - } - if (! offset) - offset = const0_rtx; - fprintf (file, "("); - output_addr_const (file, offset); - if (base) - fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]); - else if (TARGET_SB) - fprintf (file, "(sb)"); - else - abort (); - fprintf (file, ")"); - break; - default: - abort (); - } -#ifdef PC_RELATIVE - else if (GET_CODE (offset) != CONST_INT) - fprintf (file, "(pc)"); -#ifdef BASE_REG_NEEDED - else if (TARGET_SB) - fprintf (file, "(sb)"); - else - abort (); -#endif -#endif /* PC_RELATIVE */ - - /* now print index if we have one */ - if (indexexp) - { - if (GET_CODE (indexexp) == MULT) - { - scale = INTVAL (XEXP (indexexp, 1)) >> 1; - indexexp = XEXP (indexexp, 0); - } - else - scale = 0; - if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM) - abort (); - -#ifdef UTEK_ASM - fprintf (file, "[%c`%s]", - scales[scale], - ns32k_out_reg_names[REGNO (indexexp)]); -#else - fprintf (file, "[%s:%c]", - ns32k_out_reg_names[REGNO (indexexp)], - scales[scale]); -#endif - } -} - -/* National 32032 shifting is so bad that we can get - better performance in many common cases by using other - techniques. */ -const char * -output_shift_insn (rtx *operands) -{ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= 3) - { - if (GET_CODE (operands[0]) == REG) - { - if (GET_CODE (operands[1]) == REG) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - { - if (operands[2] == const1_rtx) - return "addd %0,%0"; - else if (INTVAL (operands[2]) == 2) - return "addd %0,%0\n\taddd %0,%0"; - } - if (operands[2] == const1_rtx) - return "movd %1,%0\n\taddd %0,%0"; - - operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]); - return "addr %a1,%0"; - } - if (operands[2] == const1_rtx) - return "movd %1,%0\n\taddd %0,%0"; - } - else if (GET_CODE (operands[1]) == REG) - { - operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]); - return "addr %a1,%0"; - } - else if (INTVAL (operands[2]) == 1 - && GET_CODE (operands[1]) == MEM - && rtx_equal_p (operands [0], operands[1])) - { - rtx temp = XEXP (operands[1], 0); - - if (GET_CODE (temp) == REG - || (GET_CODE (temp) == PLUS - && GET_CODE (XEXP (temp, 0)) == REG - && GET_CODE (XEXP (temp, 1)) == CONST_INT)) - return "addd %0,%0"; - } - else return "ashd %2,%0"; - } - return "ashd %2,%0"; -} - -const char * -output_move_dconst (int n, const char *s) -{ - static char r[32]; - - if (n > -9 && n < 8) - strcpy (r, "movqd "); - else if (n > 0 && n < 256) - strcpy (r, "movzbd "); - else if (n > 0 && n < 65536) - strcpy (r, "movzwd "); - else if (n < 0 && n > -129) - strcpy (r, "movxbd "); - else if (n < 0 && n > -32769) - strcpy (r, "movxwd "); - else - strcpy (r, "movd "); - strcat (r, s); - return r; -} - -static rtx -ns32k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, - int incoming ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (Pmode, NS32K_STRUCT_VALUE_REGNUM); -} - -/* Worker function for NOTICE_UPDATE_CC. */ - -void -ns32k_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) -{ - if (GET_CODE (exp) == SET) - { - if (GET_CODE (SET_DEST (exp)) == CC0) - { - cc_status.flags = 0; - cc_status.value1 = SET_DEST (exp); - cc_status.value2 = SET_SRC (exp); - } - else if (GET_CODE (SET_SRC (exp)) == CALL) - { - CC_STATUS_INIT; - } - else if (GET_CODE (SET_DEST (exp)) == REG) - { - if (cc_status.value1 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) - cc_status.value1 = 0; - if (cc_status.value2 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) - cc_status.value2 = 0; - } - else if (GET_CODE (SET_DEST (exp)) == MEM) - { - CC_STATUS_INIT; - } - } - else if (GET_CODE (exp) == PARALLEL - && GET_CODE (XVECEXP (exp, 0, 0)) == SET) - { - if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == CC0) - { - cc_status.flags = 0; - cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0)); - cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0)); - } - else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == REG) - { - if (cc_status.value1 - && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp, 0, 0)), - cc_status.value1)) - cc_status.value1 = 0; - if (cc_status.value2 - && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp, 0, 0)), - cc_status.value2)) - cc_status.value2 = 0; - } - else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == MEM) - { - CC_STATUS_INIT; - } - } - else if (GET_CODE (exp) == CALL) - { - /* all bets are off */ - CC_STATUS_INIT; - } - else - { - /* nothing happens? CC_STATUS_INIT; */ - } - if (cc_status.value1 && GET_CODE (cc_status.value1) == REG - && cc_status.value2 - && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) - abort (); -} - -/* Implement TARGET_ARG_PARTIAL_BYTES. */ - -static int -ns32k_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode, - tree type, bool named ATTRIBUTE_UNUSED) -{ - int cum = *pcum; - - if (TARGET_REGPARM && cum < 8) - { - HOST_WIDE_INT size; - - if (mode == BLKmode) - size = int_size_in_bytes (type); - else - size = GET_MODE_SIZE (mode); - - if (8 < cum + size) - return 8 - cum; - } - - return 0; -} diff --git a/gcc/config/ns32k/ns32k.h b/gcc/config/ns32k/ns32k.h deleted file mode 100644 index 1e503cf5f86..00000000000 --- a/gcc/config/ns32k/ns32k.h +++ /dev/null @@ -1,1182 +0,0 @@ -/* Definitions of target machine for GNU compiler. NS32000 version. - Copyright (C) 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2004, 2005 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@cygnus.com) - -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. */ - - -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__ns32000__"); \ - \ - /* CPU type */ \ - if (TARGET_32532) \ - builtin_define ("__ns32532__"); \ - else if (TARGET_32332) \ - builtin_define ("__ns32332__"); \ - else \ - builtin_define ("__ns32032__"); \ - \ - /* FPU type */ \ - if (TARGET_32381) \ - builtin_define ("__ns32381__"); \ - else if (TARGET_32081) \ - builtin_define ("__ns32081__"); \ - \ - /* Misc. */ \ - if (TARGET_RTD) \ - builtin_define ("__RTD__"); \ - \ - builtin_assert ("cpu=ns32k"); \ - builtin_assert ("machine=ns32k"); \ - } \ - while (0) - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION fprintf (stderr, " (32000, GAS syntax)"); - - -/* ABSOLUTE PREFIX, IMMEDIATE_PREFIX and EXTERNAL_PREFIX can be defined - to cover most NS32k addressing syntax variations. This way we don't - need to redefine long macros in all the tm.h files for just slight - variations in assembler syntax. */ - -#ifndef ABSOLUTE_PREFIX -#define ABSOLUTE_PREFIX '@' -#endif - -#if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX -#define PUT_IMMEDIATE_PREFIX(FILE) putc(IMMEDIATE_PREFIX, FILE) -#else -#define PUT_IMMEDIATE_PREFIX(FILE) -#endif -#if defined(ABSOLUTE_PREFIX) && ABSOLUTE_PREFIX -#define PUT_ABSOLUTE_PREFIX(FILE) putc(ABSOLUTE_PREFIX, FILE) -#else -#define PUT_ABSOLUTE_PREFIX(FILE) -#endif -#if defined(EXTERNAL_PREFIX) && EXTERNAL_PREFIX -#define PUT_EXTERNAL_PREFIX(FILE) putc(EXTERNAL_PREFIX, FILE) -#else -#define PUT_EXTERNAL_PREFIX(FILE) -#endif - -/* When we are generating PIC, the sb is used as a pointer - to the GOT. 32381 is a superset of 32081 */ - -#define OVERRIDE_OPTIONS \ -{ \ - if (target_flags & MASK_32532) \ - target_flags |= MASK_32332; \ - if (flag_pic || TARGET_HIMEM) \ - target_flags &= ~MASK_SB; \ - if (TARGET_32381) \ - target_flags |= MASK_32081; \ - else \ - target_flags &= ~MASK_MULT_ADD; \ - if (flag_unsafe_math_optimizations) \ - target_flags &= ~MASK_IEEE_COMPARE; \ -} - -/* Zero or more C statements that may conditionally modify two - variables `fixed_regs' and `call_used_regs' (both of type `char - []') after they have been initialized from the two preceding - macros. - - This is necessary in case the fixed or call-clobbered registers - depend on target flags. - - You need not define this macro if it has no work to do. - - If the usage of an entire class of registers depends on the target - flags, you may indicate this to GCC by using this macro to modify - `fixed_regs' and `call_used_regs' to 1 for each of the registers in - the classes which should not be used by GCC. Also define the macro - `REG_CLASS_FROM_LETTER' to return `NO_REGS' if it is called with a - letter for a class that shouldn't be used. - - (However, if this class is not included in `GENERAL_REGS' and all - of the insn patterns whose constraints permit this class are - controlled by target switches, then GCC will automatically avoid - using these registers when the target switches are opposed to - them.) */ - -#define CONDITIONAL_REGISTER_USAGE \ -do \ - { \ - if (!TARGET_32081) \ - { \ - int regno; \ - \ - for (regno = F0_REGNUM; regno <= F0_REGNUM + 8; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - if (!TARGET_32381) \ - { \ - int regno; \ - \ - for (regno = L1_REGNUM; regno <= L1_REGNUM + 8; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - } \ -while (0) - - -/* target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - This is not true on the ns32k. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. */ -/* That is not true on the ns32k. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is lowest - numbered. This is not true on the ns32k. */ -#define WORDS_BIG_ENDIAN 0 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 16 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 32 - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. National claims that the NS32032 - works without strict alignment, but rumor has it that operands - crossing a page boundary cause unpredictable results. */ -#define STRICT_ALIGNMENT 1 - -/* If bit field type is int, don't let it cross an int, - and give entire struct the alignment of an int. */ -/* Required on the 386 since it doesn't have a full set of bit-field insns. - (There is no signed extv insn.) */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 26 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - On the ns32k, these are the FP, SP, (SB and PC are not included here). */ -#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS {1, 1, 1, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 0, 0, 0, 0, \ - 1, 1, 0, 0, 0, 0, 0, 0, \ - 1, 1} - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ - "l1", "l1h","l3", "l3h","l5", "l5h","l7", "l7h", \ - "fp", "sp"} - - -#define ADDITIONAL_REGISTER_NAMES \ -{{"l0", 8}, {"l2", 10}, {"l4", 12}, {"l6", 14}} - -/* l0-7 are not recognized by the assembler. These are the names to use, - * but we don't want ambiguous names in REGISTER_NAMES - */ -#define OUTPUT_REGISTER_NAMES \ -{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ - "f1", "l1h","f3", "l3h","f5", "l5h","f7", "f7h", \ - "fp", "sp"} - -#define REG_ALLOC_ORDER \ -{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 10, 11, 18, 12, 13, 20, 14, 15, 22, 24, 25, 17, 19, 23} - -/* How to renumber registers for dbx and gdb. - NS32000 may need more change in the numeration. XXX */ - -#define DBX_REGISTER_NUMBER(REGNO) \ - ((REGNO) < L1_REGNUM? (REGNO) \ - : (REGNO) < FRAME_POINTER_REGNUM? (REGNO) - L1_REGNUM + 22 \ - : (REGNO) == FRAME_POINTER_REGNUM? 17 \ - : 16) - -/* dwarf2out.c can't understand the funny DBX register numbering. - * We use dwarf2out.c for exception handling even though we use DBX - * for debugging - */ -#define DWARF_FRAME_REGNUM(REGNO) (REGNO) - - - -#define R0_REGNUM 0 -#define F0_REGNUM 8 -#define L1_REGNUM 16 - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* NS32000 pc is not overloaded on a register. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 25 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 24 - - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - On the ns32k, all registers are 32 bits long except for the 32381 "long" - registers but we treat those as pairs */ -#define LONG_FP_REGS_P(REGNO) ((REGNO) >= L1_REGNUM && (REGNO) < L1_REGNUM + 8) -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok (REGNO, MODE) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((FLOAT_MODE_P(MODE1) && FLOAT_MODE_P(MODE2) \ - && (GET_MODE_UNIT_SIZE(MODE1) == GET_MODE_UNIT_SIZE(MODE2))) \ - || (!FLOAT_MODE_P(MODE1) && !FLOAT_MODE_P(MODE2))) - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 24 - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 1 - -/* Register in which address to store a structure value - is passed to a function. */ -#define NS32K_STRUCT_VALUE_REGNUM 2 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -enum reg_class -{ NO_REGS, GENERAL_REGS, FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, - LONG_REGS, FP_REGS, GEN_AND_FP_REGS, FRAME_POINTER_REG, - STACK_POINTER_REG, GEN_AND_MEM_REGS, ALL_REGS, LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "GENERAL_REGS", "FLOAT_REG0", "LONG_FLOAT_REG0", "FLOAT_REGS", \ - "LONG_REGS", "FP_REGS", "GEN_AND_FP_REGS", "FRAME_POINTER_REG", \ - "STACK_POINTER_REG", "GEN_AND_MEM_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ - {{0}, /* NO_REGS */ \ - {0x00ff}, /* GENERAL_REGS */ \ - {0x100}, /* FLOAT_REG0 */ \ - {0x300}, /* LONG_FLOAT_REG0 */ \ - {0xff00}, /* FLOAT_REGS */ \ - {0xff0000}, /* LONG_REGS */ \ - {0xffff00}, /* FP_REGS */ \ - {0xffffff}, /* GEN_AND_FP_REGS */ \ - {0x1000000}, /* FRAME_POINTER_REG */ \ - {0x2000000}, /* STACK_POINTER_REG */ \ - {0x30000ff}, /* GEN_AND_MEM_REGS */ \ - {0x3ffffff} /* ALL_REGS */ \ - } - -#define SUBSET_P(CLASS1, CLASS2) \ - ((ns32k_reg_class_contents[CLASS1][0] \ - & ~ns32k_reg_class_contents[CLASS2][0]) == 0) - - -/* LONG_REGS are registers which can only hold double precision floats - * and can only be accessible by long float instructions. - */ -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ - (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ - ? reg_classes_intersect_p (LONG_REGS, CLASS) : 0) - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO]) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GEN_AND_MEM_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'u' ? FLOAT_REG0 \ - : (C) == 'v' ? LONG_FLOAT_REG0 \ - : (C) == 'f' ? FLOAT_REGS \ - : (C) == 'l' ? FP_REGS \ - : (C) == 'x' ? FRAME_POINTER_REG \ - : (C) == 'y' ? STACK_POINTER_REG \ - : NO_REGS) - -/* The letters I, J, K, L and M in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - On the ns32k, these letters are used as follows: - - I : Matches integers which are valid shift amounts for scaled indexing. - These are 0, 1, 2, 3 for byte, word, double, and quadword. - Used for matching arithmetic shifts only on 32032 & 32332. - J : Matches integers which fit a "quick" operand. - K : Matches integers 0 to 7 (for inss and exts instructions). - */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((VALUE) < 8 && (VALUE) + 8 >= 0 ? \ - ((C) == 'I' ? (!TARGET_32532 && 0 <= (VALUE) && (VALUE) <= 3) : \ - (C) == 'J' ? (VALUE) <= 7 : \ - (C) == 'K' ? 0 <= (VALUE) : 0) : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -/* We return GENERAL_REGS instead of GEN_AND_MEM_REGS. - The latter offers no real additional possibilities - and can cause spurious secondary reloading. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - ((CLASS) == GEN_AND_MEM_REGS ? GENERAL_REGS : (CLASS)) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -/* On the 32000, this is the size of MODE in words */ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this to non-zero if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD 1 - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* 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. - - Before the prologue, RA is at 0(sp). */ - -#define INCOMING_RETURN_ADDR_RTX \ - gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM)) - -/* A C expression whose value is RTL representing the value of the - return address for the frame COUNT steps up from the current frame, - after the prologue. FRAMEADDR is the frame pointer of the COUNT - frame, or the frame pointer of the COUNT - 1 frame if - `RETURN_ADDR_IN_PREVIOUS_FRAME' is defined. - - After the prologue, RA is at 4(fp) in the current frame. */ - -#define RETURN_ADDR_RTX(COUNT, FRAME) \ - ((COUNT> 0 && flag_omit_frame_pointer)? NULL_RTX \ - : gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, (FRAME), GEN_INT(4)))) - -/* 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 4 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On the 32000, sp@- in a byte insn really pushes a BYTE. */ -#define PUSH_ROUNDING(BYTES) (BYTES) - -/* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) 8 - -/* Value is the number of byte of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. - - On the 32000, the RET insn may be used to pop them if the number - of args is fixed, but if the number is variable then the caller - must pop them all. RET can't be used for library calls now - because the library is compiled with the Unix compiler. - Use of RET is a selectable option, since it is incompatible with - standard Unix calling sequences. If the option is not selected, - the caller must always pop the args. - - The attribute stdcall is equivalent to RTD on a per module basis. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (ns32k_return_pops_args (FUNDECL, FUNTYPE, SIZE)) - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -/* On the 32000 the return value is in R0, - or perhaps in F0 if there is fp support. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) LIBCALL_VALUE(TYPE_MODE (VALTYPE)) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -/* On the 32000 the return value is in R0, - or perhaps F0 is there is fp support. */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx_REG (MODE, \ - FLOAT_MODE_P(MODE) && TARGET_32081 ? F0_REGNUM: R0_REGNUM) - -/* Define this if PCC uses the nonreentrant convention for returning - structure and union values. */ - -#define PCC_STATIC_STRUCT_RETURN - -/* 1 if N is a possible register number for a function value. - On the 32000, R0 and F0 are the only registers thus used. */ - -#define FUNCTION_VALUE_REGNO_P(N) (((N) & ~8) == 0) - -/* 1 if N is a possible register number for function argument passing. - On the 32000, no registers are used in this way. */ - -#define FUNCTION_ARG_REGNO_P(N) 0 - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On the ns32k, this is a single integer, which is a number of bytes - of arguments scanned so far. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - On the ns32k, the offset starts at 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += ((MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ - : (int_size_in_bytes (TYPE) + 3) & ~3)) - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -/* On the 32000 all args are pushed, except if -mregparm is specified - then the first two words of arguments are passed in r0, r1. - *NOTE* -mregparm does not work. - It exists only to test register calling conventions. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -((TARGET_REGPARM && (CUM) < 8) ? gen_rtx_REG ((MODE), (CUM) / 4) : 0) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. - - THIS DEFINITION FOR THE 32000 IS A GUESS. IT HAS NOT BEEN TESTED. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "\taddr LP%d,r0\n\tbsr mcount\n", (LABELNO)) - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. - - We use 0, because using 1 requires hair in output_function_epilogue() - that is worse than the stack adjust we could save. */ - -/* #define EXIT_IGNORE_STACK 1 */ - -/* Store in the variable DEPTH the initial difference between the - frame pointer reg contents and the stack pointer reg contents, - as of the start of the function body. This depends on the layout - of the fixed parts of the stack frame and on how registers are saved. */ - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ \ - int regno; \ - int offset = -4; \ - for (regno = 0; regno < FRAME_POINTER_REGNUM; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - offset += 4; \ - if (flag_pic && current_function_uses_pic_offset_table) \ - offset += 4; \ - (DEPTH) = (offset + get_frame_size () \ - + (get_frame_size () == 0 ? 0 : 4)); \ -} - - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -/* On the 32k, the trampoline looks like this: - - addr 0(pc),r2 - movd 16(r2),tos - movd 12(r2),r1 - ret 0 - .align 4 - .int STATIC - .int FUNCTION - - Putting the data in following data is easier than figuring out how to - do stores to memory in reverse byte order (the way immediate operands - on the 32k are stored). */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fprintf (FILE, "\taddr 0(pc),r2\n"); \ - fprintf (FILE, "\tmovd 16(r2),tos\n"); \ - fprintf (FILE, "\tmovd 12(r2),r1\n"); \ - fprintf (FILE, "\tret 0\n"); \ - assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \ - assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 12)), CXT); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 16)), FNADDR); \ -} - -/* Addressing modes, and classification of registers for them. */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -/* note that FP and SP cannot be used as an index. What about PC? */ -#define REGNO_OK_FOR_INDEX_P(REGNO) \ -((REGNO) < F0_REGNUM || (unsigned)reg_renumber[REGNO] < F0_REGNUM) -#define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < F0_REGNUM || (unsigned)reg_renumber[REGNO] < F0_REGNUM \ - || (REGNO) == FRAME_POINTER_REGNUM || (REGNO) == STACK_POINTER_REGNUM) - -#define FP_REG_P(X) \ - (GET_CODE (X) == REG && REGNO (X) >= F0_REGNUM && REGNO (X) < FRAME_POINTER_REGNUM) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* Recognize any constant value that is a valid address. - This might not work on future ns32k processors as negative - displacements are not officially allowed but a mode reserved - to National. This works on processors up to 32532, though, - and we don't expect any new ones in the series ;-( */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST \ - || (GET_CODE (X) == CONST_INT \ - && NS32K_DISPLACEMENT_P (INTVAL (X)))) - -#define CONSTANT_ADDRESS_NO_LABEL_P(X) \ - (GET_CODE (X) == CONST_INT \ - && NS32K_DISPLACEMENT_P (INTVAL (X))) - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ - secondary_reload_class (CLASS, MODE, IN) - -/* Certain machines have the property that some registers cannot be - copied to some other registers without using memory. Define this - macro on those machines to be a C expression that is nonzero if - objects of mode M in registers of CLASS1 can only be copied to - registers of class CLASS2 by storing a register of CLASS1 into - memory and loading that memory location into a register of CLASS2. - - On the ns32k, floating point regs can only be loaded through memory - - The movdf and movsf insns in ns32k.md copy between general and - floating registers using the stack. In principle, we could get - better code not allowing that case in the constraints and defining - SECONDARY_MEMORY_NEEDED in practice, though the stack slots used - are not available for optimization. */ - -#if 0 -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, M) \ - secondary_memory_needed(CLASS1, CLASS2, M) -#endif - -/* SMALL_REGISTER_CLASSES is a run time option. This should no longer - be necessary and should go when we have confidence that we won't run - out of spill registers */ -#define SMALL_REGISTER_CLASSES (target_flags & MASK_SRC) - -/* A C expression whose value is nonzero if pseudos that have been - assigned to registers of class CLASS would likely be spilled - because registers of CLASS are needed for spill registers. - - The default definition won't do because class LONG_FLOAT_REG0 has two - registers which are always accessed as a pair */ - -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - (reg_class_size[(int) (CLASS)] == 1 || (CLASS) == LONG_FLOAT_REG0) - - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) \ - (REGNO (X) < F0_REGNUM || REGNO (X) >= FIRST_PSEUDO_REGISTER) -/* Nonzero if X is a hard reg that can be used as a base reg - of if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) (REGNO (X) < F0_REGNUM || REGNO (X) >= FRAME_POINTER_REGNUM) -/* Nonzero if X is a floating point reg or a pseudo reg. */ - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */ - -/* 1 if X is an address that we could indirect through. */ -/***** NOTE ***** There is a bug in the Sequent assembler which fails - to fixup addressing information for symbols used as offsets - from registers which are not FP or SP (or SB or PC). This - makes _x(fp) valid, while _x(r0) is invalid. */ - -#define INDIRECTABLE_1_ADDRESS_P(X) \ - (CONSTANT_ADDRESS_P (X) \ - || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - || (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && ((flag_pic || TARGET_HIMEM) ? \ - CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1)) \ - : \ - CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - && (GET_CODE (X) != CONST_INT || NS32K_DISPLACEMENT_P (INTVAL (X))))) - -/* 1 if integer I will fit in a 4 byte displacement field. - Strictly speaking, we can't be sure that a symbol will fit this range. - But, in practice, it always will. */ - -/* idall@eleceng.adelaide.edu.au says that the 32016 and 32032 - can handle the full range of displacements--it is only the addresses - that have a limited range. So the following was deleted: - (((i) <= 16777215 && (i) >= -16777216) - || ((TARGET_32532 || TARGET_32332) && ...)) */ -#define NS32K_DISPLACEMENT_P(i) \ - ((i) < (1 << 29) && (i) >= - (1 << 29)) - -/* Check for frame pointer or stack pointer. */ -#define MEM_REG(X) \ - (GET_CODE (X) == REG && (REGNO (X) == FRAME_POINTER_REGNUM \ - || REGNO(X) == STACK_POINTER_REGNUM)) - -/* A memory ref whose address is the FP or SP, with optional integer offset, - or (on certain machines) a constant address. */ -#define INDIRECTABLE_2_ADDRESS_P(X) \ - (GET_CODE (X) == MEM \ - && (((xfoo0 = XEXP (X, 0), MEM_REG (xfoo0)) \ - || (GET_CODE (xfoo0) == PLUS \ - && MEM_REG (XEXP (xfoo0, 0)) \ - && CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfoo0, 1)))) \ - || (TARGET_SB && CONSTANT_ADDRESS_P (xfoo0)))) - -/* Go to ADDR if X is a valid address not using indexing. - (This much is the easy part.) */ -#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ -{ \ - if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; \ - if (INDIRECTABLE_2_ADDRESS_P (X)) goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1))) \ - if (INDIRECTABLE_2_ADDRESS_P (XEXP (X, 0))) \ - goto ADDR; \ -} - -/* Go to ADDR if X is a valid address not using indexing. - (This much is the easy part.) */ -#define GO_IF_INDEXING(X, MODE, ADDR) \ -{ register rtx xfoob = (X); \ - if (GET_CODE (xfoob) == PLUS && INDEX_TERM_P (XEXP (xfoob, 0), MODE)) \ - GO_IF_INDEXABLE_ADDRESS (XEXP (xfoob, 1), ADDR); \ - if (GET_CODE (xfoob) == PLUS && INDEX_TERM_P (XEXP (xfoob, 1), MODE)) \ - GO_IF_INDEXABLE_ADDRESS (XEXP (xfoob, 0), ADDR); } \ - -#define GO_IF_INDEXABLE_ADDRESS(X, ADDR) \ -{ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; \ - if (INDIRECTABLE_2_ADDRESS_P (X)) goto ADDR; \ - if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; \ -} - -/* 1 if PROD is either a reg times size of mode MODE - or just a reg, if MODE is just one byte. Actually, on the ns32k, - since the index mode is independent of the operand size, - we can match more stuff... - - This macro's expansion uses the temporary variables xfoo0, xfoo1 - and xfoo2 that must be declared in the surrounding context. */ -#define INDEX_TERM_P(PROD, MODE) \ -((GET_CODE (PROD) == REG && REG_OK_FOR_INDEX_P (PROD)) \ - || (GET_CODE (PROD) == MULT \ - && (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \ - (GET_CODE (xfoo1) == CONST_INT \ - && GET_CODE (xfoo0) == REG \ - && FITS_INDEX_RANGE (INTVAL (xfoo1)) \ - && REG_OK_FOR_INDEX_P (xfoo0))))) - -#define FITS_INDEX_RANGE(X) \ - ((xfoo2 = (unsigned)(X)-1), \ - ((xfoo2 < 4 && xfoo2 != 2) || xfoo2 == 7)) - -/* Note that xfoo0, xfoo1, xfoo2 are used in some of the submacros above. */ -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ register rtx xfooy, xfoo0, xfoo1; \ - unsigned xfoo2; \ - xfooy = X; \ - if (flag_pic && cfun && ! current_function_uses_pic_offset_table \ - && global_symbolic_reference_mentioned_p (X, 1)) \ - current_function_uses_pic_offset_table = 1; \ - GO_IF_NONINDEXED_ADDRESS (xfooy, ADDR); \ - if (GET_CODE (xfooy) == PLUS) \ - { \ - if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfooy, 1)) \ - && GET_CODE (XEXP (xfooy, 0)) == PLUS) \ - xfooy = XEXP (xfooy, 0); \ - else if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfooy, 0)) \ - && GET_CODE (XEXP (xfooy, 1)) == PLUS) \ - xfooy = XEXP (xfooy, 1); \ - GO_IF_INDEXING (xfooy, MODE, ADDR); \ - } \ - else if (INDEX_TERM_P (xfooy, MODE)) \ - goto ADDR; \ - else if (GET_CODE (xfooy) == PRE_DEC) \ - { \ - if (REGNO (XEXP (xfooy, 0)) == STACK_POINTER_REGNUM) goto ADDR; \ - } \ -} - -/* Nonzero if the constant value X is a legitimate general operand - when generating PIC code. It is given that flag_pic is on and - that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -#define LEGITIMATE_PIC_OPERAND_P(X) \ - (((! current_function_uses_pic_offset_table \ - && symbolic_reference_mentioned_p (X))? \ - (current_function_uses_pic_offset_table = 1):0 \ - ), (! SYMBOLIC_CONST (X) \ - || GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF)) - -#define SYMBOLIC_CONST(X) \ -(GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == LABEL_REF \ - || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X))) - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the ns32k, only predecrement and postincrement address depend thus - (the amount of decrement or increment being the length of the operand). */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ - { if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) \ - goto LABEL;} - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. - HI mode is more efficient but the range is not wide enough for - all programs. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -#define CASE_VECTOR_PC_RELATIVE 1 - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 4 - -/* The number of scalar move insns which should be generated instead - of a string move insn or a library call. - - We have a smart movmemsi insn */ -#define MOVE_RATIO 0 - -#define STORE_RATIO (optimize_size ? 3 : 15) -#define STORE_BY_PIECES_P(SIZE, ALIGN) \ - (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \ - < (unsigned int) STORE_RATIO) - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). */ - -/* This bit means that what ought to be in the Z bit - should be tested in the F bit. */ -#define CC_Z_IN_F 04000 - -/* This bit means that what ought to be in the Z bit - is complemented in the F bit. */ -#define CC_Z_IN_NOT_F 010000 - -/* This bit means that the L bit indicates unordered (IEEE) comparison. - */ -#define CC_UNORD 020000 - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ - ns32k_notice_update_cc ((EXP), (INSN)) - -/* Describe the costs of the following register moves which are discouraged: - 1.) Moves between the Floating point registers and the frame pointer and stack pointer - 2.) Moves between the stack pointer and the frame pointer - 3.) Moves between the floating point and general registers - - These all involve two memory references. This is worse than a memory - to memory move (default cost 4) - */ - -#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ - register_move_cost (CLASS1, CLASS2) - -#define OUTPUT_JUMP(NORMAL, NO_OV) \ -{ if (cc_status.flags & CC_NO_OVERFLOW) \ - return NO_OV; \ - return NORMAL; } - -/* Dividing the output into sections */ - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP "\t.data" - -/* Define the output Assembly Language */ - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "#APP\n" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "#NO_APP\n" - -/* Output of Data */ - -/* This is how to output an assembler line defining an external/static - address which is not in tree format (for collect.c). */ - -/* The prefix to add to user-visible assembler symbols. */ -#define USER_LABEL_PREFIX "_" - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tmovd %s,tos\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tmovd tos,%s\n", reg_names[REGNO]) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP ".globl " - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%ld", PREFIX, (long) NUM) - -/* This is how to align the code that follows an unconditional branch. */ - -#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (2) - -/* This is how to output an element of a case-vector that is absolute. - (The ns32k does not use such vectors, - but we must define this macro anyway.) */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ -/* ** Notice that the second element is LI format! */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.long L%d-LI%d\n", VALUE, REL) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf (FILE, "\t.align %d\n", (LOG)) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.space %u\n", (int)(SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(ROUNDED))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".lcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(ROUNDED))) - -/* Print an instruction operand X on file FILE. - CODE is the code from the %-spec that requested printing this operand; - if `%z3' was used to print operand 3, then CODE is 'z'. */ - -/* %$ means print the prefix for an immediate operand. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - ((CODE) == '$' || (CODE) == '?') - -#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE) - -/* Print a memory operand whose address is X, on file FILE. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address(FILE, ADDR) - -extern const unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1]; -extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smallest class containing REGNO */ - -/* -Local variables: -version-control: t -End: -*/ diff --git a/gcc/config/ns32k/ns32k.md b/gcc/config/ns32k/ns32k.md deleted file mode 100644 index 9159bc36863..00000000000 --- a/gcc/config/ns32k/ns32k.md +++ /dev/null @@ -1,3082 +0,0 @@ -;;- Machine description for GNU compiler, ns32000 Version -;; Copyright (C) 1988, 1994, 1996, 1998, 1999, 2000, 2001, 2002, 2004 -;; Free Software Foundation, Inc. -;; Contributed by Michael Tiemann (tiemann@cygnus.com) - -;; 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. - - -; BUGS: -;; Insert no-op between an insn with memory read-write operands -;; following by a scale-indexing operation. -;; The Sequent assembler does not allow addresses to be used -;; except in insns which explicitly compute an effective address. -;; I.e., one cannot say "cmpd _p,@_x" -;; Implement unsigned multiplication?? - -;;- Instruction patterns. When multiple patterns apply, -;;- the first one in the file is chosen. -;;- -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. -;;- -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - -;; We don't want to allow a constant operand for test insns because -;; (set (cc0) (const_int foo)) has no mode information. Such insns will -;; be folded while optimizing anyway. -;; -;; In order for pic mode to work we cannot generate, for example -;; -;; addd _x+5,r1 -;; -;; instead we must force gcc to generate something like -;; -;; addr 5(_x(sb)),r0 -;; addd r0,r1 -;; -;; This was done through operand constraints (using "rmn" in place of "g"), -;; but with the proper definition of LEGITIMATE_PIC_OPERAND (ns32k.h) -;; this is unnecessary. -;; - -;; It seems that in current CVS (2000-01-11), at least with -;; libgcc2.a, that register allocation gets worse when changing -;; "general_operand" "0" to "nonimmediate_operand" "0" (and -;; similar "0"-containing constraints), if operand 0 is (e.g.) -;; "nonimmediate_operand" "=rm". Revisit and test later. - -(define_insn "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ cc_status.flags |= CC_REVERSED; - operands[1] = const0_rtx; - return \"cmpqd %1,%0\"; }") - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ cc_status.flags |= CC_REVERSED; - operands[1] = const0_rtx; - return \"cmpqw %1,%0\"; }") - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ cc_status.flags |= CC_REVERSED; - operands[1] = const0_rtx; - return \"cmpqb %1,%0\"; }") - -(define_insn "tstdf" - [(set (cc0) - (match_operand:DF 0 "general_operand" "lmF"))] - "TARGET_32081" - "* -{ cc_status.flags |= CC_REVERSED; - if (TARGET_IEEE_COMPARE) - cc_status.flags |= CC_UNORD; - operands[1] = CONST0_RTX (DFmode); - return \"cmpl %1,%0\"; }") - -(define_insn "tstsf" - [(set (cc0) - (match_operand:SF 0 "general_operand" "fmF"))] - "TARGET_32081" - "* -{ cc_status.flags |= CC_REVERSED; - if (TARGET_IEEE_COMPARE) - cc_status.flags |= CC_UNORD; - operands[1] = CONST0_RTX (SFmode); - return \"cmpf %1,%0\"; }") - -;; See note 1 -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "general_operand" "g") - (match_operand:SI 1 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - int i = INTVAL (operands[1]); - if (i <= 7 && i >= -8) - { - cc_status.flags |= CC_REVERSED; - return \"cmpqd %1,%0\"; - } - } - cc_status.flags &= ~CC_REVERSED; - if (GET_CODE (operands[0]) == CONST_INT) - { - int i = INTVAL (operands[0]); - if (i <= 7 && i >= -8) - return \"cmpqd %0,%1\"; - } - return \"cmpd %0,%1\"; -}") - -(define_insn "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "g") - (match_operand:HI 1 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - short i = INTVAL (operands[1]); - if (i <= 7 && i >= -8) - { - cc_status.flags |= CC_REVERSED; - if (INTVAL (operands[1]) > 7) - operands[1] = GEN_INT (i); - return \"cmpqw %1,%0\"; - } - } - cc_status.flags &= ~CC_REVERSED; - if (GET_CODE (operands[0]) == CONST_INT) - { - short i = INTVAL (operands[0]); - if (i <= 7 && i >= -8) - { - if (INTVAL (operands[0]) > 7) - operands[0] = GEN_INT (i); - return \"cmpqw %0,%1\"; - } - } - return \"cmpw %0,%1\"; -}") - -(define_insn "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "general_operand" "g") - (match_operand:QI 1 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - char i = INTVAL (operands[1]); - if (i <= 7 && i >= -8) - { - cc_status.flags |= CC_REVERSED; - if (INTVAL (operands[1]) > 7) - operands[1] = GEN_INT (i); - return \"cmpqb %1,%0\"; - } - } - cc_status.flags &= ~CC_REVERSED; - if (GET_CODE (operands[0]) == CONST_INT) - { - char i = INTVAL (operands[0]); - if (i <= 7 && i >= -8) - { - if (INTVAL (operands[0]) > 7) - operands[0] = GEN_INT (i); - return \"cmpqb %0,%1\"; - } - } - return \"cmpb %0,%1\"; -}") - -(define_insn "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "lmF") - (match_operand:DF 1 "general_operand" "lmF")))] - "TARGET_32081" - "* -{ - if (TARGET_IEEE_COMPARE) - cc_status.flags |= CC_UNORD; - return \"cmpl %0,%1\";}") - -(define_insn "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "general_operand" "fmF") - (match_operand:SF 1 "general_operand" "fmF")))] - "TARGET_32081" - "* -{ - if (TARGET_IEEE_COMPARE) - cc_status.flags |= CC_UNORD; - return \"cmpf %0,%1\";}") - -;; movdf and movsf copy between general and floating registers using -;; the stack. In principle, we could get better code not allowing -;; that case in the constraints and defining SECONDARY_MEMORY_NEEDED -;; in practice, though the stack slots used are not available for -;; optimization. -(define_insn "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lrm<") - (match_operand:DF 1 "general_operand" "lFg"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE) - return \"movl %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"movd %1,tos\", xoperands); - output_asm_insn (\"movd %1,tos\", operands); - return \"movl tos,%0\"; - } - return \"movl %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - { - output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - return \"movd tos,%0\"; - } - else - return \"movl %1,%0\"; - } - return output_move_double (operands); -}") - -(define_insn "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=frm<") - (match_operand:SF 1 "general_operand" "fFg"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < F0_REGNUM) - return \"movd %1,tos\;movf tos,%0\"; - else - return \"movf %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - return \"movf %1,tos\;movd tos,%0\"; - return \"movf %1,%0\"; - } -#if 0 /* Someone suggested this for the Sequent. Is it needed? */ - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - return \"movf %1,%0\"; -#endif -/* There was a #if 0 around this, but that was erroneous - for many machines -- rms. */ -#ifndef MOVD_FLOAT_OK - /* GAS understands floating constants in ordinary movd instructions - but other assemblers might object. */ - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - union {int i[2]; float f; double d;} convrt; - convrt.i[0] = CONST_DOUBLE_LOW (operands[1]); - convrt.i[1] = CONST_DOUBLE_HIGH (operands[1]); - convrt.f = convrt.d; - - /* Is there a better machine-independent way to to this? */ - operands[1] = GEN_INT (convrt.i[0]); - return \"movd %1,%0\"; - } -#endif - else return \"movd %1,%0\"; -}") - -(define_insn "*movti" - [(set (match_operand:TI 0 "memory_operand" "=m") - (match_operand:TI 1 "memory_operand" "m"))] - "" - "movmd %1,%0,4") - -(define_insn "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm<,*l,rm") - (match_operand:DI 1 "general_operand" "gF,g,*l"))] - "" - "* -{ - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE) - return \"movl %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"movd %1,tos\", xoperands); - output_asm_insn (\"movd %1,tos\", operands); - return \"movl tos,%0\"; - } - return \"movl %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - { - output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - return \"movd tos,%0\"; - } - else - return \"movl %1,%0\"; - } - return output_move_double (operands); -}") - -;; This special case must precede movsi. -(define_insn "*ldsp" - [(set (reg:SI 25) - (match_operand:SI 0 "general_operand" "g"))] - "" - "lprd sp,%0") - -(define_insn "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<,rm<,*f,rm,x") - (match_operand:SI 1 "general_operand" "g,?xy,g,*f,rmn"))] - "" - "* -{ - extern int flag_pic; - - if (FP_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < F0_REGNUM) - return \"movd %1,tos\;movf tos,%0\"; - else - return \"movf %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - return \"movf %1,tos\;movd tos,%0\"; - return \"movf %1,%0\"; - } - if (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) == FRAME_POINTER_REGNUM) - return \"lprd fp,%1\"; - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); - if (GET_CODE (operands[1]) == CONST_INT) - { - int i = INTVAL (operands[1]); - if (! TARGET_32532) - { - if (i <= 7 && i >= -8) - return \"movqd %1,%0\"; - if (NS32K_DISPLACEMENT_P (i)) -#if defined (GNX_V3) || defined (UTEK_ASM) - return \"addr %c1,%0\"; -#else - return \"addr @%c1,%0\"; -#endif - return \"movd %1,%0\"; - } - else - return output_move_dconst(i, \"%1,%0\"); - } - else if (GET_CODE (operands[1]) == CONST && ! flag_pic) - { - /* Must contain symbols so we don't know how big it is. In - * that case addr might lead to overflow. For PIC symbolic - * address loads always have to be done with addr. - */ - return \"movd %1,%0\"; - } - else if (GET_CODE (operands[1]) == REG) - { - if (REGNO (operands[1]) < F0_REGNUM) - return \"movd %1,%0\"; - else if (REGNO (operands[1]) == FRAME_POINTER_REGNUM) - { - if (GET_CODE(operands[0]) == REG) - return \"sprd fp,%0\"; - else - return \"addr 0(fp),%0\" ; - } - else if (REGNO (operands[1]) == STACK_POINTER_REGNUM) - { - if (GET_CODE(operands[0]) == REG) - return \"sprd sp,%0\"; - else - return \"addr 0(sp),%0\" ; - } - else abort (); - } - else if (GET_CODE (operands[1]) == MEM) - return \"movd %1,%0\"; - - /* Check if this effective address can be - calculated faster by pulling it apart. */ - if (REG_P (operands[0]) - && GET_CODE (operands[1]) == MULT - && GET_CODE (XEXP (operands[1], 1)) == CONST_INT - && (INTVAL (XEXP (operands[1], 1)) == 2 - || INTVAL (XEXP (operands[1], 1)) == 4)) - { - rtx xoperands[3]; - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - xoperands[2] = GEN_INT (INTVAL (XEXP (operands[1], 1)) >> 1); - return output_shift_insn (xoperands); - } - return \"addr %a1,%0\"; -}") - -(define_insn "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<,*f,rm") - (match_operand:HI 1 "general_operand" "g,g,*f"))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - short i = INTVAL (operands[1]); - if (i <= 7 && i >= -8) - { - if (INTVAL (operands[1]) > 7) - operands[1] = GEN_INT (i); - return \"movqw %1,%0\"; - } - return \"movw %1,%0\"; - } - else if (FP_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < F0_REGNUM) - return \"movwf %1,tos\;movf tos,%0\"; - else - return \"movwf %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - return \"movf %1,tos\;movd tos,%0\"; - return \"movf %1,%0\"; - } - else - return \"movw %1,%0\"; -}") - -(define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r")) - (match_operand:HI 1 "general_operand" "g"))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL(operands[1]) <= 7 && INTVAL(operands[1]) >= -8) - return \"movqw %1,%0\"; - return \"movw %1,%0\"; -}") - -(define_insn "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<,*f,rm") - (match_operand:QI 1 "general_operand" "g,g,*f"))] - "" - "* -{ if (GET_CODE (operands[1]) == CONST_INT) - { - char char_val = (char)INTVAL (operands[1]); - if (char_val <= 7 && char_val >= -8) - { - if (INTVAL (operands[1]) > 7) - operands[1] = GEN_INT (char_val); - return \"movqb %1,%0\"; - } - return \"movb %1,%0\"; - } - else if (FP_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < F0_REGNUM) - return \"movbf %1,tos\;movf tos,%0\"; - else - return \"movbf %1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - return \"movf %1,tos\;movd tos,%0\"; - return \"movf %1,%0\"; - } - else - return \"movb %1,%0\"; -}") - -(define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r")) - (match_operand:QI 1 "general_operand" "g"))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL(operands[1]) < 8 && INTVAL(operands[1]) > -9) - return \"movqb %1,%0\"; - return \"movb %1,%0\"; -}") - -;; Block moves -;; Argument 0 is the destination -;; Argument 1 is the source -;; Argument 2 is the length -;; Argument 3 is the alignment -;; -;; Strategy: Use define_expand to -;; either emit insns directly if it can be done simply or -;; emit rtl to match movmemsi1 which has extra scratch registers -;; which can be used to generate more complex code. - -(define_expand "movmemsi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:SI 2 "general_operand" "")) - (use (match_operand:SI 3 "const_int_operand" ""))])] - "" - " -{ - if (operands[0]) /* avoid unused code messages */ - { - expand_block_move (operands); - DONE; - } -}") - -;; Special Registers: -;; r0 count -;; r1 from -;; r2 to -;; r3 match - - -(define_insn "movmemsi1" - [(set (mem:BLK (reg:SI 2)) - (mem:BLK (reg:SI 1))) - (use (reg:SI 0)) - (set (reg:SI 2) (plus:SI (reg:SI 2) (mult:SI (reg:SI 0) (match_operand:SI 0 "const_int_operand" "")))) - (set (reg:SI 1) (plus:SI (reg:SI 1) (mult:SI (reg:SI 0) (match_dup 0)))) - (set (reg:SI 0) (const_int 0))] - "" - "* - { - int align = INTVAL(operands[0]); - if (align == 4) - return \"movsd\"; - else - return \"movsb\"; - }") - -(define_insn "movmemsi2" - [(set (mem:BLK (match_operand:SI 0 "address_operand" "p")) - (mem:BLK (match_operand:SI 1 "address_operand" "p"))) - (use (match_operand 2 "immediate_operand" "i"))] - "" - "movmd %a1,%a0,%2") - - -;; Extension and truncation insns. -;; Those for integer source operand -;; are ordered widest source type first. - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "" - "movxwd %1,%0") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "" - "movxbw %1,%0") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "" - "movxbd %1,%0") - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") - (float_extend:DF (match_operand:SF 1 "general_operand" "fmF")))] - "TARGET_32081" - "movfl %1,%0") - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (float_truncate:SF (match_operand:DF 1 "general_operand" "lmF")))] - "TARGET_32081" - "movlf %1,%0") - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "" - "movzwd %1,%0") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "" - "movzbw %1,%0") - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "" - "movzbd %1,%0") - -;; Fix-to-float conversion insns. -;; Note that the ones that start with SImode come first. -;; That is so that an operand that is a CONST_INT -;; (and therefore lacks a specific machine mode). -;; will be recognized as SImode (which is always valid) -;; rather than as QImode or HImode. - -;; Rumor has it that the National part does not correctly convert -;; constant ints to floats. This conversion is therefore disabled. -;; A register must be used to perform the conversion. - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))] - "TARGET_32081" - "movdf %1,%0") - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))] - "TARGET_32081" - "movdl %1,%0") - -(define_insn "floathisf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (float:SF (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "TARGET_32081" - "movwf %1,%0") - -(define_insn "floathidf2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") - (float:DF (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "TARGET_32081" - "movwl %1,%0") - -(define_insn "floatqisf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (float:SF (match_operand:QI 1 "nonimmediate_operand" "rm")))] - "TARGET_32081" - "movbf %1,%0") - -; Some assemblers warn that this insn doesn't work. -; Maybe they know something we don't. -;(define_insn "floatqidf2" -; [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") -; (float:DF (match_operand:QI 1 "nonimmediate_operand" "rm")))] -; "TARGET_32081" -; "movbl %1,%0") - -;; Float-to-fix conversion insns. -;; The sequent compiler always generates "trunc" insns. - -(define_insn "fixsfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (fix:QI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfb %1,%0") - -(define_insn "fixsfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (fix:HI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfw %1,%0") - -(define_insn "fixsfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (fix:SI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfd %1,%0") - -(define_insn "fixdfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (fix:QI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "trunclb %1,%0") - -(define_insn "fixdfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (fix:HI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "trunclw %1,%0") - -(define_insn "fixdfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (fix:SI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "truncld %1,%0") - -;; Unsigned - -(define_insn "fixunssfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:QI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfb %1,%0") - -(define_insn "fixunssfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:HI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfw %1,%0") - -(define_insn "fixunssfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:SI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "fm"))))] - "TARGET_32081" - "truncfd %1,%0") - -(define_insn "fixunsdfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:QI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "trunclb %1,%0") - -(define_insn "fixunsdfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:HI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "trunclw %1,%0") - -(define_insn "fixunsdfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (unsigned_fix:SI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "lm"))))] - "TARGET_32081" - "truncld %1,%0") - -;;; These are not yet used by GCC -(define_insn "fix_truncsfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (fix:QI (match_operand:SF 1 "nonimmediate_operand" "fm")))] - "TARGET_32081" - "truncfb %1,%0") - -(define_insn "fix_truncsfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (fix:HI (match_operand:SF 1 "nonimmediate_operand" "fm")))] - "TARGET_32081" - "truncfw %1,%0") - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (fix:SI (match_operand:SF 1 "nonimmediate_operand" "fm")))] - "TARGET_32081" - "truncfd %1,%0") - -(define_insn "fix_truncdfqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (fix:QI (match_operand:DF 1 "nonimmediate_operand" "lm")))] - "TARGET_32081" - "trunclb %1,%0") - -(define_insn "fix_truncdfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (fix:HI (match_operand:DF 1 "nonimmediate_operand" "lm")))] - "TARGET_32081" - "trunclw %1,%0") - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (fix:SI (match_operand:DF 1 "nonimmediate_operand" "lm")))] - "TARGET_32081" - "truncld %1,%0") - -;; Multiply-add instructions -(define_insn "*madddf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=v,v,&lm") - (plus:DF (mult:DF (match_operand:DF 1 "general_operand" "%lmF,0,0") - (match_operand:DF 2 "general_operand" "lmF,lmF,lmF")) - (match_operand:DF 3 "general_operand" "0,lmF,lmF")))] - "TARGET_MULT_ADD" - "@ - dotl %1,%2 - polyl %2,%3 - mull %2,%0\;addl %3,%0") - -(define_insn "*maddsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=u,u,&fm") - (plus:SF (mult:SF (match_operand:SF 1 "general_operand" "%fmF,0,0") - (match_operand:SF 2 "general_operand" "fmF,fmF,fmF")) - (match_operand:SF 3 "general_operand" "0,fmF,fmF")))] - "TARGET_MULT_ADD" - "@ - dotf %1,%2 - polyf %2,%3 - mulf %2,%0\;addf %3,%0") - - -;; Multiply-sub instructions -(define_insn "*msubdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=&v,&lm") - (minus:DF (mult:DF (match_operand:DF 1 "general_operand" "%lmF,0") - (match_operand:DF 2 "general_operand" "lmF,lmF")) - (match_operand:DF 3 "general_operand" "lmF,lmF")))] - "TARGET_MULT_ADD" - "@ - negl %3,%0\;dotl %1,%2 - mull %2,%0\;subl %3,%0") - -(define_insn "*msubsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=&u,&fm") - (minus:SF (mult:SF (match_operand:SF 1 "general_operand" "%fmF,0") - (match_operand:SF 2 "general_operand" "fmF,fmF")) - (match_operand:SF 3 "general_operand" "fmF,fmF")))] - "TARGET_MULT_ADD" - "@ - negf %3,%0\;dotf %1,%2 - mulf %2,%0\;subf %3,%0") - -;;- All kinds of add instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm") - (plus:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "lmF")))] - "TARGET_32081" - "addl %2,%0") - - -(define_insn "addsf3" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm") - (plus:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "fmF")))] - "TARGET_32081" - "addf %2,%0") - -(define_insn "*add_to_sp" - [(set (reg:SI 25) - (plus:SI (reg:SI 25) - (match_operand:SI 0 "immediate_operand" "i")))] - "GET_CODE (operands[0]) == CONST_INT" - "* -{ -#ifndef SEQUENT_ADJUST_STACK - if (TARGET_32532) - if (INTVAL (operands[0]) == 8) - return \"cmpd tos,tos\"; - if (TARGET_32532 || TARGET_32332) - if (INTVAL (operands[0]) == 4) - return \"cmpqd %$0,tos\"; -#endif - if (! TARGET_32532) - { - if (INTVAL (operands[0]) < 64 && INTVAL (operands[0]) > -64) - return \"adjspb %n0\"; - else if (INTVAL (operands[0]) < 8192 && INTVAL (operands[0]) >= -8192) - return \"adjspw %n0\"; - } - return \"adjspd %n0\"; -}") - -(define_insn "adddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro") - (plus:DI (match_operand:DI 1 "general_operand" "%0") - (match_operand:DI 2 "general_operand" "ron")))] - "" - "* -{ - rtx low[3], high[3], xops[4]; - split_di (operands, 3, low, high); - xops[0] = low[0]; - xops[1] = high[0]; - xops[2] = low[2]; - xops[3] = high[2]; - - if (GET_CODE (xops[2]) == CONST_INT) - { - int i = INTVAL (xops[2]); - - if (i <= 7 && i >= -8) - { - if (i == 0) - { - i = INTVAL (xops[3]); - if (i <= 7 && i >= -8) - output_asm_insn (\"addqd %3,%1\", xops); - else - output_asm_insn (\"addd %3,%1\", xops); - } - else - { - output_asm_insn (\"addqd %2,%0\", xops); - output_asm_insn (\"addcd %3,%1\", xops); - } - return \"\"; - } - } - output_asm_insn (\"addd %2,%0\", xops); - output_asm_insn (\"addcd %3,%1\", xops); - return \"\"; -}") - -;; See Note 1 -(define_insn "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,=rm<,=rm<") - (plus:SI (match_operand:SI 1 "general_operand" "%0,r,xy") - (match_operand:SI 2 "general_operand" "g,i,i")))] - "" - "* -{ - if (which_alternative == 1) - { - if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - if (NS32K_DISPLACEMENT_P (i)) - return \"addr %c2(%1),%0\"; - else - return \"movd %1,%0\;addd %2,%0\"; - } - else - { - if (flag_pic) - return \"addr %a2[%1:b],%0\"; - else - return \"addr %c2(%1),%0\"; - } - } - else if (which_alternative == 2) - { - if (GET_CODE (operands[2]) == CONST_INT && - NS32K_DISPLACEMENT_P (INTVAL (operands[2]))) - return \"addr %c2(%1),%0\"; - else - return \"sprd %1,%0\;addd %2,%0\"; - } - else if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - - if (i <= 7 && i >= -8) - return \"addqd %2,%0\"; - else if (! TARGET_32532 && GET_CODE (operands[0]) == REG - && NS32K_DISPLACEMENT_P (i)) - return \"addr %c2(%0),%0\"; - } - return \"addd %2,%0\"; -}") - -(define_insn "addhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (plus:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - if (i <= 7 && i >= -8) - return \"addqw %2,%0\"; - } - return \"addw %2,%0\"; -}") - -(define_insn "*addhi_strict_low3" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r")) - (plus:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8) - return \"addqw %2,%0\"; - return \"addw %2,%0\"; -}") - -(define_insn "addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (plus:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - if (i <= 7 && i >= -8) - return \"addqb %2,%0\"; - } - return \"addb %2,%0\"; -}") - -(define_insn "*addqi_strict_low3" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r")) - (plus:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8) - return \"addqb %2,%0\"; - return \"addb %2,%0\"; -}") - -;;- All kinds of subtract instructions. - -(define_insn "subdf3" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm") - (minus:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "lmF")))] - "TARGET_32081" - "subl %2,%0") - -(define_insn "subsf3" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm") - (minus:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "fmF")))] - "TARGET_32081" - "subf %2,%0") - -(define_insn "*sub_from_sp" - [(set (reg:SI 25) - (minus:SI (reg:SI 25) - (match_operand:SI 0 "immediate_operand" "i")))] - "GET_CODE (operands[0]) == CONST_INT" - "* -{ - if (! TARGET_32532 && GET_CODE(operands[0]) == CONST_INT - && INTVAL(operands[0]) < 64 && INTVAL(operands[0]) > -64) - return \"adjspb %0\"; - return \"adjspd %0\"; -}") - -(define_insn "subdi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro") - (minus:DI (match_operand:DI 1 "general_operand" "0") - (match_operand:DI 2 "general_operand" "ron")))] - "" - "* -{ - rtx low[3], high[3], xops[4]; - split_di (operands, 3, low, high); - xops[0] = low[0]; - xops[1] = high[0]; - xops[2] = low[2]; - xops[3] = high[2]; - - if (GET_CODE (xops[2]) == CONST_INT) - { - int i = INTVAL (xops[2]); - - if (i <= 8 && i >= -7) - { - if (i == 0) - { - i = INTVAL (xops[3]); - if (i <= 8 && i >= -7) - output_asm_insn (\"addqd %n3,%1\", xops); - else - output_asm_insn (\"subd %3,%1\", xops); - } - else - { - output_asm_insn (\"addqd %n2,%0\", xops); - output_asm_insn (\"subcd %3,%1\", xops); - } - return \"\"; - } - } - output_asm_insn (\"subd %2,%0\", xops); - output_asm_insn (\"subcd %3,%1\", xops); - return \"\"; -}") - -(define_insn "subsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (minus:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - - if (i <= 8 && i >= -7) - return \"addqd %n2,%0\"; - } - return \"subd %2,%0\"; -}") - -(define_insn "subhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (minus:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - - if (i <= 8 && i >= -7) - return \"addqw %n2,%0\"; - } - return \"subw %2,%0\"; -}") - -(define_insn "*subhi_strict_low3" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r")) - (minus:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9) - return \"addqw %n2,%0\"; - return \"subw %2,%0\"; -}") - -(define_insn "subqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (minus:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - - if (i <= 8 && i >= -7) - return \"addqb %n2,%0\"; - } - return \"subb %2,%0\"; -}") - -(define_insn "*subqi_strict_low3" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r")) - (minus:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9) - return \"addqb %n2,%0\"; - return \"subb %2,%0\"; -}") - -;;- Multiply instructions. - -(define_insn "muldf3" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm") - (mult:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "lmF")))] - "TARGET_32081" - "mull %2,%0") - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm") - (mult:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "fmF")))] - "TARGET_32081" - "mulf %2,%0") - -;; See note 1 -(define_insn "mulsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "muld %2,%0") - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (mult:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "mulw %2,%0") - -(define_insn "mulqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (mult:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "mulb %2,%0") - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "0")) - (zero_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "rm"))))] - "" - "meid %2,%0") - -;; divmod insns: We can only do the unsigned case. -(define_expand "udivmodsi4" - [(parallel - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (udiv:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (match_operand:SI 3 "nonimmediate_operand" "") - (umod:SI (match_dup 1) (match_dup 2)))])] - "" - " -{ - rtx temp = gen_reg_rtx(DImode); - rtx insn, first, last; - first = emit_move_insn(gen_lowpart(SImode, temp), operands[1]); - emit_move_insn(gen_highpart(SImode, temp), const0_rtx); - emit_insn(gen_udivmoddisi4_internal(temp, temp, operands[2])); - last = emit_move_insn(temp, temp); - { - rtx divdi, moddi, divsi, modsi; - divsi = gen_rtx_UDIV (SImode, operands[1], operands[2]); - modsi = gen_rtx_UMOD (SImode, operands[1], operands[2]); - divdi = gen_rtx_ZERO_EXTEND (DImode, divsi); - moddi = gen_rtx_ZERO_EXTEND (DImode, modsi); - REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, - REG_NOTES (first)); - REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, - gen_rtx_EXPR_LIST (REG_EQUAL, - gen_rtx_IOR (DImode, moddi, - gen_rtx_ASHIFT (DImode, divdi, GEN_INT(32))), - REG_NOTES (last))); - } - - insn = emit_move_insn(operands[0], gen_highpart(SImode, temp)); - insn = emit_move_insn(operands[3], gen_lowpart(SImode, temp)); - DONE; -}") - -;; If we try and describe what this does, we have to zero-expand an -;; operand, which prevents it being a constant (VOIDmode) (see udivmoddisi4 -;; below. This udivmoddisi4_internal never matches anything and is only -;; ever used when explicitly emitted by a define_expand. -(define_insn "udivmoddisi4_internal" - [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") - (unspec:DI [(match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "general_operand" "g")] 0))] - "" - "deid %2,%0") - -;; Retain this insn which *does* have a pattern indicating what it does, -;; just in case the compiler is smart enough to recognize a substitution. -(define_insn "udivmoddisi4" - [(set (subreg:SI (match_operand:DI 0 "nonimmediate_operand" "=rm") 4) - (truncate:SI (udiv:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))) - (set (subreg:SI (match_operand:DI 3 "nonimmediate_operand" "=0") 0) - (truncate:SI (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))] - "" - "deid %2,%0") - -;;;; Part word variants. These seem to never be used at the moment (gcc -;;;; 2.7.2.2). The code generation prefers to zero extend hi's and qi's -;;;; and use signed div and mod. Keep these insns incase that changes. -;;;; divmod should have an advantage when both div and mod are needed. However, -;;;; divmod uses two registers, so maybe the compiler knows best. -;; -;;(define_expand "udivmodhi4" -;; [(parallel -;; [(set (match_operand:HI 0 "nonimmediate_operand" "") -;; (udiv:HI (match_operand:HI 1 "general_operand" "") -;; (match_operand:HI 2 "general_operand" ""))) -;; (set (match_operand:HI 3 "nonimmediate_operand" "") -;; (umod:HI (match_dup 1) (match_dup 2)))])] -;; "" -;; " -;;{ -;; rtx temp = gen_reg_rtx(DImode); -;; rtx insn, first, last; -;; first = emit_move_insn(gen_lowpart(HImode, temp), operands[1]); -;; emit_move_insn(gen_highpart (HImode, temp), const0_rtx); -;; operands[2] = force_reg(HImode, operands[2]); -;; emit_insn(gen_udivmoddihi4_internal(temp, temp, operands[2])); -;; last = emit_move_insn(temp, temp); -;; { -;; rtx divdi, moddi, divhi, modhi; -;; divhi = gen_rtx_UDIV (HImode, operands[1], operands[2]); -;; modhi = gen_rtx_UMOD (HImode, operands[1], operands[2]); -;; divdi = gen_rtx_ZERO_EXTEND (DImode, divhi); -;; moddi = gen_rtx_ZERO_EXTEND (DImode, modhi); -;; REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, -;; REG_NOTES (first)); -;; REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, -;; gen_rtx_EXPR_LIST (REG_EQUAL, -;; gen_rtx_IOR (DImode, moddi, -;; gen_rtx_ASHIFT (DImode, divdi, GEN_INT(32))), -;; REG_NOTES (last))); -;; } -;; -;; insn = emit_move_insn(operands[0], gen_highpart(HImode, temp)); -;; insn = emit_move_insn(operands[3], gen_lowpart(HImode, temp)); -;; DONE; -;;}") -;; -;;;; deiw wants two hi's in separate registers or else they can be adjacent -;;;; in memory. DI mode will ensure two registers are available, but if we -;;;; want to allow memory as an operand we would need SI mode. There is no -;;;; way to do this, so just restrict operand 0 and 1 to be in registers. -;;(define_insn "udivmoddihi4_internal" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (unspec:DI [(match_operand:DI 1 "register_operand" "0") -;; (match_operand:HI 2 "general_operand" "g")] 0))] -;; "" -;; "deiw %2,%0") -;; -;;(define_insn "udivmoddihi4" -;; [(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 2) -;; (truncate:HI (udiv:DI (match_operand:DI 1 "register_operand" "0") -;; (zero_extend:DI (match_operand:HI 2 "nonimmediate_operand" "rm"))))) -;; (set (subreg:HI (match_operand:DI 3 "register_operand" "=0") 0) -;; (truncate:HI (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))] -;; "" -;; "deiw %2,%0") -;; -;;(define_expand "udivmodqi4" -;; [(parallel -;; [(set (match_operand:QI 0 "nonimmediate_operand" "") -;; (udiv:QI (match_operand:QI 1 "general_operand" "") -;; (match_operand:QI 2 "general_operand" ""))) -;; (set (match_operand:QI 3 "nonimmediate_operand" "") -;; (umod:QI (match_dup 1) (match_dup 2)))])] -;; "" -;; " -;;{ -;; rtx temp = gen_reg_rtx(DImode); -;; rtx insn, first, last; -;; first = emit_move_insn(gen_lowpart(QImode, temp), operands[1]); -;; emit_move_insn(gen_highpart(QImode, temp), const0_rtx); -;; operands[2] = force_reg(QImode, operands[2]); -;; emit_insn(gen_udivmoddiqi4_internal(temp, temp, operands[2])); -;; last = emit_move_insn(temp, temp); -;; { -;; rtx divdi, moddi, divqi, modqi; -;; divqi = gen_rtx_UDIV (QImode, operands[1], operands[2]); -;; modqi = gen_rtx_UMOD (QImode, operands[1], operands[2]); -;; divdi = gen_rtx_ZERO_EXTEND (DImode, divqi); -;; moddi = gen_rtx_ZERO_EXTEND (DImode, modqi); -;; REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, -;; REG_NOTES (first)); -;; REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, -;; gen_rtx_EXPR_LIST (REG_EQUAL, -;; gen_rtx_IOR (DImode, moddi, -;; gen_rtx_ASHIFT (DImode, divdi, GEN_INT(32))), -;; REG_NOTES (last))); -;; } -;; -;; insn = emit_move_insn(operands[0], gen_highpart(QImode, temp)); -;; insn = emit_move_insn(operands[3], gen_lowpart(QImode, temp)); -;; DONE; -;;}") -;; -;;;; deib wants two qi's in separate registers or else they can be adjacent -;;;; in memory. DI mode will ensure two registers are available, but if we -;;;; want to allow memory as an operand we would need HI mode. There is no -;;;; way to do this, so just restrict operand 0 and 1 to be in registers. -;;(define_insn "udivmoddiqi4_internal" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (unspec:DI [(match_operand:DI 1 "register_operand" "0") -;; (match_operand:QI 2 "general_operand" "g")] 0))] -;; "" -;; "deib %2,%0") -;; -;;(define_insn "udivmoddiqi4" -;; [(set (subreg:QI (match_operand:DI 0 "register_operand" "=r") 1) -;; (truncate:QI (udiv:DI (match_operand:DI 1 "register_operand" "0") -;; (zero_extend:DI (match_operand:QI 2 "nonimmediate_operand" "rm"))))) -;; (set (subreg:QI (match_operand:DI 3 "register_operand" "=0") 0) -;; (truncate:QI (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))] -;; "" -;; "deib %2,%0") - -;;- Divide instructions. - -(define_insn "divdf3" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm") - (div:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "lmF")))] - "TARGET_32081" - "divl %2,%0") - -(define_insn "divsf3" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm") - (div:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "fmF")))] - "TARGET_32081" - "divf %2,%0") - -;; See note 1 -(define_insn "divsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (div:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "quod %2,%0") - -(define_insn "divhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (div:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "quow %2,%0") - -(define_insn "divqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (div:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "quob %2,%0") - -;; Remainder instructions. - -;; See note 1 -(define_insn "modsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (mod:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "remd %2,%0") - -(define_insn "modhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (mod:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "remw %2,%0") - -(define_insn "modqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (mod:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "remb %2,%0") - - -;;- Logical Instructions: AND - -;; See note 1 -(define_insn "andsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (and:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if ((INTVAL (operands[2]) | 0xff) == 0xffffffff) - { - if (INTVAL (operands[2]) == 0xffffff00) - return \"movqb %$0,%0\"; - else - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); - return \"andb %2,%0\"; - } - } - if ((INTVAL (operands[2]) | 0xffff) == 0xffffffff) - { - if (INTVAL (operands[2]) == 0xffff0000) - return \"movqw %$0,%0\"; - else - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); - return \"andw %2,%0\"; - } - } - } - return \"andd %2,%0\"; -}") - -(define_insn "andhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (and:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) | 0xff) == 0xffffffff) - { - if (INTVAL (operands[2]) == 0xffffff00) - return \"movqb %$0,%0\"; - else - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); - return \"andb %2,%0\"; - } - } - return \"andw %2,%0\"; -}") - -(define_insn "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (and:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "andb %2,%0") - -;; See note 1 -(define_insn "*bicsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (and:SI (not:SI (match_operand:SI 1 "general_operand" "g")) - (match_operand:SI 2 "general_operand" "0")))] - "" - "bicd %1,%0") - -(define_insn "*bichi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (and:HI (not:HI (match_operand:HI 1 "general_operand" "g")) - (match_operand:HI 2 "general_operand" "0")))] - "" - "bicw %1,%0") - -(define_insn "*bicqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (and:QI (not:QI (match_operand:QI 1 "general_operand" "g")) - (match_operand:QI 2 "general_operand" "0")))] - "" - "bicb %1,%0") - -;;- Bit set instructions. - -;; See note 1 -(define_insn "iorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ior:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) { - if ((INTVAL (operands[2]) & 0xffffff00) == 0) - return \"orb %2,%0\"; - if ((INTVAL (operands[2]) & 0xffff0000) == 0) - return \"orw %2,%0\"; - } - return \"ord %2,%0\"; -}") - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ior:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE(operands[2]) == CONST_INT && - (INTVAL(operands[2]) & 0xffffff00) == 0) - return \"orb %2,%0\"; - return \"orw %2,%0\"; -}") - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (ior:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "orb %2,%0") - -;;- xor instructions. - -;; See note 1 -(define_insn "xorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (xor:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) { - if ((INTVAL (operands[2]) & 0xffffff00) == 0) - return \"xorb %2,%0\"; - if ((INTVAL (operands[2]) & 0xffff0000) == 0) - return \"xorw %2,%0\"; - } - return \"xord %2,%0\"; -}") - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (xor:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - if (GET_CODE(operands[2]) == CONST_INT && - (INTVAL(operands[2]) & 0xffffff00) == 0) - return \"xorb %2,%0\"; - return \"xorw %2,%0\"; -}") - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (xor:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "g")))] - "" - "xorb %2,%0") - -(define_insn "negdf2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") - (neg:DF (match_operand:DF 1 "general_operand" "lmF")))] - "TARGET_32081" - "negl %1,%0") - -(define_insn "negsf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (neg:SF (match_operand:SF 1 "general_operand" "fmF")))] - "TARGET_32081" - "negf %1,%0") - -(define_insn "negdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro") - (neg:DI (match_operand:DI 1 "nonimmediate_operand" "ro")))] - "" - "* -{ - rtx low[2], high[2], xops[4]; - split_di (operands, 2, low, high); - xops[0] = low[0]; - xops[1] = high[0]; - xops[2] = low[1]; - xops[3] = high[1]; - - if (rtx_equal_p (operands[0], operands[1])) - { - output_asm_insn (\"negd %3,%1\", xops); - output_asm_insn (\"negd %2,%0\", xops); - output_asm_insn (\"subcd %$0,%1\", xops); - } - else - { - output_asm_insn (\"negd %2,%0\", xops); - output_asm_insn (\"movqd %$0,%1\", xops); - output_asm_insn (\"subcd %3,%1\", xops); - } - return \"\"; -}") - -;; See note 1 -(define_insn "negsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (neg:SI (match_operand:SI 1 "general_operand" "g")))] - "" - "negd %1,%0") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (neg:HI (match_operand:HI 1 "general_operand" "g")))] - "" - "negw %1,%0") - -(define_insn "negqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (neg:QI (match_operand:QI 1 "general_operand" "g")))] - "" - "negb %1,%0") - -;; See note 1 -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (not:SI (match_operand:SI 1 "general_operand" "g")))] - "" - "comd %1,%0") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (not:HI (match_operand:HI 1 "general_operand" "g")))] - "" - "comw %1,%0") - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (not:QI (match_operand:QI 1 "general_operand" "g")))] - "" - "comb %1,%0") - -;; arithmetic left and right shift operations -;; on the 32532 we will always use lshd for arithmetic left shifts, -;; because it is three times faster. Broken programs which -;; use negative shift counts are probably broken differently -;; than elsewhere. - -;; alternative 0 never matches on the 32532 -;; See note 1 -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") - (ashift:SI (match_operand:SI 1 "general_operand" "r,0") - (match_operand:SI 2 "general_operand" "I,g")))] - "" - "* -{ if (TARGET_32532) - return \"lshd %2,%0\"; - else - return output_shift_insn (operands); -}") - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) == 1) - return \"addw %0,%0\"; - else if (! TARGET_32532 && INTVAL (operands[2]) == 2) - return \"addw %0,%0\;addw %0,%0\"; - } - if (TARGET_32532) - return \"lshw %2,%0\"; - else - return \"ashw %2,%0\"; -}") - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (ashift:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) == 1) - return \"addb %0,%0\"; - else if (! TARGET_32532 && INTVAL (operands[2]) == 2) - return \"addb %0,%0\;addb %0,%0\"; - } - if (TARGET_32532) - return \"lshb %2,%0\"; - else - return \"ashb %2,%0\"; -}") - -;; Arithmetic right shift on the 32k works by negating the shift count. -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*ashrisi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "ashd %n2,%0") - -(define_insn "*ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "ashd %2,%0") - -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*ashrihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "ashw %n2,%0") - -(define_insn "*ashrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "ashw %2,%0") - -(define_expand "ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*ashriqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "ashb %n2,%0") - -(define_insn "*ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "ashb %2,%0") - -;; logical shift instructions - -;; Logical right shift on the 32k works by negating the shift count. -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*lshrisi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "lshd %n2,%0") - -(define_insn "*lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "lshd %2,%0") - -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*lshrihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "lshw %n2,%0") - -(define_insn "*lshrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "lshw %2,%0") - -(define_expand "lshrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*lshriqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "lshb %n2,%0") - -(define_insn "*lshrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "lshb %2,%0") - -;; Rotate instructions - -;; See note 1 -(define_insn "rotlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotate:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "rotd %2,%0") - -(define_insn "rotlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotate:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "rotw %2,%0") - -(define_insn "rotlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (rotate:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "rotb %2,%0") - -;; Right rotate on the 32k works by negating the shift count. -(define_expand "rotrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*rotrisi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "rotd %n2,%0") - -(define_insn "*rotrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "rotd %2,%0") - -(define_expand "rotrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*rotrihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "rotw %n2,%0") - -(define_insn "*rotrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "rotw %2,%0") - -(define_expand "rotrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (rotatert:QI (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*rotriqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (rotatert:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "rotb %n2,%0") - -(define_insn "*rotrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (rotatert:QI (match_operand:QI 1 "general_operand" "0") - (neg:SI (match_operand:SI 2 "register_operand" "r"))))] - "" - "rotb %2,%0") - -;;- load or push effective address -;; These come after the move, add, and multiply patterns -;; because we don't want pushl $1 turned into pushad 1. - -(define_insn "*addrsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ - if (REG_P (operands[0]) - && GET_CODE (operands[1]) == MULT - && GET_CODE (XEXP (operands[1], 1)) == CONST_INT - && (INTVAL (XEXP (operands[1], 1)) == 2 - || INTVAL (XEXP (operands[1], 1)) == 4)) - { - rtx xoperands[3]; - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - xoperands[2] = GEN_INT (INTVAL (XEXP (operands[1], 1)) >> 1); - return output_shift_insn (xoperands); - } - return \"addr %a1,%0\"; -}") - -;;; Index insns. These are about the same speed as multiply-add counterparts. -;;; but slower than using power-of-2 shifts if we can use them -; -;;; See note 1 -;(define_insn "" -; [(set (match_operand:SI 0 "register_operand" "=r") -; (plus:SI (match_operand:SI 1 "general_operand" "g") -; (mult:SI (match_operand:SI 2 "register_operand" "0") -; (plus:SI (match_operand:SI 3 "general_operand" "g") (const_int 1)))))] -; "GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) > 8" -; "indexd %0,%3,%1") -; -;(define_insn "" -; [(set (match_operand:SI 0 "register_operand" "=r") -; (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0") -; (plus:SI (match_operand:SI 2 "general_operand" "g") (const_int 1))) -; (match_operand:SI 3 "general_operand" "g")))] -; "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 8" -; "indexd %0,%2,%3") - -;; Set, Clear, and Invert bit - -;; See note 1 -(define_insn "*sbitsi" - [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+rm") - (const_int 1) - (match_operand:SI 1 "general_operand" "g")) - (const_int 1))] - "" - "sbitd %1,%0") - -;; See note 1 -(define_insn "*cbitsi" - [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+rm") - (const_int 1) - (match_operand:SI 1 "general_operand" "g")) - (const_int 0))] - "" - "cbitd %1,%0") - -;; See note 1 -(define_insn "*ibitsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "+rm") - (xor:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "general_operand" "g")) - (match_dup 0)))] - "" - "ibitd %1,%0") - -;; See note 1 -(define_insn "*ibitqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") - (xor:QI (subreg:QI - (ashift:SI (const_int 1) - (match_operand:QI 1 "general_operand" "g")) 0) - (match_dup 0)))] - "" - "ibitb %1,%0") - -;; Recognize jbs and jbc instructions. - -(define_insn "*tbit" - [(set (cc0) - (zero_extract (match_operand:SI 0 "nonimmediate_operand" "rm") - (const_int 1) - (match_operand:SI 1 "general_operand" "g")))] - "" - "* -{ cc_status.flags = CC_Z_IN_F; - return \"tbitd %1,%0\"; -}") - -;; extract(base, width, offset) -;; Signed bit-field extraction is not supported in hardware on the -;; NS 32032. It is therefore better to let GCC figure out a -;; good strategy for generating the proper instruction sequence -;; and represent it as rtl. - -;; Optimize the case of extracting a byte or word from a register. -;; Otherwise we must load a register with the offset of the -;; chunk we want, and perform an extract insn (each of which -;; is very expensive). Since we use the stack to do our bit-twiddling -;; we cannot use it for a destination. Perhaps things are fast -;; enough on the 32532 that such hacks are not needed. - -(define_insn "*extract_bytes" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "i") - (match_operand:SI 3 "const_int_operand" "i")))] - "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) == 8 || INTVAL (operands[3]) == 16 || INTVAL (operands[3]) == 24)" - "* -{ - output_asm_insn (\"movd %1,tos\", operands); - if (INTVAL (operands[2]) == 16) - { - if (INTVAL (operands[3]) == 8) - output_asm_insn (\"movzwd 1(sp),%0\", operands); - else - output_asm_insn (\"movzwd 2(sp),%0\", operands); - } - else - { - if (INTVAL (operands[3]) == 8) - output_asm_insn (\"movzbd 1(sp),%0\", operands); - else if (INTVAL (operands[3]) == 16) - output_asm_insn (\"movzbd 2(sp),%0\", operands); - else - output_asm_insn (\"movzbd 3(sp),%0\", operands); - } - if (TARGET_32532 || TARGET_32332) - return \"cmpqd %$0,tos\"; - else - return \"adjspb %$-4\"; -}") - -;; The exts/ext instructions have the problem that they always access -;; 32 bits even if the bit-field is smaller. For example the instruction -;; extsd 7(r1),r0,2,5 -;; would read not only at address 7(r1) but also at 8(r1) to 10(r1). -;; If these addresses are in a different (unmapped) page a memory fault -;; is the result. -;; -;; Timing considerations: -;; movd 0(r1),r0 3 bytes -;; lshd -26,r0 4 -;; andd 0x1f,r0 5 -;; takes about 13 cycles on the 532 while -;; extsd 7(r1),r0,2,5 5 bytes -;; takes about 21 cycles. -;; -;; The inss/ins instructions suffer from the same problem. -;; -;; A machine specific option (-mbitfield/-mnobitfield) is used -;; to allow/disallow the use of these instructions. - -(define_insn "*bitfield_ext" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (zero_extract:SI (match_operand:SI 1 "register_operand" "g") - (match_operand:SI 2 "const_int_operand" "i") - (match_operand:SI 3 "nonmemory_operand" "rK")))] - "TARGET_BITFIELD" - "* -{ if (GET_CODE (operands[3]) == CONST_INT) - return \"extsd %1,%0,%3,%2\"; - else return \"extd %3,%1,%0,%2\"; -}") - -(define_insn "extzv" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (zero_extract:SI (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "const_int_operand" "i") - (match_operand:SI 3 "nonmemory_operand" "rK")))] - "TARGET_BITFIELD" - "* -{ if (GET_CODE (operands[3]) == CONST_INT) - return \"extsd %1,%0,%3,%2\"; - else return \"extd %3,%1,%0,%2\"; -}") - -(define_insn "*bitfield_set" - [(set (zero_extract:SI (match_operand:SI 0 "memory_operand" "+o,+r") - (match_operand:SI 1 "const_int_operand" "i,i") - (match_operand:SI 2 "nonmemory_operand" "rn,rK")) - (match_operand:SI 3 "nonimmediate_operand" "rm,rm"))] - "TARGET_BITFIELD" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - if (which_alternative == 0 && INTVAL (operands[2]) >= 8) - { - operands[0] = adjust_address (operands[0], QImode, - INTVAL (operands[2]) / 8); - operands[2] = GEN_INT (INTVAL (operands[2]) % 8); - } - if (INTVAL (operands[1]) <= 8) - return \"inssb %3,%0,%2,%1\"; - else if (INTVAL (operands[1]) <= 16) - return \"inssw %3,%0,%2,%1\"; - else - return \"inssd %3,%0,%2,%1\"; - } - return \"insd %2,%3,%0,%1\"; -}") - - -(define_insn "insv" - [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+rm") - (match_operand:SI 1 "const_int_operand" "i") - (match_operand:SI 2 "nonmemory_operand" "rK")) - (match_operand:SI 3 "nonimmediate_operand" "rm"))] - "TARGET_BITFIELD" - "* -{ if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[1]) <= 8) - return \"inssb %3,%0,%2,%1\"; - else if (INTVAL (operands[1]) <= 16) - return \"inssw %3,%0,%2,%1\"; - else - return \"inssd %3,%0,%2,%1\"; - } - return \"insd %2,%3,%0,%1\"; -}") - - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "br %l0") - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"bfc %l0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"bfs %l0\"; - else return \"beq %l0\"; -}") - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"bfs %l0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"bfc %l0\"; - else return \"bne %l0\"; -}") - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "bgt %l0") - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "bhi %l0") - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"bhi 0f\;blt %l0\;0:\"; - else - return \"blt %l0\"; -}") - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "blo %l0") - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "bge %l0") - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "bhs %l0") - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"bhi 0f\;ble %l0\;0:\"; - else - return \"ble %l0\"; -}") - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "bls %l0") - -;; "Reversed" jump instructions. - -(define_insn "*rbeq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"bfs %l0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"bfc %l0\"; - else - return \"bne %l0\"; -}") - -(define_insn "*rbne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"bfc %l0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"bfs %l0\"; - else return \"beq %l0\"; -}") - -(define_insn "*rbgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"ble %l0\;bhi %l0\"; - else - return \"ble %l0\"; -}") - -(define_insn "*rbgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "bls %l0") - -(define_insn "*rblt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"bge %l0\;bhi %l0\"; - else - return \"bge %l0\"; -}") - -(define_insn "*rbltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "bhs %l0") - -(define_insn "*rbge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"blt %l0\;bhi %l0\"; - else - return \"blt %l0\"; -}") - -(define_insn "*rbgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "blo %l0") - -(define_insn "*rble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (cc_prev_status.flags & CC_UNORD) - return \"bgt %l0\;bhi %l0\"; - else - return \"bgt %l0\"; -}") - -(define_insn "*rbleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "bhi %l0") - -;; Subtract-and-jump and Add-and-jump insns. -;; These can actually be used for adding numbers in the range -8 to 7 - -(define_insn "*sub_br" - [(set (pc) - (if_then_else - (ne (match_operand:SI 0 "nonimmediate_operand" "+rm") - (match_operand:SI 1 "const_int_operand" "i")) - (label_ref (match_operand 2 "" "")) - (pc))) - (set (match_dup 0) - (minus:SI (match_dup 0) - (match_dup 1)))] - "INTVAL (operands[1]) > -8 && INTVAL (operands[1]) <= 8" - "acbd %n1,%0,%l2") - -(define_insn "*add_br" - [(set (pc) - (if_then_else - (ne (match_operand:SI 0 "nonimmediate_operand" "+rm") - (match_operand:SI 1 "const_int_operand" "i")) - (label_ref (match_operand 2 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (match_operand:SI 3 "const_int_operand" "i")))] - "INTVAL (operands[1]) == - INTVAL (operands[3]) - && INTVAL (operands[3]) >= -8 && INTVAL (operands[3]) < 8" - "acbd %3,%0,%l2") - -(define_insn "call" - [(call (match_operand:QI 0 "memory_operand" "m") - (match_operand 1 "" ""))] - ;; Operand 1 is not used - "" - "* -{ -#ifndef JSR_ALWAYS - if (GET_CODE (operands[0]) == MEM) - { - rtx temp = XEXP (operands[0], 0); - if (CONSTANT_ADDRESS_P (temp)) - { -#ifdef ENCORE_ASM - return \"bsr %?%0\"; -#else -#ifdef CALL_MEMREF_IMPLICIT - operands[0] = temp; - return \"bsr %0\"; -#else -#ifdef GNX_V3 - return \"bsr %0\"; -#else - return \"bsr %?%a0\"; -#endif -#endif -#endif - } - if (GET_CODE (XEXP (operands[0], 0)) == REG) -#if defined (GNX_V3) || defined (CALL_MEMREF_IMPLICIT) - return \"jsr %0\"; -#else - return \"jsr %a0\"; -#endif - } -#endif /* not JSR_ALWAYS */ - return \"jsr %0\"; -}") - -(define_insn "call_value" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "memory_operand" "m") - (match_operand 2 "" "")))] - ;; Operand 2 is not used - "" - "* -{ -#ifndef JSR_ALWAYS - if (GET_CODE (operands[1]) == MEM) - { - rtx temp = XEXP (operands[1], 0); - if (CONSTANT_ADDRESS_P (temp)) - { -#ifdef ENCORE_ASM - return \"bsr %?%1\"; -#else -#ifdef CALL_MEMREF_IMPLICIT - operands[1] = temp; - return \"bsr %1\"; -#else -#ifdef GNX_V3 - return \"bsr %1\"; -#else - return \"bsr %?%a1\"; -#endif -#endif -#endif - } - if (GET_CODE (XEXP (operands[1], 0)) == REG) -#if defined (GNX_V3) || defined (CALL_MEMREF_IMPLICIT) - return \"jsr %1\"; -#else - return \"jsr %a1\"; -#endif - } -#endif /* not JSR_ALWAYS */ - return \"jsr %1\"; -}") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_insn "return" - [(return)] - "0" - "ret 0") - -(define_insn "abssf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=fm<") - (abs:SF (match_operand:SF 1 "general_operand" "fmF")))] - "TARGET_32081" - "absf %1,%0") - -(define_insn "absdf2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=lm<") - (abs:DF (match_operand:DF 1 "general_operand" "lmF")))] - "TARGET_32081" - "absl %1,%0") - -;; See note 1 -(define_insn "abssi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm<") - (abs:SI (match_operand:SI 1 "general_operand" "g")))] - "" - "absd %1,%0") - -(define_insn "abshi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm<") - (abs:HI (match_operand:HI 1 "general_operand" "g")))] - "" - "absw %1,%0") - -(define_insn "absqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rm<") - (abs:QI (match_operand:QI 1 "general_operand" "g")))] - "" - "absb %1,%0") - -(define_insn "nop" - [(const_int 0)] - "" - "nop") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "jump %0") - -(define_insn "tablejump" - [(set (pc) - (plus:SI (pc) (match_operand:SI 0 "general_operand" "g"))) - (use (label_ref (match_operand 1 "" "")))] - "" - "* -{ - (*targetm.asm_out.internal_label) (asm_out_file, \"LI\", - CODE_LABEL_NUMBER (operands[1])); - return \"cased %0\"; -}") - -;; Scondi instructions -(define_insn "seq" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (eq:SI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfcd %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfsd %0\"; - else return \"seqd %0\"; -}") - -(define_insn "*seqhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (eq:HI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfcw %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfsw %0\"; - else return \"seqw %0\"; -}") - -(define_insn "*seqqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (eq:QI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfcb %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfsb %0\"; - else return \"seqb %0\"; -}") - -(define_insn "sne" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (ne:SI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfsd %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfcd %0\"; - else return \"sned %0\"; -}") - -(define_insn "*snehi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (ne:HI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfsw %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfcw %0\"; - else return \"snew %0\"; -}") - -(define_insn "*sneqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (ne:QI (cc0) (const_int 0)))] - "" - "* -{ if (cc_prev_status.flags & CC_Z_IN_F) - return \"sfsb %0\"; - else if (cc_prev_status.flags & CC_Z_IN_NOT_F) - return \"sfcb %0\"; - else return \"sneb %0\"; -}") - -(define_insn "sgt" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (gt:SI (cc0) (const_int 0)))] - "" - "sgtd %0") - -(define_insn "*sgthi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (gt:HI (cc0) (const_int 0)))] - "" - "sgtw %0") - -(define_insn "*sgtqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (gt:QI (cc0) (const_int 0)))] - "" - "sgtb %0") - -(define_insn "sgtu" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (gtu:SI (cc0) (const_int 0)))] - "" - "shid %0") - -(define_insn "*sgtuhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (gtu:HI (cc0) (const_int 0)))] - "" - "shiw %0") - -(define_insn "*sgtuqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (gtu:QI (cc0) (const_int 0)))] - "" - "shib %0") - -(define_insn "slt" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (lt:SI (cc0) (const_int 0)))] - "" - "sltd %0") - -(define_insn "*slthi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (lt:HI (cc0) (const_int 0)))] - "" - "sltw %0") - -(define_insn "*sltqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (lt:QI (cc0) (const_int 0)))] - "" - "sltb %0") - -(define_insn "sltu" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (ltu:SI (cc0) (const_int 0)))] - "" - "slod %0") - -(define_insn "*sltuhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (ltu:HI (cc0) (const_int 0)))] - "" - "slow %0") - -(define_insn "*sltuqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (ltu:QI (cc0) (const_int 0)))] - "" - "slob %0") - -(define_insn "sge" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (ge:SI (cc0) (const_int 0)))] - "" - "sged %0") - -(define_insn "*sgehi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (ge:HI (cc0) (const_int 0)))] - "" - "sgew %0") - -(define_insn "*sgeqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (ge:QI (cc0) (const_int 0)))] - "" - "sgeb %0") - -(define_insn "sgeu" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (geu:SI (cc0) (const_int 0)))] - "" - "shsd %0") - -(define_insn "*sgeuhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (geu:HI (cc0) (const_int 0)))] - "" - "shsw %0") - -(define_insn "*sgeuqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (geu:QI (cc0) (const_int 0)))] - "" - "shsb %0") - -(define_insn "sle" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (le:SI (cc0) (const_int 0)))] - "" - "sled %0") - -(define_insn "*slehi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (le:HI (cc0) (const_int 0)))] - "" - "slew %0") - -(define_insn "*sleqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (le:QI (cc0) (const_int 0)))] - "" - "sleb %0") - -(define_insn "sleu" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r<") - (leu:SI (cc0) (const_int 0)))] - "" - "slsd %0") - -(define_insn "*sleuhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r<") - (leu:HI (cc0) (const_int 0)))] - "" - "slsw %0") - -(define_insn "*sleuqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r<") - (leu:QI (cc0) (const_int 0)))] - "" - "slsb %0") - -;; ffs instructions - -(define_insn "*ffs" - [(set (match_operand:SI 0 "nonimmediate_operand" "+ro") - (minus:SI - (plus:SI (ffs:SI (zero_extract:SI - (match_operand:SI 1 "general_operand" "g") - (minus:SI (const_int 32) (match_dup 0)) - (match_dup 0))) - (match_dup 0)) - (const_int 1)))] - "" - "ffsd %1,%0\;bfc 1f\;addqd %$-1,%0\;1:") - -(define_expand "ffssi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") (const_int 0)) - (set (match_dup 0) - (minus:SI - (plus:SI (ffs:SI (zero_extract:SI - (match_operand:SI 1 "general_operand" "g") - (minus:SI (const_int 32) (match_dup 0)) - (match_dup 0))) - (match_dup 0)) - (const_int 1))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "" - "operands[1] = make_safe_from(operands[1], operands[0]);") - -;; Speed up stack adjust followed by a HI fixedpoint push. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int -2))) - (set (match_operand:HI 0 "push_operand" "=m") - (match_operand:HI 1 "general_operand" "g"))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,tos\"), - operands); - else - output_asm_insn (\"movzwd %1,tos\", operands); - return \"\"; -}") - -;; Speed up stack adjust followed by a zero_extend:HI(QI) fixedpoint push. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int -2))) - (set (match_operand:HI 0 "push_operand" "=m") - (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,tos\"), - operands); - else - output_asm_insn (\"movzbd %1,tos\", operands); - return \"\"; -}") - -;; Speed up stack adjust followed by a sign_extend:HI(QI) fixedpoint push. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int -2))) - (set (match_operand:HI 0 "push_operand" "=m") - (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,tos\"), - operands); - else - output_asm_insn (\"movxbd %1,tos\", operands); - return \"\"; -}") - -;; Speed up stack adjust followed by a QI fixedpoint push. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int -3))) - (set (match_operand:QI 0 "push_operand" "=m") - (match_operand:QI 1 "general_operand" "g"))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,tos\"), - operands); - else - output_asm_insn (\"movzbd %1,tos\", operands); - return \"\"; -}") - -;; Speed up stack adjust followed by a SI fixedpoint push. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int 4))) - (set (match_operand:SI 0 "push_operand" "=m") - (match_operand:SI 1 "general_operand" "g"))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,0(sp)\"), - operands); - else if (GET_CODE (operands[1]) != REG - && GET_CODE (operands[1]) != MEM - && address_operand (operands[1], SImode)) - output_asm_insn (\"addr %a1,0(sp)\", operands); - else - output_asm_insn (\"movd %1,0(sp)\", operands); - return \"\"; -}") - -;; Speed up stack adjust followed by two fullword fixedpoint pushes. - -(define_peephole - [(set (reg:SI 25) (plus:SI (reg:SI 25) (const_int 8))) - (set (match_operand:SI 0 "push_operand" "=m") - (match_operand:SI 1 "general_operand" "g")) - (set (match_operand:SI 2 "push_operand" "=m") - (match_operand:SI 3 "general_operand" "g"))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1]) - && ! reg_mentioned_p (stack_pointer_rtx, operands[3])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[1]), \"%1,4(sp)\"), - operands); - else if (GET_CODE (operands[1]) != REG - && GET_CODE (operands[1]) != MEM - && address_operand (operands[1], SImode)) - output_asm_insn (\"addr %a1,4(sp)\", operands); - else - output_asm_insn (\"movd %1,4(sp)\", operands); - - if (GET_CODE (operands[3]) == CONST_INT) - output_asm_insn (output_move_dconst (INTVAL (operands[3]), \"%3,0(sp)\"), - operands); - else if (GET_CODE (operands[3]) != REG - && GET_CODE (operands[3]) != MEM - && address_operand (operands[3], SImode)) - output_asm_insn (\"addr %a3,0(sp)\", operands); - else - output_asm_insn (\"movd %3,0(sp)\", operands); - return \"\"; -}") diff --git a/gcc/config/ns32k/ns32k.opt b/gcc/config/ns32k/ns32k.opt deleted file mode 100644 index 94e578e33df..00000000000 --- a/gcc/config/ns32k/ns32k.opt +++ /dev/null @@ -1,108 +0,0 @@ -; Options for the NS32000 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. - -m32032 -Target RejectNegative -Optimize for 32032 - -m32081 -Target RejectNegative Report Mask(32081) -Use hardware fp - -m32332 -Target RejectNegative Report Mask(32332) -Optimize for 32332 - -m32381 -Target RejectNegative Report Mask(32381) -Use the 32381 fpu - -m32532 -Target RejectNegative Report Mask(32532) -Optimize for 32532 - -mbitfield -Target RejectNegative Report Mask(BITFIELD) -Use bit-field instructions - -mhimem -Target RejectNegative Report Mask(HIMEM) -Generate code for high memory - -mieee-compare -Target RejectNegative Report Mask(IEEE_COMPARE) -Use IEEE math for fp comparisons - -mmult-add -Target RejectNegative Report Mask(MULT_ADD) -Use multiply-accumulate fp instructions - -mnobitfield -Target RejectNegative Report InverseMask(BITFIELD) -Do not use bit-field instructions - -mnohimem -Target RejectNegative Report InverseMask(HIMEM) -Generate code for low memory - -mnoieee-compare -Target RejectNegative Report InverseMask(IEEE_COMPARE) -Do not use IEEE math for fp comparisons - -mnomult-add -Target RejectNegative Report InverseMask(MULT_ADD) -Do not use multiply-accumulate fp instructions - -mnoregparm -Target RejectNegative Report InverseMask(REGPARM) -Pass all arguments on the stack - -mnortd -Target RejectNegative Report InverseMask(RTD) -Use the normal calling convention - -mnosb -Target RejectNegative Report InverseMask(SB) -Do not use register sb - -mnosrc -Target RejectNegative Report InverseMask(SRC) -Do not use the 'small register classes' kludge - -mregparm -Target RejectNegative Report Mask(REGPARM) -Pass some arguments in registers - -mrtd -Target RejectNegative Report Mask(RTD) -Use an alternative calling convention - -msb -Target RejectNegative Report Mask(SB) -Register sb is zero, use it for absolute addressing - -msoft-float -Target RejectNegative -Do not use hardware fp - -msrc -Target RejectNegative Report Mask(SRC) -Use the 'small register classes' kludge diff --git a/gcc/config/ns32k/t-ns32k b/gcc/config/ns32k/t-ns32k deleted file mode 100644 index a8b6329d47f..00000000000 --- a/gcc/config/ns32k/t-ns32k +++ /dev/null @@ -1,4 +0,0 @@ -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -LIB2FUNCS_EXTRA = $(srcdir)/config/ns32k/__unorddf2.c \ - $(srcdir)/config/ns32k/__unordsf2.c diff --git a/gcc/config/sparc/openbsd.h b/gcc/config/sparc/openbsd.h deleted file mode 100644 index 99fd5169b16..00000000000 --- a/gcc/config/sparc/openbsd.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Configuration file for sparc OpenBSD target. - Copyright (C) 1999, 2002, 2003, 2004 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. */ - -/* Target OS builtins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__unix__"); \ - builtin_define ("__OpenBSD__"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=OpenBSD"); \ - } \ - while (0) - -/* Layout of source language data types */ - -/* This must agree with <machine/ansi.h> */ -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 32 - -/* Specific options for DBX Output. */ - -/* This is BSD, so it wants DBX format. */ -#define DBX_DEBUGGING_INFO 1 - -/* This is the char to use for continuation */ -#define DBX_CONTIN_CHAR '?' - -/* Stack & calling: aggregate returns. */ - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#undef DEFAULT_PCC_STRUCT_RETURN -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Assembler format: exception region output. */ - -/* All configurations that don't use elf must be explicit about not using - dwarf unwind information. */ -#define DWARF2_UNWIND_INFO 0 - -#undef ASM_PREFERRED_EH_DATA_FORMAT diff --git a/gcc/config/sparc/t-openbsd b/gcc/config/sparc/t-openbsd deleted file mode 100644 index 898a24e079d..00000000000 --- a/gcc/config/sparc/t-openbsd +++ /dev/null @@ -1,5 +0,0 @@ -# The native linker doesn't handle linking -fpic code with -fPIC code. Ugh. -# We cope by building both variants of libgcc. -MULTILIB_OPTIONS = fpic/fPIC -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index e0362635da0..c1b54630b26 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -2244,8 +2244,6 @@ GNU Compiler Collection on your machine. @item @uref{#x-ibm-aix,,*-ibm-aix*} @item -@uref{#ip2k-x-elf,,ip2k-*-elf} -@item @uref{#iq2000-x-elf,,iq2000-*-elf} @item @uref{#m32r-x-elf,,m32r-*-elf} @@ -3178,16 +3176,6 @@ switch and using the configure option @option{--with-cpu-@var{cpu_type}}. @html <hr /> @end html -@heading @anchor{ip2k-x-elf}ip2k-*-elf -Ubicom IP2022 micro controller. -This configuration is intended for embedded systems. -There are no standard Unix configurations. - -Use @samp{configure --target=ip2k-elf --enable-languages=c} to configure GCC@. - -@html -<hr /> -@end html @heading @anchor{iq2000-x-elf}iq2000-*-elf Vitesse IQ2000 processors. These are used in embedded applications. There are no standard Unix configurations. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 48764a63207..3fde0683694 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -599,12 +599,6 @@ Objective-C and Objective-C++ Dialects}. -mam33-2 -mno-am33-2 @gol -mno-crt0 -mrelax} -@emph{NS32K Options} -@gccoptlist{-m32032 -m32332 -m32532 -m32081 -m32381 @gol --mmult-add -mnomult-add -msoft-float -mrtd -mnortd @gol --mregparam -mnoregparam -msb -mnosb @gol --mbitfield -mnobitfield -mhimem -mnohimem} - @emph{PDP-11 Options} @gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol -mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol @@ -6970,7 +6964,6 @@ platform. * MIPS Options:: * MMIX Options:: * MN10300 Options:: -* NS32K Options:: * PDP-11 Options:: * PowerPC Options:: * RS/6000 and PowerPC Options:: @@ -10407,148 +10400,6 @@ has an effect when used on the command line for the final link step. This option makes symbolic debugging impossible. @end table -@node NS32K Options -@subsection NS32K Options -@cindex NS32K options - -These are the @samp{-m} options defined for the 32000 series. The default -values for these options depends on which style of 32000 was selected when -the compiler was configured; the defaults for the most common choices are -given below. - -@table @gcctabopt -@item -m32032 -@itemx -m32032 -@opindex m32032 -@opindex m32032 -Generate output for a 32032. This is the default -when the compiler is configured for 32032 and 32016 based systems. - -@item -m32332 -@itemx -m32332 -@opindex m32332 -@opindex m32332 -Generate output for a 32332. This is the default -when the compiler is configured for 32332-based systems. - -@item -m32532 -@itemx -m32532 -@opindex m32532 -@opindex m32532 -Generate output for a 32532. This is the default -when the compiler is configured for 32532-based systems. - -@item -m32081 -@opindex m32081 -Generate output containing 32081 instructions for floating point. -This is the default for all systems. - -@item -m32381 -@opindex m32381 -Generate output containing 32381 instructions for floating point. This -also implies @option{-m32081}. The 32381 is only compatible with the 32332 -and 32532 cpus. This is the default for the pc532-netbsd configuration. - -@item -mmulti-add -@opindex mmulti-add -Try and generate multiply-add floating point instructions @code{polyF} -and @code{dotF}. This option is only available if the @option{-m32381} -option is in effect. Using these instructions requires changes to -register allocation which generally has a negative impact on -performance. This option should only be enabled when compiling code -particularly likely to make heavy use of multiply-add instructions. - -@item -mnomulti-add -@opindex mnomulti-add -Do not try and generate multiply-add floating point instructions -@code{polyF} and @code{dotF}. This is the default on all platforms. - -@item -msoft-float -@opindex msoft-float -Generate output containing library calls for floating point. -@strong{Warning:} the requisite libraries may not be available. - -@item -mieee-compare -@itemx -mno-ieee-compare -@opindex mieee-compare -@opindex mno-ieee-compare -Control whether or not the compiler uses IEEE floating point -comparisons. These handle correctly the case where the result of a -comparison is unordered. -@strong{Warning:} the requisite kernel support may not be available. - -@item -mnobitfield -@opindex mnobitfield -Do not use the bit-field instructions. On some machines it is faster to -use shifting and masking operations. This is the default for the pc532. - -@item -mbitfield -@opindex mbitfield -Do use the bit-field instructions. This is the default for all platforms -except the pc532. - -@item -mrtd -@opindex mrtd -Use a different function-calling convention, in which functions -that take a fixed number of arguments return pop their -arguments on return with the @code{ret} instruction. - -This calling convention is incompatible with the one normally -used on Unix, so you cannot use it if you need to call libraries -compiled with the Unix compiler. - -Also, you must provide function prototypes for all functions that -take variable numbers of arguments (including @code{printf}); -otherwise incorrect code will be generated for calls to those -functions. - -In addition, seriously incorrect code will result if you call a -function with too many arguments. (Normally, extra arguments are -harmlessly ignored.) - -This option takes its name from the 680x0 @code{rtd} instruction. - - -@item -mregparam -@opindex mregparam -Use a different function-calling convention where the first two arguments -are passed in registers. - -This calling convention is incompatible with the one normally -used on Unix, so you cannot use it if you need to call libraries -compiled with the Unix compiler. - -@item -mnoregparam -@opindex mnoregparam -Do not pass any arguments in registers. This is the default for all -targets. - -@item -msb -@opindex msb -It is OK to use the sb as an index register which is always loaded with -zero. This is the default for the pc532-netbsd target. - -@item -mnosb -@opindex mnosb -The sb register is not available for use or has not been initialized to -zero by the run time system. This is the default for all targets except -the pc532-netbsd. It is also implied whenever @option{-mhimem} or -@option{-fpic} is set. - -@item -mhimem -@opindex mhimem -Many ns32000 series addressing modes use displacements of up to 512MB@. -If an address is above 512MB then displacements from zero can not be used. -This option causes code to be generated which can be loaded above 512MB@. -This may be useful for operating systems or ROM code. - -@item -mnohimem -@opindex mnohimem -Assume code will be loaded in the first 512MB of virtual address space. -This is the default for all platforms. - -@end table - @node PDP-11 Options @subsection PDP-11 Options @cindex PDP-11 Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 5af0d55e10b..bf71b7a80ab 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2165,76 +2165,6 @@ An integer constant with all bits set except exactly one. Any SYMBOL_REF. @end table -@item IP2K---@file{ip2k.h} -@table @code -@item a -@samp{DP} or @samp{IP} registers (general address) - -@item f -@samp{IP} register - -@item j -@samp{IPL} register - -@item k -@samp{IPH} register - -@item b -@samp{DP} register - -@item y -@samp{DPH} register - -@item z -@samp{DPL} register - -@item q -@samp{SP} register - -@item c -@samp{DP} or @samp{SP} registers (offsettable address) - -@item d -Non-pointer registers (not @samp{SP}, @samp{DP}, @samp{IP}) - -@item u -Non-SP registers (everything except @samp{SP}) - -@item R -Indirect through @samp{IP}---Avoid this except for @code{QImode}, since we -can't access extra bytes - -@item S -Indirect through @samp{SP} or @samp{DP} with short displacement (0..127) - -@item T -Data-section immediate value - -@item I -Integers from @minus{}255 to @minus{}1 - -@item J -Integers from 0 to 7---valid bit number in a register - -@item K -Integers from 0 to 127---valid displacement for addressing mode - -@item L -Integers from 1 to 127 - -@item M -Integer @minus{}1 - -@item N -Integer 1 - -@item O -Zero - -@item P -Integers from 0 to 255 -@end table - @item MIPS---@file{mips.h} @table @code @item d diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 043d5128019..ab5287beb73 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-20 Kazu Hirata <kazu@codesourcery.com> + + * gcc.dg/20020312-2.c, gcc.dg/sibcall-3.c, gcc.dg/sibcall-4.c, + gcc.dg/cpp/assert4.c: Don't mention obsolete ports. + 2005-07-19 James A. Morrison <phython@gcc.gnu.org> * gcc.dg/fold-abs-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index 763e167a12b..211fd755ad8 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -44,8 +44,6 @@ extern void abort (void); /* No pic register. */ #elif defined(__mn10300__) /* No pic register. */ -#elif #cpu(ns32k) -/* No pic register. */ #elif defined(__hppa__) /* PIC register is %r27 or %r19, but is used even without -fpic. */ #elif defined(__pdp11__) diff --git a/gcc/testsuite/gcc.dg/cpp/assert4.c b/gcc/testsuite/gcc.dg/cpp/assert4.c index 023bb50cdeb..99b1f5e509a 100644 --- a/gcc/testsuite/gcc.dg/cpp/assert4.c +++ b/gcc/testsuite/gcc.dg/cpp/assert4.c @@ -254,14 +254,6 @@ # error #endif -#if defined __i860__ -# if !#cpu(i860) || !#machine(i860) -# error -# endif -#elif #cpu(i860) || #machine(i860) -# error -#endif - #if defined __ia64__ # if !#cpu(ia64) || !#machine(ia64) # error @@ -319,14 +311,6 @@ # error #endif -#if defined __ns32k__ -# if !#cpu(ns32k) || !#machine(ns32k) -# error -# endif -#elif #cpu(ns32k) || #machine(ns32k) -# error -#endif - #if defined __pdp11__ # if !#cpu(pdp11) || !#machine(pdp11) # error diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c index 490e193541f..95edee107d8 100644 --- a/gcc/testsuite/gcc.dg/sibcall-3.c +++ b/gcc/testsuite/gcc.dg/sibcall-3.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* ns32k-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ /* The option -foptimize-sibling-calls is the default, but serves as diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c index 7237310b3a0..3991ecc9279 100644 --- a/gcc/testsuite/gcc.dg/sibcall-4.c +++ b/gcc/testsuite/gcc.dg/sibcall-4.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* ns32k-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ /* The option -foptimize-sibling-calls is the default, but serves as |