summaryrefslogtreecommitdiff
path: root/gcc/config/romp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/romp')
-rwxr-xr-xgcc/config/romp/romp.c2038
-rwxr-xr-xgcc/config/romp/romp.h1636
-rwxr-xr-xgcc/config/romp/romp.md2776
-rwxr-xr-xgcc/config/romp/x-mach5
-rwxr-xr-xgcc/config/romp/x-romp11
-rwxr-xr-xgcc/config/romp/xm-romp.h54
6 files changed, 0 insertions, 6520 deletions
diff --git a/gcc/config/romp/romp.c b/gcc/config/romp/romp.c
deleted file mode 100755
index 0f64a9e..0000000
--- a/gcc/config/romp/romp.c
+++ /dev/null
@@ -1,2038 +0,0 @@
-/* Subroutines used for code generation on ROMP.
- Copyright (C) 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
- Contributed by Richard Kenner (kenner@nyu.edu)
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-#include "config.h"
-#include <stdio.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 "flags.h"
-#include "recog.h"
-#include "expr.h"
-#include "obstack.h"
-#include "tree.h"
-
-#define min(A,B) ((A) < (B) ? (A) : (B))
-#define max(A,B) ((A) > (B) ? (A) : (B))
-
-static int unsigned_comparisons_p ();
-static void output_loadsave_fpregs ();
-static void output_fpops ();
-static void init_fpops ();
-
-/* Return 1 if the insn using CC0 set by INSN does not contain
- any unsigned tests applied to the condition codes.
-
- Based on `next_insn_tests_no_inequality' in recog.c. */
-
-int
-next_insn_tests_no_unsigned (insn)
- rtx insn;
-{
- register rtx next = next_cc0_user (insn);
-
- if (next == 0)
- {
- if (find_reg_note (insn, REG_UNUSED, cc0_rtx))
- return 1;
- else
- abort ();
- }
-
- return ((GET_CODE (next) == JUMP_INSN
- || GET_CODE (next) == INSN
- || GET_CODE (next) == CALL_INSN)
- && ! unsigned_comparisons_p (PATTERN (next)));
-}
-
-static int
-unsigned_comparisons_p (x)
- rtx x;
-{
- register char *fmt;
- register int len, i;
- register enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case REG:
- case PC:
- case CC0:
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- return 0;
-
- case LTU:
- case GTU:
- case LEU:
- case GEU:
- return (XEXP (x, 0) == cc0_rtx || XEXP (x, 1) == cc0_rtx);
- }
-
- len = GET_RTX_LENGTH (code);
- fmt = GET_RTX_FORMAT (code);
-
- for (i = 0; i < len; i++)
- {
- if (fmt[i] == 'e')
- {
- if (unsigned_comparisons_p (XEXP (x, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- {
- register int j;
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (unsigned_comparisons_p (XVECEXP (x, i, j)))
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Update the condition code from the insn. Look mostly at the first
- byte of the machine-specific insn description information.
-
- cc_state.value[12] refer to two possible values that might correspond
- to the CC. We only store register values. */
-
-update_cc (body, insn)
- rtx body;
- rtx insn;
-{
- switch (get_attr_cc (insn))
- {
- case CC_NONE:
- /* Insn does not affect the CC at all. */
- break;
-
- case CC_CHANGE0:
- /* Insn doesn't affect the CC but does modify operand[0], known to be
- a register. */
- if (cc_status.value1 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
- cc_status.value1 = 0;
-
- if (cc_status.value2 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
- cc_status.value2 = 0;
-
- break;
-
- case CC_COPY1TO0:
- /* Insn copies operand[1] to operand[0], both registers, but doesn't
- affect the CC. */
- if (cc_status.value1 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
- cc_status.value1 = 0;
-
- if (cc_status.value2 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
- cc_status.value2 = 0;
-
- if (cc_status.value1 != 0
- && rtx_equal_p (cc_status.value1, recog_operand[1]))
- cc_status.value2 = recog_operand[0];
-
- if (cc_status.value2 != 0
- && rtx_equal_p (cc_status.value2, recog_operand[1]))
- cc_status.value1 = recog_operand[0];
-
- break;
-
- case CC_CLOBBER:
- /* Insn clobbers CC. */
- CC_STATUS_INIT;
- break;
-
- case CC_SETS:
- /* Insn sets CC to recog_operand[0], but overflow is impossible. */
- CC_STATUS_INIT;
- cc_status.flags |= CC_NO_OVERFLOW;
- cc_status.value1 = recog_operand[0];
- break;
-
- case CC_COMPARE:
- /* Insn is a compare which sets the CC fully. Update CC_STATUS for this
- compare and mark whether the test will be signed or unsigned. */
- {
- register rtx p = PATTERN (insn);
-
- CC_STATUS_INIT;
-
- if (GET_CODE (p) == PARALLEL)
- p = XVECEXP (p, 0, 0);
- cc_status.value1 = SET_SRC (p);
-
- if (GET_CODE (SET_SRC (p)) == REG)
- cc_status.flags |= CC_NO_OVERFLOW;
- if (! next_insn_tests_no_unsigned (insn))
- cc_status.flags |= CC_UNSIGNED;
- }
- break;
-
- case CC_TBIT:
- /* Insn sets T bit if result is non-zero. Next insn must be branch. */
- CC_STATUS_INIT;
- cc_status.flags = CC_IN_TB | CC_NOT_NEGATIVE;
- break;
-
- default:
- abort ();
- }
-}
-
-/* Return 1 if a previous compare needs to be re-issued. This will happen
- if two compares tested the same objects, but one was signed and the
- other unsigned. OP is the comparison operation being performed. */
-
-int
-restore_compare_p (op)
- rtx op;
-{
- enum rtx_code code = GET_CODE (op);
-
- return (((code == GEU || code == LEU || code == GTU || code == LTU)
- && ! (cc_status.flags & CC_UNSIGNED))
- || ((code == GE || code == LE || code == GT || code == LT)
- && (cc_status.flags & CC_UNSIGNED)));
-}
-
-/* Generate the (long) string corresponding to an inline multiply insn.
- Note that `r10' does not refer to the register r10, but rather to the
- SCR used as the MQ. */
-char *
-output_in_line_mul ()
-{
- static char insns[200];
- int i;
-
- strcpy (insns, "s %0,%0\n");
- strcat (insns, "\tmts r10,%1\n");
- for (i = 0; i < 16; i++)
- strcat (insns, "\tm %0,%2\n");
- strcat (insns, "\tmfs r10,%0");
-
- return insns;
-}
-
-/* Returns 1 if OP is a memory reference with an offset from a register within
- the range specified. The offset must also be a multiple of the size of the
- mode. */
-
-static int
-memory_offset_in_range_p (op, mode, low, high)
- register rtx op;
- enum machine_mode mode;
- int low, high;
-{
- int offset = 0;
-
- if (! memory_operand (op, mode))
- return 0;
-
- while (GET_CODE (op) == SUBREG)
- {
- offset += SUBREG_WORD (op) * UNITS_PER_WORD;
-#if BYTES_BIG_ENDIAN
- offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- - min (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))));
-#endif
- op = SUBREG_REG (op);
- }
-
- /* We must now have either (mem (reg (x)), (mem (plus (reg (x)) (c))),
- or a constant pool address. */
- if (GET_CODE (op) != MEM)
- abort ();
-
- /* Now use the actual mode and get the address. */
- mode = GET_MODE (op);
- op = XEXP (op, 0);
- if (GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
- offset = get_pool_offset (op) + 12;
- else if (GET_CODE (op) == PLUS)
- {
- if (GET_CODE (XEXP (op, 1)) != CONST_INT
- || ! register_operand (XEXP (op, 0), Pmode))
- return 0;
-
- offset += INTVAL (XEXP (op, 1));
- }
-
- else if (! register_operand (op, Pmode))
- return 0;
-
- return (offset >= low && offset <= high
- && (offset % GET_MODE_SIZE (mode) == 0));
-}
-
-/* Return 1 if OP is a valid operand for a memory reference insn that can
- only reference indirect through a register. */
-
-int
-zero_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return memory_offset_in_range_p (op, mode, 0, 0);
-}
-
-/* Return 1 if OP is a valid operand for a `short' memory reference insn. */
-
-int
-short_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- return memory_offset_in_range_p (op, mode, 0,
- 15 * min (UNITS_PER_WORD,
- GET_MODE_SIZE (mode)));
-}
-
-/* Returns 1 if OP is a memory reference involving a symbolic constant
- that is not in the constant pool. */
-
-int
-symbolic_memory_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (! memory_operand (op, mode))
- return 0;
-
- while (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- if (GET_CODE (op) != MEM)
- abort ();
-
- op = XEXP (op, 0);
- if (constant_pool_address_operand (op, VOIDmode))
- return 0;
- else
- return romp_symbolic_operand (op, Pmode)
- || (GET_CODE (op) == PLUS && register_operand (XEXP (op, 0), Pmode)
- && romp_symbolic_operand (XEXP (op, 1), Pmode));
-}
-
-
-/* Returns 1 if OP is a constant pool reference to the current function. */
-
-int
-current_function_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
- || ! CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
- return 0;
-
- op = get_pool_constant (XEXP (op, 0));
- return (GET_CODE (op) == SYMBOL_REF
- && ! strcmp (current_function_name, XSTR (op, 0)));
-}
-
-/* Return non-zero if this function is known to have a null epilogue. */
-
-int
-null_epilogue ()
-{
- return (reload_completed
- && first_reg_to_save () == 16
- && ! romp_pushes_stack ());
-}
-
-/* Returns 1 if OP is the address of a location in the constant pool. */
-
-int
-constant_pool_address_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
- || (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (op, 0), 0))));
-}
-
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-romp_symbolic_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- return ! op->integrated;
-
- case CONST:
- op = XEXP (op, 0);
- return (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT;
-
- default:
- return 0;
- }
-}
-
-/* Returns 1 if OP is a valid constant for the ROMP. */
-
-int
-constant_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- switch (GET_CODE (op))
- {
- case LABEL_REF:
- case SYMBOL_REF:
- case PLUS:
- case CONST:
- return romp_symbolic_operand (op,mode);
-
- case CONST_INT:
- return (unsigned int) (INTVAL (op) + 0x8000) < 0x10000
- || (INTVAL (op) & 0xffff) == 0 || (INTVAL (op) & 0xffff0000) == 0;
-
- default:
- return 0;
- }
-}
-
-/* Returns 1 if OP is either a constant integer valid for the ROMP or a
- register. If a register, it must be in the proper mode unless MODE is
- VOIDmode. */
-
-int
-reg_or_cint_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == CONST_INT)
- return constant_operand (op, mode);
-
- return register_operand (op, mode);
-}
-
-/* Return 1 is the operand is either a register or ANY constant integer. */
-
-int
-reg_or_any_cint_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- return GET_CODE (op) == CONST_INT || register_operand (op, mode);
-}
-
-/* Return 1 if the operand is either a register or a valid D-type operand. */
-
-int
-reg_or_D_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == CONST_INT)
- return (unsigned) (INTVAL (op) + 0x8000) < 0x10000;
-
- return register_operand (op, mode);
-}
-
-/* Return 1 if the operand is either a register or an item that can be
- used as the operand of an SI add insn. */
-
-int
-reg_or_add_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- return reg_or_D_operand (op, mode) || romp_symbolic_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0);
-}
-
-/* Return 1 if the operand is either a register or an item that can be
- used as the operand of a ROMP logical AND insn. */
-
-int
-reg_or_and_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (reg_or_cint_operand (op, mode))
- return 1;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return (INTVAL (op) & 0xffff) == 0xffff
- || (INTVAL (op) & 0xffff0000) == 0xffff0000;
-}
-
-/* Return 1 if the operand is a register or memory operand. */
-
-int
-reg_or_mem_operand (op, mode)
- register rtx op;
- register enum machine_mode mode;
-{
- return register_operand (op, mode) || memory_operand (op, mode);
-}
-
-/* Return 1 if the operand is either a register or a memory operand that is
- not symbolic. */
-
-int
-reg_or_nonsymb_mem_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (register_operand (op, mode))
- return 1;
-
- if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
- return 1;
-
- return 0;
-}
-
-/* Return 1 if this operand is valid for the ROMP. This is any operand except
- certain constant integers. */
-
-int
-romp_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == CONST_INT)
- return constant_operand (op, mode);
-
- return general_operand (op, mode);
-}
-
-/* Return 1 if the operand is (reg:mode 0). */
-
-int
-reg_0_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && GET_CODE (op) == REG && REGNO (op) == 0);
-}
-
-/* Return 1 if the operand is (reg:mode 15). */
-
-int
-reg_15_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && GET_CODE (op) == REG && REGNO (op) == 15);
-}
-
-/* Return 1 if this is a binary floating-point operation. */
-
-int
-float_binary (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
- return 0;
-
- switch (GET_CODE (op))
- {
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- return GET_MODE (XEXP (op, 0)) == GET_MODE (op)
- && GET_MODE (XEXP (op, 1)) == GET_MODE (op);
-
- default:
- return 0;
- }
-}
-
-/* Return 1 if this is a unary floating-point operation. */
-
-int
-float_unary (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
- return 0;
-
- return (GET_CODE (op) == NEG || GET_CODE (op) == ABS)
- && GET_MODE (XEXP (op, 0)) == GET_MODE (op);
-}
-
-/* Return 1 if this is a valid floating-point conversion that can be done
- as part of an operation by the RT floating-point routines. */
-
-int
-float_conversion (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- switch (GET_CODE (op))
- {
- case FLOAT_TRUNCATE:
- return GET_MODE (op) == SFmode && GET_MODE (XEXP (op, 0)) == DFmode;
-
- case FLOAT_EXTEND:
- return GET_MODE (op) == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;
-
- case FLOAT:
- return ((GET_MODE (XEXP (op, 0)) == SImode
- || GET_CODE (XEXP (op, 0)) == CONST_INT)
- && (GET_MODE (op) == SFmode || GET_MODE (op) == DFmode));
-
- case FIX:
- return ((GET_MODE (op) == SImode
- || GET_CODE (XEXP (op, 0)) == CONST_INT)
- && (GET_MODE (XEXP (op, 0)) == SFmode
- || GET_MODE (XEXP (op, 0)) == DFmode));
-
- default:
- return 0;
- }
-}
-
-/* Print an operand. Recognize special options, documented below. */
-
-void
-print_operand (file, x, code)
- FILE *file;
- rtx x;
- char code;
-{
- int i;
-
- switch (code)
- {
- case 'B':
- /* Byte number (const/8) */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%B value");
-
- fprintf (file, "%d", INTVAL (x) / 8);
- break;
-
- case 'L':
- /* Low order 16 bits of constant. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%L value");
-
- fprintf (file, "%d", INTVAL (x) & 0xffff);
- break;
-
- case 's':
- /* Null or "16" depending on whether the constant is greater than 16. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%s value");
-
- if (INTVAL (x) >= 16)
- fprintf (file, "16");
-
- break;
-
- case 'S':
- /* For shifts: 's' will have given the half. Just give the amount
- within 16. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%S value");
-
- fprintf (file, "%d", INTVAL (x) & 15);
- break;
-
- case 'b':
- /* The number of a single bit set or cleared, mod 16. Note that the ROMP
- numbers bits with the high-order bit 31. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%b value");
-
- if ((i = exact_log2 (INTVAL (x))) >= 0)
- fprintf (file, "%d", (31 - i) % 16);
- else if ((i = exact_log2 (~ INTVAL (x))) >= 0)
- fprintf (file, "%d", (31 - i) % 16);
- else
- output_operand_lossage ("invalid %%b value");
-
- break;
-
- case 'h':
- /* "l" or "u" depending on which half of the constant is zero. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%h value");
-
- if ((INTVAL (x) & 0xffff0000) == 0)
- fprintf (file, "l");
- else if ((INTVAL (x) & 0xffff) == 0)
- fprintf (file, "u");
- else
- output_operand_lossage ("invalid %%h value");
-
- break;
-
- case 'H':
- /* Upper or lower half, depending on which half is zero. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%H value");
-
- if ((INTVAL (x) & 0xffff0000) == 0)
- fprintf (file, "%d", INTVAL (x) & 0xffff);
- else if ((INTVAL (x) & 0xffff) == 0)
- fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
- else
- output_operand_lossage ("invalid %%H value");
-
- break;
-
- case 'z':
- /* Write two characters:
- 'lo' if the high order part is all ones
- 'lz' if the high order part is all zeros
- 'uo' if the low order part is all ones
- 'uz' if the low order part is all zeros
- */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%z value");
-
- if ((INTVAL (x) & 0xffff0000) == 0)
- fprintf (file, "lz");
- else if ((INTVAL (x) & 0xffff0000) == 0xffff0000)
- fprintf (file, "lo");
- else if ((INTVAL (x) & 0xffff) == 0)
- fprintf (file, "uz");
- else if ((INTVAL (x) & 0xffff) == 0xffff)
- fprintf (file, "uo");
- else
- output_operand_lossage ("invalid %%z value");
-
- break;
-
- case 'Z':
- /* Upper or lower half, depending on which is non-zero or not
- all ones. Must be consistent with 'z' above. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%Z value");
-
- if ((INTVAL (x) & 0xffff0000) == 0
- || (INTVAL (x) & 0xffff0000) == 0xffff0000)
- fprintf (file, "%d", INTVAL (x) & 0xffff);
- else if ((INTVAL (x) & 0xffff) == 0 || (INTVAL (x) & 0xffff) == 0xffff)
- fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
- else
- output_operand_lossage ("invalid %%Z value");
-
- break;
-
- case 'k':
- /* Same as 'z', except the trailing 'o' or 'z' is not written. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%k value");
-
- if ((INTVAL (x) & 0xffff0000) == 0
- || (INTVAL (x) & 0xffff0000) == 0xffff0000)
- fprintf (file, "l");
- else if ((INTVAL (x) & 0xffff) == 0
- || (INTVAL (x) & 0xffff) == 0xffff)
- fprintf (file, "u");
- else
- output_operand_lossage ("invalid %%k value");
-
- break;
-
- case 't':
- /* Similar to 's', except that we write 'h' or 'u'. */
- if (GET_CODE (x) != CONST_INT)
- output_operand_lossage ("invalid %%k value");
-
- if (INTVAL (x) < 16)
- fprintf (file, "u");
- else
- fprintf (file, "l");
- break;
-
- case 'M':
- /* For memory operations, write 's' if the operand is a short
- memory operand. */
- if (short_memory_operand (x, VOIDmode))
- fprintf (file, "s");
- break;
-
- case 'N':
- /* Like 'M', but check for zero memory offset. */
- if (zero_memory_operand (x, VOIDmode))
- fprintf (file, "s");
- break;
-
- case 'O':
- /* Write low-order part of DImode or DFmode. Supported for MEM
- and REG only. */
- if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
- else if (GET_CODE (x) == MEM)
- print_operand (file, gen_rtx (MEM, GET_MODE (x),
- plus_constant (XEXP (x, 0), 4)), 0);
- else
- abort ();
- break;
-
- case 'C':
- /* Offset in constant pool for constant pool address. */
- if (! constant_pool_address_operand (x, VOIDmode))
- abort ();
- if (GET_CODE (x) == SYMBOL_REF)
- fprintf (file, "%d", get_pool_offset (x) + 12);
- else
- /* Must be (const (plus (symbol_ref) (const_int))) */
- fprintf (file, "%d",
- (get_pool_offset (XEXP (XEXP (x, 0), 0)) + 12
- + INTVAL (XEXP (XEXP (x, 0), 1))));
- break;
-
- case 'j':
- /* Branch opcode. Check for condition in test bit for eq/ne. */
- switch (GET_CODE (x))
- {
- case EQ:
- if (cc_status.flags & CC_IN_TB)
- fprintf (file, "ntb");
- else
- fprintf (file, "eq");
- break;
-
- case NE:
- if (cc_status.flags & CC_IN_TB)
- fprintf (file, "tb");
- else
- fprintf (file, "ne");
- break;
-
- case GT:
- case GTU:
- fprintf (file, "h");
- break;
-
- case LT:
- case LTU:
- fprintf (file, "l");
- break;
-
- case GE:
- case GEU:
- fprintf (file, "he");
- break;
-
- case LE:
- case LEU:
- fprintf (file, "le");
- break;
-
- default:
- output_operand_lossage ("invalid %%j value");
- }
- break;
-
- case 'J':
- /* Reversed branch opcode. */
- switch (GET_CODE (x))
- {
- case EQ:
- if (cc_status.flags & CC_IN_TB)
- fprintf (file, "tb");
- else
- fprintf (file, "ne");
- break;
-
- case NE:
- if (cc_status.flags & CC_IN_TB)
- fprintf (file, "ntb");
- else
- fprintf (file, "eq");
- break;
-
- case GT:
- case GTU:
- fprintf (file, "le");
- break;
-
- case LT:
- case LTU:
- fprintf (file, "he");
- break;
-
- case GE:
- case GEU:
- fprintf (file, "l");
- break;
-
- case LE:
- case LEU:
- fprintf (file, "h");
- break;
-
- default:
- output_operand_lossage ("invalid %%j value");
- }
- break;
-
- case '.':
- /* Output nothing. Used as delimiter in, e.g., "mc%B1%.3 " */
- break;
-
- case '#':
- /* Output 'x' if this insn has a delay slot, else nothing. */
- if (dbr_sequence_length ())
- fprintf (file, "x");
- break;
-
- case 0:
- if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x)]);
- else if (GET_CODE (x) == MEM)
- {
- if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
- && current_function_operand (x, Pmode))
- fprintf (file, "r14");
- else
- output_address (XEXP (x, 0));
- }
- else
- output_addr_const (file, x);
- break;
-
- default:
- output_operand_lossage ("invalid %%xn code");
- }
-}
-
-/* This page contains routines that are used to determine what the function
- prologue and epilogue code will do and write them out. */
-
-/* Return the first register that is required to be saved. 16 if none. */
-
-int
-first_reg_to_save()
-{
- int first_reg;
-
- /* Find lowest numbered live register. */
- for (first_reg = 6; first_reg <= 15; first_reg++)
- if (regs_ever_live[first_reg])
- break;
-
- /* If we think that we do not have to save r14, see if it will be used
- to be sure. */
- if (first_reg > 14 && romp_using_r14 ())
- first_reg = 14;
-
- return first_reg;
-}
-
-/* Compute the size of the save area in the stack, including the space for
- the first four incoming arguments. */
-
-int
-romp_sa_size ()
-{
- int size;
- int i;
-
- /* We have the 4 words corresponding to the arguments passed in registers,
- 4 reserved words, space for static chain, general register save area,
- and floating-point save area. */
- size = 4 + 4 + 1 + (16 - first_reg_to_save ());
-
- /* The documentation says we have to leave 18 words in the save area if
- any floating-point registers at all are saved, not the three words
- per register you might otherwise expect. */
- for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
- if (regs_ever_live[i + 17])
- {
- size += 18;
- break;
- }
-
- return size * 4;
-}
-
-/* Return non-zero if this function makes calls or has fp operations
- (which are really calls). */
-
-int
-romp_makes_calls ()
-{
- rtx insn;
-
- for (insn = get_insns (); insn; insn = next_insn (insn))
- {
- if (GET_CODE (insn) == CALL_INSN)
- return 1;
- else if (GET_CODE (insn) == INSN)
- {
- rtx body = PATTERN (insn);
-
- if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER
- && GET_CODE (body) != ADDR_VEC
- && GET_CODE (body) != ADDR_DIFF_VEC
- && get_attr_type (insn) == TYPE_FP)
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Return non-zero if this function will use r14 as a pointer to its
- constant pool. */
-
-int
-romp_using_r14 ()
-{
- /* If we are debugging, profiling, have a non-empty constant pool, or
- call a function, we need r14. */
- return (write_symbols != NO_DEBUG || profile_flag || get_pool_size () != 0
- || romp_makes_calls ());
-}
-
-/* Return non-zero if this function needs to push space on the stack. */
-
-int
-romp_pushes_stack ()
-{
- /* We need to push the stack if a frame pointer is needed (because the
- stack might be dynamically adjusted), if we are debugging, if the
- total required size is more than 100 bytes, or if we make calls. */
-
- return (frame_pointer_needed || write_symbols != NO_DEBUG
- || (romp_sa_size () + get_frame_size ()) > 100
- || romp_makes_calls ());
-}
-
-/* Write function prologue.
-
- We compute the size of the fixed area required as follows:
-
- We always allocate 4 words for incoming arguments, 4 word reserved, 1
- word for static link, as many words as required for general register
- save area, plus 2 words for each FP reg 2-7 that must be saved. */
-
-void
-output_prolog (file, size)
- FILE *file;
- int size;
-{
- int first_reg;
- int reg_save_offset;
- int fp_save = size + current_function_outgoing_args_size;
-
- init_fpops ();
-
- /* Add in fixed size plus output argument area. */
- size += romp_sa_size () + current_function_outgoing_args_size;
-
- /* Compute first register to save and perform the save operation if anything
- needs to be saved. */
- first_reg = first_reg_to_save();
- reg_save_offset = - (4 + 4 + 1 + (16 - first_reg)) * 4;
- if (first_reg == 15)
- fprintf (file, "\tst r15,%d(r1)\n", reg_save_offset);
- else if (first_reg < 16)
- fprintf (file, "\tstm r%d,%d(r1)\n", first_reg, reg_save_offset);
-
- /* Set up pointer to data area if it is needed. */
- if (romp_using_r14 ())
- fprintf (file, "\tcas r14,r0,r0\n");
-
- /* Set up frame pointer if needed. */
- if (frame_pointer_needed)
- fprintf (file, "\tcal r13,-%d(r1)\n", romp_sa_size () + 64);
-
- /* Push stack if neeeded. There are a couple of ways of doing this. */
- if (romp_pushes_stack ())
- {
- if (size >= 32768)
- {
- if (size >= 65536)
- {
- fprintf (file, "\tcau r0,%d(r0)\n", size >> 16);
- fprintf (file, "\toil r0,r0,%d\n", size & 0xffff);
- }
- else
- fprintf (file, "\tcal16 r0,%d(r0)\n", size);
- fprintf (file, "\ts r1,r0\n");
- }
- else
- fprintf (file, "\tcal r1,-%d(r1)\n", size);
- }
-
- /* Save floating-point registers. */
- output_loadsave_fpregs (file, USE,
- plus_constant (stack_pointer_rtx, fp_save));
-}
-
-/* Output the offset information used by debuggers.
- This is the exactly the total_size value of output_epilog
- which is added to the frame pointer. However the value in the debug
- table is encoded in a space-saving way as follows:
-
- The first byte contains two fields: a 2-bit size field and the first
- 6 bits of an offset value. The 2-bit size field is in the high-order
- position and specifies how many subsequent bytes follow after
- this one. An offset value is at most 4-bytes long.
-
- The last 6 bits of the first byte initialize the offset value. In many
- cases where procedures have small local storage, this is enough and, in
- this case, the high-order size field is zero so the byte can (almost) be
- used as is (see below). Thus, the byte value of 0x0d is encodes a offset
- size of 13 words, or 52 bytes.
-
- For procedures with a local space larger than 60 bytes, the 6 bits
- are the high-order 6 bits. The remaining bytes follow as necessary,
- in Big Endian order. Thus, the short value of 16907 (= 16384+523)
- encodes an offset of 2092 bytes (523 words).
-
- The total offset value is in words (not bytes), so the final value has to
- be multiplied by 4 before it can be used in address computations by a
- debugger. */
-
-void
-output_encoded_offset (file, reg_offset)
- FILE *file;
- unsigned reg_offset;
-{
- /* Convert the offset value to 4-byte words rather than bytes. */
- reg_offset = (reg_offset + 3) / 4;
-
- /* Now output 1-4 bytes in encoded form. */
- if (reg_offset < (1 << 6))
- /* Fits into one byte */
- fprintf (file, "\t.byte %d\n", reg_offset);
- else if (reg_offset < (1 << (6 + 8)))
- /* Fits into two bytes */
- fprintf (file, "\t.short %d\n", (1 << (6 + 8)) + reg_offset);
- else if (reg_offset < (1 << (6 + 8 + 8)))
- {
- /* Fits in three bytes */
- fprintf (file, "\t.byte %d\n", (2 << 6) + (reg_offset >> ( 6+ 8)));
- fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
- }
- else
- {
- /* Use 4 bytes. */
- fprintf (file, "\t.short %d", (3 << (6 + 8)) + (reg_offset >> (6 + 8)));
- fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
- }
-}
-
-/* Write function epilogue. */
-
-void
-output_epilog (file, size)
- FILE *file;
- int size;
-{
- int first_reg = first_reg_to_save();
- int pushes_stack = romp_pushes_stack ();
- int reg_save_offset = - ((16 - first_reg) + 1 + 4 + 4) * 4;
- int total_size = (size + romp_sa_size ()
- + current_function_outgoing_args_size);
- int fp_save = size + current_function_outgoing_args_size;
- int long_frame = total_size >= 32768;
- rtx insn = get_last_insn ();
- int write_code = 1;
-
- int nargs = 0; /* words of arguments */
- tree argptr;
-
- /* Compute the number of words of arguments. Since this is just for
- the traceback table, we ignore arguments that don't have a size or
- don't have a fixed size. */
-
- for (argptr = DECL_ARGUMENTS (current_function_decl);
- argptr; argptr = TREE_CHAIN (argptr))
- {
- int this_size = int_size_in_bytes (TREE_TYPE (argptr));
-
- if (this_size > 0)
- nargs += (this_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- }
-
- /* If the last insn was a BARRIER, we don't have to write anything except
- the trace table. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- write_code = 0;
-
- /* Restore floating-point registers. */
- if (write_code)
- output_loadsave_fpregs (file, CLOBBER,
- gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, 1),
- GEN_INT (fp_save)));
-
- /* If we push the stack and do not have size > 32K, adjust the register
- save location to the current position of sp. Otherwise, if long frame,
- restore sp from fp. */
- if (pushes_stack && ! long_frame)
- reg_save_offset += total_size;
- else if (long_frame && write_code)
- fprintf (file, "\tcal r1,%d(r13)\n", romp_sa_size () + 64);
-
- /* Restore registers. */
- if (first_reg == 15 && write_code)
- fprintf (file, "\tl r15,%d(r1)\n", reg_save_offset);
- else if (first_reg < 16 && write_code)
- fprintf (file, "\tlm r%d,%d(r1)\n", first_reg, reg_save_offset);
- if (first_reg == 16) first_reg = 0;
-
- /* Handle popping stack, if needed and write debug table entry. */
- if (pushes_stack)
- {
- if (write_code)
- {
- if (long_frame)
- fprintf (file, "\tbr r15\n");
- else
- fprintf (file, "\tbrx r15\n\tcal r1,%d(r1)\n", total_size);
- }
-
- /* Table header (0xdf), usual-type stack frame (0x07),
- table header (0xdf), and first register saved.
-
- The final 0x08 means that there is a byte following this one
- describing the number of parameter words and the register used as
- stack pointer.
-
- If GCC passed floating-point parameters in floating-point registers,
- it would be necessary to change the final byte from 0x08 to 0x0c.
- Also an additional entry byte would be need to be emitted to specify
- the first floating-point register.
-
- (See also Section 11 (Trace Tables) in ``IBM/4.3 Linkage Convention,''
- pages IBM/4.3-PSD:5-7 of Volume III of the IBM Academic Operating
- System Manual dated July 1987.) */
-
- fprintf (file, "\t.long 0x%x\n", 0xdf07df08 + first_reg * 0x10);
-
- if (nargs > 15) nargs = 15;
-
- /* The number of parameter words and the register used as the stack
- pointer (encoded here as r1).
-
- Note: The MetWare Hich C Compiler R2.1y actually gets this wrong;
- it erroneously lists r13 but uses r1 as the stack too. But a bug in
- dbx 1.5 nullifies this mistake---most of the time.
- (Dbx retrieves the value of r13 saved on the stack which is often
- the value of r1 before the call.) */
-
- fprintf (file, "\t.byte 0x%x1\n", nargs);
- output_encoded_offset (file, total_size);
- }
- else
- {
- if (write_code)
- fprintf (file, "\tbr r15\n");
-
- /* Table header (0xdf), no stack frame (0x02),
- table header (0xdf) and no parameters saved (0x00).
-
- If GCC passed floating-point parameters in floating-point registers,
- it might be necessary to change the final byte from 0x00 to 0x04.
- Also a byte would be needed to specify the first floating-point
- register. */
- fprintf (file, "\t.long 0xdf02df00\n");
- }
-
- /* Output any pending floating-point operations. */
- output_fpops (file);
-}
-
-/* For the ROMP we need to make new SYMBOL_REFs for the actual name of a
- called routine. To keep them unique we maintain a hash table of all
- that have been created so far. */
-
-struct symref_hashent {
- rtx symref; /* Created SYMBOL_REF rtx. */
- struct symref_hashent *next; /* Next with same hash code. */
-};
-
-#define SYMHASHSIZE 151
-#define HASHBITS 65535
-
-/* Define the hash table itself. */
-
-static struct symref_hashent *symref_hash_table[SYMHASHSIZE];
-
-/* Given a name (allocable in temporary storage), return a SYMBOL_REF
- for the name. The rtx is allocated from the current rtl_obstack, while
- the name string is allocated from the permanent obstack. */
-rtx
-get_symref (name)
- register char *name;
-{
- extern struct obstack permanent_obstack;
- register char *sp = name;
- unsigned int hash = 0;
- struct symref_hashent *p, **last_p;
-
- /* Compute the hash code for the string. */
- while (*sp)
- hash = (hash << 4) + *sp++;
-
- /* Search for a matching entry in the hash table, keeping track of the
- insertion location as we do so. */
- hash = (hash & HASHBITS) % SYMHASHSIZE;
- for (last_p = &symref_hash_table[hash], p = *last_p;
- p; last_p = &p->next, p = *last_p)
- if (strcmp (name, XSTR (p->symref, 0)) == 0)
- break;
-
- /* If couldn't find matching SYMBOL_REF, make a new one. */
- if (p == 0)
- {
- /* Ensure SYMBOL_REF will stay around. */
- end_temporary_allocation ();
- p = *last_p = (struct symref_hashent *)
- permalloc (sizeof (struct symref_hashent));
- p->symref = gen_rtx (SYMBOL_REF, Pmode,
- obstack_copy0 (&permanent_obstack,
- name, strlen (name)));
- p->next = 0;
- resume_temporary_allocation ();
- }
-
- return p->symref;
-}
-
-/* Validate the precision of a floating-point operation.
-
- We merge conversions from integers and between floating-point modes into
- the insn. However, this must not effect the desired precision of the
- insn. The RT floating-point system uses the widest of the operand modes.
- If this should be a double-precision insn, ensure that one operand
- passed to the floating-point processor has double mode.
-
- Note that since we don't check anything if the mode is single precision,
- it, strictly speaking, isn't necessary to call this for those insns.
- However, we do so in case something else needs to be checked in the
- future.
-
- This routine returns 1 if the operation is OK. */
-
-int
-check_precision (opmode, op1, op2)
- enum machine_mode opmode;
- rtx op1, op2;
-{
- if (opmode == SFmode)
- return 1;
-
- /* If operand is not a conversion from an integer mode or an extension from
- single-precision, it must be a double-precision value. */
- if (GET_CODE (op1) != FLOAT && GET_CODE (op1) != FLOAT_EXTEND)
- return 1;
-
- if (op2 && GET_CODE (op2) != FLOAT && GET_CODE (op2) != FLOAT_EXTEND)
- return 1;
-
- return 0;
-}
-
-/* Floating-point on the RT is done by creating an operation block in the data
- area that describes the operation. If two floating-point operations are the
- same in a single function, they can use the same block.
-
- These routines are responsible for managing these blocks. */
-
-/* Structure to describe a floating-point operation. */
-
-struct fp_op {
- struct fp_op *next_same_hash; /* Next op with same hash code. */
- struct fp_op *next_in_mem; /* Next op in memory. */
- int mem_offset; /* Offset from data area. */
- short size; /* Size of block in bytes. */
- short noperands; /* Number of operands in block. */
- rtx ops[3]; /* RTL for operands. */
- enum rtx_code opcode; /* Operation being performed. */
-};
-
-/* Size of hash table. */
-#define FP_HASH_SIZE 101
-
-/* Hash table of floating-point operation blocks. */
-static struct fp_op *fp_hash_table[FP_HASH_SIZE];
-
-/* First floating-point block in data area. */
-static struct fp_op *first_fpop;
-
-/* Last block in data area so far. */
-static struct fp_op *last_fpop_in_mem;
-
-/* Subroutine number in file, to get unique "LF" labels. */
-static int subr_number = 0;
-
-/* Current word offset in data area (includes header and any constant pool). */
-int data_offset;
-
-/* Compute hash code for an RTX used in floating-point. */
-
-static unsigned int
-hash_rtx (x)
- register rtx x;
-{
- register unsigned int hash = (((int) GET_CODE (x) << 10)
- + ((int) GET_MODE (x) << 20));
- register int i;
- register char *fmt = GET_RTX_FORMAT (GET_CODE (x));
-
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
- if (fmt[i] == 'e')
- hash += hash_rtx (XEXP (x, i));
- else if (fmt[i] == 'u')
- hash += (unsigned HOST_WIDE_INT) XEXP (x, i);
- else if (fmt[i] == 'i')
- hash += XINT (x, i);
- else if (fmt[i] == 's')
- hash += (unsigned HOST_WIDE_INT) XSTR (x, i);
-
- return hash;
-}
-
-/* Given an operation code and up to three operands, return a character string
- corresponding to the code to emit to branch to a floating-point operation
- block. INSN is provided to see if the delay slot has been filled or not.
-
- A new floating-point operation block is created if this operation has not
- been seen before. */
-
-char *
-output_fpop (code, op0, op1, op2, insn)
- enum rtx_code code;
- rtx op0, op1, op2;
- rtx insn;
-{
- static char outbuf[40];
- unsigned int hash, hash0, hash1, hash2;
- int size, i;
- register struct fp_op *fpop, *last_fpop;
- int dyadic = (op2 != 0);
- enum machine_mode opmode;
- int noperands;
- rtx tem;
- unsigned int tem_hash;
- int fr0_avail = 0;
-
- /* Compute hash code for each operand. If the operation is commutative,
- put the one with the smaller hash code first. This will make us see
- more operations as identical. */
- hash0 = op0 ? hash_rtx (op0) : 0;
- hash1 = op1 ? hash_rtx (op1) : 0;
- hash2 = op2 ? hash_rtx (op2) : 0;
-
- if (hash0 > hash1 && code == EQ)
- {
- tem = op0; op0 = op1; op1 = tem;
- tem_hash = hash0; hash0 = hash1; hash1 = tem_hash;
- }
- else if (hash1 > hash2 && (code == PLUS || code == MULT))
- {
- tem = op1; op1 = op2; op2 = tem;
- tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
- }
-
- /* If operation is commutative and the first and third operands are equal,
- swap the second and third operands. Note that we must consider two
- operands equal if they are the same register even if different modes. */
- if (op2 && (code == PLUS || code == MULT)
- && (rtx_equal_p (op0, op2)
- || (GET_CODE (op0) == REG && GET_CODE (op2) == REG
- && REGNO (op0) == REGNO (op2))))
- {
- tem = op1; op1 = op2; op2 = tem;
- tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
- }
-
- /* If the first and second operands are the same, merge them. Don't do this
- for SFmode or SImode in general registers because this triggers a bug in
- the RT fp code. */
- if (op1 && rtx_equal_p (op0, op1)
- && code != EQ && code != GE && code != SET
- && ((GET_MODE (op1) != SFmode && GET_MODE (op1) != SImode)
- || GET_CODE (op0) != REG || FP_REGNO_P (REGNO (op0))))
- {
- op1 = op2;
- op2 = 0;
- }
-
- noperands = 1 + (op1 != 0) + (op2 != 0);
-
- /* Compute hash code for entire expression and see if operation block
- already exists. */
- hash = ((int) code << 13) + (hash0 << 2) + (hash1 << 1) + hash2;
-
- hash %= FP_HASH_SIZE;
- for (fpop = fp_hash_table[hash], last_fpop = 0;
- fpop;
- last_fpop = fpop, fpop = fpop->next_same_hash)
- if (fpop->opcode == code && noperands == fpop->noperands
- && (op0 == 0 || rtx_equal_p (op0, fpop->ops[0]))
- && (op1 == 0 || rtx_equal_p (op1, fpop->ops[1]))
- && (op2 == 0 || rtx_equal_p (op2, fpop->ops[2])))
- goto win;
-
- /* We have never seen this operation before. */
- fpop = (struct fp_op *) oballoc (sizeof (struct fp_op));
- fpop->mem_offset = data_offset;
- fpop->opcode = code;
- fpop->noperands = noperands;
- fpop->ops[0] = op0;
- fpop->ops[1] = op1;
- fpop->ops[2] = op2;
-
- /* Compute the size using the rules in Appendix A of the RT Linkage
- Convention (4.3/RT-PSD:5) manual. These rules are a bit ambiguous,
- but if we guess wrong, it will effect only efficiency, not correctness. */
-
- /* Size = 24 + 32 for each non-fp (or fr7) */
- size = 24;
- if (op0 && (GET_CODE (op0) != REG
- || ! FP_REGNO_P (REGNO (op0)) || REGNO (op0) == 23))
- size += 32;
-
- if (op1 && (GET_CODE (op1) != REG
- || ! FP_REGNO_P (REGNO (op1)) || REGNO (op1) == 23))
- size += 32;
-
- if (op2 && (GET_CODE (op2) != REG
- || ! FP_REGNO_P (REGNO (op2)) || REGNO (op2) == 23))
- size += 32;
-
- /* Size + 12 for each conversion. First get operation mode. */
- if ((op0 && GET_MODE (op0) == DFmode)
- || (op1 && GET_MODE (op1) == DFmode)
- || (op2 && GET_MODE (op2) == DFmode))
- opmode = DFmode;
- else
- opmode = SFmode;
-
- if (op0 && GET_MODE (op0) != opmode)
- size += 12;
- if (op1 && GET_MODE (op1) != opmode)
- size += 12;
- if (op2 && GET_MODE (op2) != opmode)
- size += 12;
-
- /* 12 more if first and third operand types not the same. */
- if (op2 && GET_MODE (op0) != GET_MODE (op2))
- size += 12;
-
- /* CMP and CMPT need additional. Also, compute size of save/restore here. */
- if (code == EQ)
- size += 32;
- else if (code == GE)
- size += 64;
- else if (code == USE || code == CLOBBER)
- {
- /* 34 + 24 for each additional register plus 8 if fr7 saved. (We
- call it 36 because we need to keep the block length a multiple
- of four. */
- size = 36 - 24;
- for (i = 0; i <= 7; i++)
- if (INTVAL (op0) & (1 << (7-i)))
- size += 24 + 8 * (i == 7);
- }
-
- /* We provide no general-purpose scratch registers. */
- size +=16;
-
- /* No floating-point scratch registers are provided. Compute extra
- length due to this. This logic is that shown in the referenced
- appendix. */
-
- i = 0;
- if (op0 && GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
- i++;
- if (op1 && GET_CODE (op1) == REG && FP_REGNO_P (REGNO (op1)))
- i++;
- if (op2 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
- i++;
-
- if ((op0 == 0 || GET_CODE (op0) != REG || REGNO(op0) != 17)
- && (op1 == 0 || GET_CODE (op1) != REG || REGNO(op1) != 17)
- && (op2 == 0 || GET_CODE (op2) != REG || REGNO(op2) != 17))
- fr0_avail = 1;
-
- if (dyadic)
- {
- if (i == 0)
- size += fr0_avail ? 64 : 112;
- else if (fpop->noperands == 2 && i == 1)
- size += fr0_avail ? 0 : 64;
- else if (fpop->noperands == 3)
- {
- if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0))
- && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
- {
- if (REGNO (op0) == REGNO (op2))
-#if 1
- /* This triggers a bug on the RT. */
- abort ();
-#else
- size += fr0_avail ? 0 : 64;
-#endif
- }
- else
- {
- i = 0;
- if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
- i++;
- if (GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
- i++;
- if (i == 0)
- size += fr0_avail ? 64 : 112;
- else if (i == 1)
- size += fr0_avail ? 0 : 64;
- }
- }
- }
- else if (code != USE && code != CLOBBER
- && (GET_CODE (op0) != REG || ! FP_REGNO_P (REGNO (op0))))
- size += 64;
-
- if (! TARGET_FULL_FP_BLOCKS)
- {
- /* If we are not to pad the blocks, just compute its actual length. */
- size = 12; /* Header + opcode */
- if (code == USE || code == CLOBBER)
- size += 2;
- else
- {
- if (op0) size += 2;
- if (op1) size += 2;
- if (op2) size += 2;
- }
-
- /* If in the middle of a word, round. */
- if (size % UNITS_PER_WORD)
- size += 2;
-
- /* Handle any immediates. */
- if (code != USE && code != CLOBBER && op0 && GET_CODE (op0) != REG)
- size += 4;
- if (op1 && GET_CODE (op1) != REG)
- size += 4;
- if (op2 && GET_CODE (op2) != REG)
- size += 4;
-
- if (code != USE && code != CLOBBER &&
- op0 && GET_CODE (op0) == CONST_DOUBLE && GET_MODE (op0) == DFmode)
- size += 4;
- if (op1 && GET_CODE (op1) == CONST_DOUBLE && GET_MODE (op1) == DFmode)
- size += 4;
- if (op2 && GET_CODE (op2) == CONST_DOUBLE && GET_MODE (op2) == DFmode)
- size += 4;
- }
-
- /* Done with size computation! Chain this in. */
- fpop->size = size;
- data_offset += size / UNITS_PER_WORD;
- fpop->next_in_mem = 0;
- fpop->next_same_hash = 0;
-
- if (last_fpop_in_mem)
- last_fpop_in_mem->next_in_mem = fpop;
- else
- first_fpop = fpop;
- last_fpop_in_mem = fpop;
-
- if (last_fpop)
- last_fpop->next_same_hash = fpop;
- else
- fp_hash_table[hash] = fpop;
-
-win:
- /* FPOP describes the operation to be performed. Return a string to branch
- to it. */
- if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
- sprintf (outbuf, "cal r15,%d(r14)\n\tbalr%s r15,r15",
- fpop->mem_offset * UNITS_PER_WORD,
- dbr_sequence_length () ? "x" : "");
- else
- sprintf (outbuf, "get r15,$L%dF%d\n\tbalr%s r15,r15",
- subr_number, fpop->mem_offset * UNITS_PER_WORD,
- dbr_sequence_length () ? "x" : "");
- return outbuf;
-}
-
-/* If necessary, output a floating-point operation to save or restore all
- floating-point registers.
-
- file is the file to write the operation to, CODE is USE for save, CLOBBER
- for restore, and ADDR is the address of the same area, as RTL. */
-
-static void
-output_loadsave_fpregs (file, code, addr)
- FILE *file;
- enum rtx_code code;
- rtx addr;
-{
- register int i;
- register int mask = 0;
-
- for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
- if (regs_ever_live[i + 17])
- mask |= 1 << (7 - i);
-
- if (mask)
- fprintf (file, "\t%s\n",
- output_fpop (code, GEN_INT (mask),
- gen_rtx (MEM, Pmode, addr),
- 0, const0_rtx));
-
-}
-
-/* Output any floating-point operations at the end of the routine. */
-
-static void
-output_fpops (file)
- FILE *file;
-{
- register struct fp_op *fpop;
- register int size_so_far;
- register int i;
- rtx immed[3];
-
- if (first_fpop == 0)
- return;
-
- data_section ();
-
- ASM_OUTPUT_ALIGN (file, 2);
-
- for (fpop = first_fpop; fpop; fpop = fpop->next_in_mem)
- {
- if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
- fprintf (file, "# data area offset = %d\n",
- fpop->mem_offset * UNITS_PER_WORD);
- else
- fprintf (file, "L%dF%d:\n",
- subr_number, fpop->mem_offset * UNITS_PER_WORD);
-
- fprintf (file, "\tcas r0,r15,r0\n");
- fprintf (file, "\t.long FPGLUE\n");
- switch (fpop->opcode)
- {
- case USE:
- fprintf (file, "\t.byte 0x1d\t# STOREM\n");
- break;
- case CLOBBER:
- fprintf (file, "\t.byte 0x0f\t# LOADM\n");
- break;
- case ABS:
- fprintf (file, "\t.byte 0x00\t# ABS\n");
- break;
- case PLUS:
- fprintf (file, "\t.byte 0x02\t# ADD\n");
- break;
- case EQ:
- fprintf (file, "\t.byte 0x07\t# CMP\n");
- break;
- case GE:
- fprintf (file, "\t.byte 0x08\t# CMPT\n");
- break;
- case DIV:
- fprintf (file, "\t.byte 0x0c\t# DIV\n");
- break;
- case SET:
- fprintf (file, "\t.byte 0x14\t# MOVE\n");
- break;
- case MULT:
- fprintf (file, "\t.byte 0x15\t# MUL\n");
- break;
- case NEG:
- fprintf (file, "\t.byte 0x16\t# NEG\n");
- break;
- case SQRT:
- fprintf (file, "\t.byte 0x1c\t# SQRT\n");
- break;
- case MINUS:
- fprintf (file, "\t.byte 0x1e\t# SUB\n");
- break;
- default:
- abort ();
- }
-
- fprintf (file, "\t.byte %d\n", fpop->noperands);
- fprintf (file, "\t.short 0x8001\n");
-
- if ((fpop->ops[0] == 0
- || GET_CODE (fpop->ops[0]) != REG || REGNO(fpop->ops[0]) != 17)
- && (fpop->ops[1] == 0 || GET_CODE (fpop->ops[1]) != REG
- || REGNO(fpop->ops[1]) != 17)
- && (fpop->ops[2] == 0 || GET_CODE (fpop->ops[2]) != REG
- || REGNO(fpop->ops[2]) != 17))
- fprintf (file, "\t.byte %d, 0x80\n", fpop->size);
- else
- fprintf (file, "\t.byte %d, 0\n", fpop->size);
- size_so_far = 12;
- for (i = 0; i < fpop->noperands; i++)
- {
- register int type;
- register int opbyte;
- register char *desc0;
- char desc1[50];
-
- immed[i] = 0;
- switch (GET_MODE (fpop->ops[i]))
- {
- case SImode:
- case VOIDmode:
- desc0 = "int";
- type = 0;
- break;
- case SFmode:
- desc0 = "float";
- type = 2;
- break;
- case DFmode:
- desc0 = "double";
- type = 3;
- break;
- default:
- abort ();
- }
-
- switch (GET_CODE (fpop->ops[i]))
- {
- case REG:
- strcpy(desc1, reg_names[REGNO (fpop->ops[i])]);
- if (FP_REGNO_P (REGNO (fpop->ops[i])))
- {
- type += 0x10;
- opbyte = REGNO (fpop->ops[i]) - 17;
- }
- else
- {
- type += 0x00;
- opbyte = REGNO (fpop->ops[i]);
- if (type == 3)
- opbyte = (opbyte << 4) + opbyte + 1;
- }
- break;
-
- case MEM:
- type += 0x30;
- if (GET_CODE (XEXP (fpop->ops[i], 0)) == PLUS)
- {
- immed[i] = XEXP (XEXP (fpop->ops[i], 0), 1);
- opbyte = REGNO (XEXP (XEXP (fpop->ops[i], 0), 0));
- if (GET_CODE (immed[i]) == CONST_INT)
- sprintf (desc1, "%d(%s)", INTVAL (immed[i]),
- reg_names[opbyte]);
- else
- sprintf (desc1, "<memory> (%s)", reg_names[opbyte]);
- }
- else if (GET_CODE (XEXP (fpop->ops[i], 0)) == REG)
- {
- opbyte = REGNO (XEXP (fpop->ops[i], 0));
- immed[i] = const0_rtx;
- sprintf (desc1, "(%s)", reg_names[opbyte]);
- }
- else
- {
- immed[i] = XEXP (fpop->ops[i], 0);
- opbyte = 0;
- sprintf(desc1, "<memory>");
- }
- break;
-
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- type += 0x20;
- opbyte = 0;
- immed[i] = fpop->ops[i];
- desc1[0] = '$';
- desc1[1] = '\0';
- break;
-
- default:
- abort ();
- }
-
- /* Save/restore is special. */
- if (i == 0 && (fpop->opcode == USE || fpop->opcode == CLOBBER))
- type = 0xff, opbyte = INTVAL (fpop->ops[0]), immed[i] = 0;
-
- fprintf (file, "\t.byte 0x%x,0x%x # (%s) %s\n",
- type, opbyte, desc0, desc1);
-
- size_so_far += 2;
- }
-
- /* If in the middle of a word, round. */
- if (size_so_far % UNITS_PER_WORD)
- {
- fprintf (file, "\t.space 2\n");
- size_so_far += 2;
- }
-
- for (i = 0; i < fpop->noperands; i++)
- if (immed[i])
- switch (GET_MODE (immed[i]))
- {
- case SImode:
- case VOIDmode:
- size_so_far += 4;
- fprintf (file, "\t.long ");
- output_addr_const (file, immed[i]);
- fprintf (file, "\n");
- break;
-
- case DFmode:
- size_so_far += 4;
- case SFmode:
- size_so_far += 4;
- if (GET_CODE (immed[i]) == CONST_DOUBLE)
- {
- union real_extract u;
-
- bcopy ((char *) &CONST_DOUBLE_LOW (immed[i]),
- (char *) &u, sizeof u);
- if (GET_MODE (immed[i]) == DFmode)
- ASM_OUTPUT_DOUBLE (file, u.d);
- else
- ASM_OUTPUT_FLOAT (file, u.d);
- }
- else
- abort ();
- break;
-
- default:
- abort ();
- }
-
- if (size_so_far != fpop->size)
- {
- if (TARGET_FULL_FP_BLOCKS)
- fprintf (file, "\t.space %d\n", fpop->size - size_so_far);
- else
- abort ();
- }
- }
-
- /* Update for next subroutine. */
- subr_number++;
- text_section ();
-}
-
- /* Initialize floating-point operation table. */
-
-static void
-init_fpops()
-{
- register int i;
-
- first_fpop = last_fpop_in_mem = 0;
- for (i = 0; i < FP_HASH_SIZE; i++)
- fp_hash_table[i] = 0;
-}
-
-/* Return the offset value of an automatic variable (N_LSYM) having
- the given offset. Basically, we correct by going from a frame pointer to
- stack pointer value.
-*/
-
-int
-romp_debugger_auto_correction(offset)
- int offset;
-{
- int fp_to_sp;
-
- /* We really want to go from STACK_POINTER_REGNUM to
- FRAME_POINTER_REGNUM, but this isn't defined. So go the other
- direction and negate. */
- INITIAL_ELIMINATION_OFFSET (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM,
- fp_to_sp);
-
- /* The offset value points somewhere between the frame pointer and
- the stack pointer. What is up from the frame pointer is down from the
- stack pointer. Therefore the negation in the offset value too. */
-
- return -(offset+fp_to_sp+4);
-}
-
-/* Return the offset value of an argument having
- the given offset. Basically, we correct by going from a arg pointer to
- stack pointer value. */
-
-int
-romp_debugger_arg_correction (offset)
- int offset;
-{
- int fp_to_argp;
-
- INITIAL_ELIMINATION_OFFSET (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM,
- fp_to_argp);
-
- /* Actually, something different happens if offset is from a floating-point
- register argument, but we don't handle it here. */
-
- return (offset - fp_to_argp);
-}
diff --git a/gcc/config/romp/romp.h b/gcc/config/romp/romp.h
deleted file mode 100755
index 82a0186..0000000
--- a/gcc/config/romp/romp.h
+++ /dev/null
@@ -1,1636 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ROMP chip.
- Copyright (C) 1989, 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
- Contributed by Richard Kenner (kenner@nyu.edu)
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Names to predefine in the preprocessor for this target machine. */
-
-#define CPP_PREDEFINES "-Dibm032 -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(ibm032) -Amachine(ibm032)"
-
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION ;
-
-/* Add -lfp_p when running with -p or -pg. */
-#define LIB_SPEC "%{pg:-lfp_p}%{p:-lfp_p} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
-
-/* Run-time compilation parameters selecting different hardware subsets. */
-
-/* Flag to generate all multiplies as an in-line sequence of multiply-step
- insns instead of calling a library routine. */
-#define TARGET_IN_LINE_MUL (target_flags & 1)
-
-/* Flag to generate padded floating-point data blocks. Otherwise, we generate
- them the minimum size. This trades off execution speed against size. */
-#define TARGET_FULL_FP_BLOCKS (target_flags & 2)
-
-/* Flag to pass and return floating point values in floating point registers.
- Since this violates the linkage convention, we feel free to destroy fr2
- and fr3 on function calls.
- fr1-fr3 are used to pass the arguments. */
-#define TARGET_FP_REGS (target_flags & 4)
-
-/* Flag to return structures of more than one word in memory. This is for
- compatibility with the MetaWare HighC (hc) compiler. */
-#define TARGET_HC_STRUCT_RETURN (target_flags & 010)
-
-extern int target_flags;
-
-/* Macro to define tables used to set the flags.
- This is a list in braces of pairs in braces,
- each pair being { "NAME", VALUE }
- where VALUE is the bits to set or minus the bits to clear.
- An empty string NAME is used to identify the default VALUE. */
-
-#define TARGET_SWITCHES \
- { {"in-line-mul", 1}, \
- {"call-lib-mul", -1}, \
- {"full-fp-blocks", 2}, \
- {"minimum-fp-blocks", -2}, \
- {"fp-arg-in-fpregs", 4}, \
- {"fp-arg-in-gregs", -4}, \
- {"hc-struct-return", 010}, \
- {"nohc-struct-return", - 010}, \
- { "", TARGET_DEFAULT}}
-
-#define TARGET_DEFAULT 3
-
-/* target machine storage layout */
-
-/* Define this if most significant bit is lowest numbered
- in instructions that operate on numbered bit-fields. */
-/* That is true on ROMP. */
-#define BITS_BIG_ENDIAN 1
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-/* That is true on ROMP. */
-#define BYTES_BIG_ENDIAN 1
-
-/* Define this if most significant word of a multiword number is lowest
- numbered.
-
- For ROMP we can decide arbitrarily since there are no machine instructions
- for them. Might as well be consistent with bits and bytes. */
-#define WORDS_BIG_ENDIAN 1
-
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
- Note that this is not necessarily the width of data type `int';
- if using 16-bit ints on a 68000, this would still be 32.
- But on a machine with 16-bit registers, this would be 16. */
-#define BITS_PER_WORD 32
-
-/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD 4
-
-/* Width in bits of a pointer.
- See also the macro `Pmode' defined below. */
-#define POINTER_SIZE 32
-
-/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-#define PARM_BOUNDARY 32
-
-/* 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
-
-/* No data type wants to be aligned rounder than this. */
-#define BIGGEST_ALIGNMENT 32
-
-/* 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
-
-/* A bitfield declared as `int' forces `int' alignment for the struct. */
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-/* Make arrays of chars word-aligned for the same reasons. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE \
- && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-/* Set this nonzero if move instructions will actually fail to work
- when given unaligned data. */
-#define STRICT_ALIGNMENT 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.
-
- ROMP has 16 fullword registers and 8 floating point registers.
-
- In addition, the difference between the frame and argument pointers is
- a function of the number of registers saved, so we need to have a register
- to use for AP that will later be eliminated in favor of sp or fp. This is
- a normal register, but it is fixed. */
-
-#define FIRST_PSEUDO_REGISTER 25
-
-/* 1 for registers that have pervasive standard uses
- and are not available for the register allocator.
-
- On ROMP, r1 is used for the stack and r14 is used for a
- data area pointer.
-
- HACK WARNING: On the RT, there is a bug in code generation for
- the MC68881 when the first and third operands are the same floating-point
- register. See the definition of the FINAL_PRESCAN_INSN macro for details.
- Here we need to reserve fr0 for this purpose. */
-#define FIXED_REGISTERS \
- {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, \
- 1, 0, 0, 0, 0, 0, 0, 0}
-
-/* 1 for registers not available across function calls.
- These must include the FIXED_REGISTERS and also any
- registers that can be used without being saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like. */
-#define CALL_USED_REGISTERS \
- {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, \
- 1, 1, 0, 0, 0, 0, 0, 0}
-
-/* List the order in which to allocate registers. Each register must be
- listed once, even those in FIXED_REGISTERS.
-
- We allocate in the following order:
- fr0, fr1 (not saved)
- fr2 ... fr6
- fr7 (more expensive for some FPA's)
- r0 (not saved and won't conflict with parameter register)
- r4, r3, r2 (not saved, highest used first to make less conflict)
- r5 (not saved, but forces r6 to be saved if DI/DFmode)
- r15, r14, r13, r12, r11, r10, r9, r8, r7, r6 (less to save)
- r1, ap */
-
-#define REG_ALLOC_ORDER \
- {17, 18, \
- 19, 20, 21, 22, 23, \
- 24, \
- 0, \
- 4, 3, 2, \
- 5, \
- 15, 14, 13, 12, 11, 10, \
- 9, 8, 7, 6, \
- 1, 16}
-
-/* True if register is floating-point. */
-#define FP_REGNO_P(N) ((N) >= 17)
-
-/* 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 ROMP, ordinary registers hold 32 bits worth;
- a single floating point register is always enough for
- anything that can be stored in them at all. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- (FP_REGNO_P (REGNO) ? GET_MODE_NUNITS (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.
- On ROMP, the cpu registers can hold any mode but the float registers
- can hold only floating point. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (! FP_REGNO_P (REGNO) || GET_MODE_CLASS (MODE) == MODE_FLOAT \
- || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
-
-/* 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) \
- ((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))
-
-/* A C expression returning the cost of moving data from a register of class
- CLASS1 to one of CLASS2.
-
- On the ROMP, access to floating-point registers is expensive (even between
- two FP regs.) */
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
- (2 + 10 * ((CLASS1) == FP_REGS) + 10 * (CLASS2 == FP_REGS))
-
-/* Specify the registers used for certain standard purposes.
- The values of these macros are register numbers. */
-
-/* ROMP 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 1
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 13
-
-/* 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 16
-
-/* Place to put static chain when calling a function that requires it. */
-#define STATIC_CHAIN \
- gen_rtx (MEM, Pmode, gen_rtx (PLUS, Pmode, stack_pointer_rtx, \
- GEN_INT (-36)))
-
-/* Place where static chain is found upon entry to routine. */
-#define STATIC_CHAIN_INCOMING \
- gen_rtx (MEM, Pmode, gen_rtx (PLUS, Pmode, arg_pointer_rtx, \
- GEN_INT (-20)))
-
-/* Place that structure value return address is placed.
-
- On the ROMP, it is passed as an extra parameter. */
-#define STRUCT_VALUE 0
-
-/* 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 ROMP has two types of registers, general and floating-point.
-
- However, r0 is special in that it cannot be used as a base register.
- So make a class for registers valid as base registers.
-
- For floating-point support, add classes that just consist of r0 and
- r15, respectively. */
-
-enum reg_class { NO_REGS, R0_REGS, R15_REGS, BASE_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", "R0_REGS", "R15_REGS", "BASE_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, 0x00001, 0x08000, 0x1fffe, 0x1ffff, \
- 0x1fe0000, 0x1ffffff }
-
-/* 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) == 0 ? GENERAL_REGS : FP_REGNO_P (REGNO) ? FP_REGS : BASE_REGS)
-
-/* The class value for index registers, and the one for base regs. */
-#define INDEX_REG_CLASS BASE_REGS
-#define BASE_REG_CLASS BASE_REGS
-
-/* Get reg_class from a letter such as appears in the machine description. */
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'f' ? FP_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'z' ? R0_REGS \
- : (C) == 't' ? R15_REGS \
- : NO_REGS)
-
-/* The letters I, J, K, L, M, N, and P 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.
-
- `I' is constants less than 16
- `J' is negative constants greater than -16
- `K' is the range for a normal D insn.
- `L' is a constant with only the low-order 16 bits set
- `M' is a constant with only the high-order 16 bits set
- `N' is a single-bit constant
- `O' is a constant with either the high-order or low-order 16 bits all ones
- `P' is the complement of a single-bit constant
- */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ( (C) == 'I' ? (unsigned) (VALUE) < 0x10 \
- : (C) == 'J' ? (VALUE) < 0 && (VALUE) > -16 \
- : (C) == 'K' ? (unsigned) ((VALUE) + 0x8000) < 0x10000 \
- : (C) == 'L' ? ((VALUE) & 0xffff0000) == 0 \
- : (C) == 'M' ? ((VALUE) & 0xffff) == 0 \
- : (C) == 'N' ? exact_log2 (VALUE) >= 0 \
- : (C) == 'O' ? ((VALUE) & 0xffff) == 0xffff \
- || ((VALUE) & 0xffff0000) == 0xffff0000 \
- : (C) == 'P' ? exact_log2 (~ (VALUE)) >= 0 \
- : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself.
- No floating-point constants on ROMP. */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
-
-/* Optional extra constraints for this machine.
-
- For the ROMP, `Q' means that this is a memory operand but not a symbolic
- memory operand. Note that an unassigned pseudo register is such a
- memory operand. If register allocation has not been done, we reject
- pseudos, since we assume (hope) that they will get hard registers.
-
- `R' means that this is a constant pool reference to the current function.
- This is just r14 and so can be treated as a register. We bother with this
- just in move insns as that is the only place it is likely to occur.
-
- `S' means that this is the address of a constant pool location. This is
- equal to r14 plus a constant. We also only check for this in move insns. */
-
-#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? \
- ((GET_CODE (OP) == REG \
- && REGNO (OP) >= FIRST_PSEUDO_REGISTER \
- && reg_renumber != 0 \
- && reg_renumber[REGNO (OP)] < 0) \
- || (GET_CODE (OP) == MEM \
- && ! symbolic_memory_operand (OP, VOIDmode))) \
- : (C) == 'R' ? current_function_operand (OP, VOIDmode) \
- : (C) == 'S' ? constant_pool_address_operand (OP, VOIDmode) \
- : 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.
-
- For the ROMP, if X is a memory reference that involves a symbol,
- we must use a BASE_REGS register instead of GENERAL_REGS
- to do the reload. The argument of MEM be either REG, PLUS, or SYMBOL_REF
- to be valid, so we assume that this is the case.
-
- Also, if X is an integer class, ensure that floating-point registers
- aren't used. */
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == FP_REGS && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
- ? GENERAL_REGS : \
- (CLASS) != GENERAL_REGS ? (CLASS) : \
- GET_CODE (X) != MEM ? GENERAL_REGS : \
- GET_CODE (XEXP (X, 0)) == SYMBOL_REF ? BASE_REGS : \
- GET_CODE (XEXP (X, 0)) == LABEL_REF ? BASE_REGS : \
- GET_CODE (XEXP (X, 0)) == CONST ? BASE_REGS : \
- GET_CODE (XEXP (X, 0)) == REG ? GENERAL_REGS : \
- GET_CODE (XEXP (X, 0)) != PLUS ? GENERAL_REGS : \
- GET_CODE (XEXP (XEXP (X, 0), 1)) == SYMBOL_REF ? BASE_REGS : \
- GET_CODE (XEXP (XEXP (X, 0), 1)) == LABEL_REF ? BASE_REGS : \
- GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST ? BASE_REGS : GENERAL_REGS)
-
-/* Return the register class of a scratch register needed to store into
- OUT from a register of class CLASS in MODE.
-
- On the ROMP, we cannot store into a symbolic memory address from an
- integer register; we need a BASE_REGS register as a scratch to do it. */
-
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT) \
- (GET_MODE_CLASS (MODE) == MODE_INT && symbolic_memory_operand (OUT, MODE) \
- ? BASE_REGS : NO_REGS)
-
-/* Return the maximum number of consecutive registers
- needed to represent mode MODE in a register of class CLASS.
-
- On ROMP, this is the size of MODE in words,
- except in the FP regs, where a single reg is always enough. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((CLASS) == FP_REGS ? 1 \
- : ((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 if the nominal address of the stack frame
- is at the high-address end of the local variables;
- that is, each additional local variable allocated
- goes at a more negative offset in the frame. */
-#define FRAME_GROWS_DOWNWARD
-
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated.
- On the ROMP, if we set the frame pointer to 15 words below the highest
- address of the highest local variable, the first 16 words will be
- addressable via D-short insns. */
-#define STARTING_FRAME_OFFSET 64
-
-/* If we generate an insn to push BYTES bytes,
- this says how many the stack pointer really advances by.
- On ROMP, don't define this because there are no push insns. */
-/* #define PUSH_ROUNDING(BYTES) */
-
-/* Offset of first parameter from the argument pointer register value.
- On the ROMP, we define the argument pointer to the start of the argument
- area. */
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Define this if stack space is still allocated for a parameter passed
- in a register. The value is the number of bytes. */
-#define REG_PARM_STACK_SPACE(FNDECL) 16
-
-/* This is the difference between the logical top of stack and the actual sp.
-
- For the ROMP, sp points past the words allocated for the first four outgoing
- arguments (they are part of the callee's frame). */
-#define STACK_POINTER_OFFSET -16
-
-/* Define this if the maximum size of all the outgoing args is to be
- accumulated and pushed during the prologue. The amount can be
- found in the variable current_function_outgoing_args_size. */
-#define ACCUMULATE_OUTGOING_ARGS
-
-/* 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 ROMP the value is found in r2, unless the machine specific option
- fp-arg-in-fpregs is selected, in which case FP return values are in fr1 */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, TYPE_MODE (VALTYPE), \
- (TARGET_FP_REGS && \
- GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT) ? 18 : 2)
-
-/* Define how to find the value returned by a library function
- assuming the value has mode MODE. */
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 2)
-
-/* The definition of this macro implies that there are cases where
- a scalar value cannot be returned in registers.
-
- For the ROMP, if compatibility with HC is required, anything of
- type DImode is returned in memory. */
-
-#define RETURN_IN_MEMORY(type) \
- (TYPE_MODE (type) == BLKmode \
- || (TARGET_HC_STRUCT_RETURN && TYPE_MODE (type) == DImode))
-
-/* 1 if N is a possible register number for a function value
- as seen by the caller.
-
- On ROMP, r2 is the only register thus used unless fp values are to be
- returned in fp regs, in which case fr1 is also used. */
-
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || ((N) == 18 && TARGET_FP_REGS))
-
-/* 1 if N is a possible register number for function argument passing.
- On ROMP, these are r2-r5 (and fr1-fr4 if fp regs are used). */
-
-#define FUNCTION_ARG_REGNO_P(N) \
- (((N) <= 5 && (N) >= 2) || (TARGET_FP_REGS && (N) > 17 && (N) < 21))
-
-/* 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 ROMP, this is a structure. The first word is the number of
- words of (integer only if -mfp-arg-in-fpregs is specified) arguments
- scanned so far (including the invisible argument, if any, which holds
- the structure-value-address). The second word hold the corresponding
- value for floating-point arguments, except that both single and double
- count as one register. */
-
-struct rt_cargs {int gregs, fregs; };
-#define CUMULATIVE_ARGS struct rt_cargs
-
-#define USE_FP_REG(MODE,CUM) \
- (TARGET_FP_REGS && GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && (CUM).fregs < 3)
-
-/* Define intermediate macro to compute the size (in registers) of an argument
- for the ROMP. */
-
-#define ROMP_ARG_SIZE(MODE, TYPE, NAMED) \
-(! (NAMED) ? 0 \
- : (MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \
- : (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
-
-/* 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 ROMP, the 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) \
- (CUM).gregs = 0, \
- (CUM).fregs = 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) \
-{ if (NAMED) \
- { \
- if (USE_FP_REG(MODE, CUM)) \
- (CUM).fregs++; \
- else \
- (CUM).gregs += ROMP_ARG_SIZE (MODE, TYPE, NAMED); \
- } \
-}
-
-/* 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 ROMP the first four words of args are normally in registers
- and the rest are pushed. */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- (! (NAMED) ? 0 \
- : ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST) ? 0 \
- : USE_FP_REG(MODE,CUM) ? gen_rtx(REG, (MODE),(CUM.fregs) + 17) \
- : (CUM).gregs < 4 ? gen_rtx(REG, (MODE), 2 + (CUM).gregs) : 0)
-
-/* For an arg passed partly in registers and partly in memory,
- this is the number of registers used.
- For args passed entirely in registers or entirely in memory, zero. */
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- (! (NAMED) ? 0 \
- : USE_FP_REG(MODE,CUM) ? 0 \
- : (((CUM).gregs < 4 \
- && 4 < ((CUM).gregs + ROMP_ARG_SIZE (MODE, TYPE, NAMED))) \
- ? 4 - (CUM).gregs : 0))
-
-/* Perform any needed actions needed for a function that is receiving a
- variable number of arguments.
-
- CUM is as above.
-
- MODE and TYPE are the mode and type of the current parameter.
-
- PRETEND_SIZE is a variable that should be set to the amount of stack
- that must be pushed by the prolog to pretend that our caller pushed
- it.
-
- Normally, this macro will push all remaining incoming registers on the
- stack and set PRETEND_SIZE to the length of the registers pushed. */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ if (TARGET_FP_REGS) \
- error ("can't have varargs with -mfp-arg-in-fp-regs"); \
- else if ((CUM).gregs < 4) \
- { \
- int first_reg_offset = (CUM).gregs; \
- \
- if (MUST_PASS_IN_STACK (MODE, TYPE)) \
- first_reg_offset += ROMP_ARG_SIZE (TYPE_MODE (TYPE), TYPE, 1); \
- \
- if (first_reg_offset > 4) \
- first_reg_offset = 4; \
- \
- if (! NO_RTL && first_reg_offset != 4) \
- move_block_from_reg \
- (2 + first_reg_offset, \
- gen_rtx (MEM, BLKmode, \
- plus_constant (virtual_incoming_args_rtx, \
- first_reg_offset * 4)), \
- 4 - first_reg_offset, (4 - first_reg_offset) * UNITS_PER_WORD); \
- PRETEND_SIZE = (4 - first_reg_offset) * UNITS_PER_WORD; \
- } \
-}
-
-/* This macro produces the initial definition of a function name.
- On the ROMP, we need to place an extra '.' in the function name. */
-
-#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
-{ if (TREE_PUBLIC(DECL)) \
- fprintf (FILE, "\t.globl _.%s\n", NAME); \
- fprintf (FILE, "_.%s:\n", NAME); \
-}
-
-/* This macro is used to output the start of the data area.
-
- On the ROMP, the _name is a pointer to the data area. At that
- location is the address of _.name, which is really the name of
- the function. We need to set all this up here.
-
- The global declaration of the data area, if needed, is done in
- `assemble_function', where it thinks it is globalizing the function
- itself. */
-
-#define ASM_OUTPUT_POOL_PROLOGUE(FILE, NAME, DECL, SIZE) \
-{ extern int data_offset; \
- data_section (); \
- fprintf (FILE, "\t.align 2\n"); \
- ASM_OUTPUT_LABEL (FILE, NAME); \
- fprintf (FILE, "\t.long _.%s, 0, ", NAME); \
- if (current_function_calls_alloca) \
- fprintf (FILE, "0x%x\n", \
- 0xf6900000 + current_function_outgoing_args_size); \
- else \
- fprintf (FILE, "0\n"); \
- data_offset = ((SIZE) + 12 + 3) / 4; \
-}
-
-/* Select section for constant in constant pool.
-
- On ROMP, all constants are in the data area. */
-
-#define SELECT_RTX_SECTION(MODE, X) data_section ()
-
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf(FILE, "\tcas r0,r15,r0\n\tbali r15,mcount\n");
-
-/* 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 */
-
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
-
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts.
-
- The trampoline should set the static chain pointer to value placed
- into the trampoline and should branch to the specified routine.
-
- On the ROMP, we have a problem. There are no free registers to use
- to construct the static chain and function addresses. Hence we use
- the following kludge: r15 (the return address) is first saved in mq.
- Then we use r15 to form the function address. We then branch to the
- function and restore r15 in the delay slot. This makes it appear that
- the function was called directly from the caller.
-
- (Note that the function address built is actually that of the data block.
- This is passed in r0 and the actual routine address is loaded into r15.)
-
- In addition, note that the address of the "called function", in this case
- the trampoline, is actually the address of the data area. So we need to
- make a fake data area that will contain the address of the trampoline.
- Note that this must be defined as two half-words, since the trampoline
- template (as opposed to the trampoline on the stack) is only half-word
- aligned. */
-
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf (FILE, "\t.short 0,0\n"); \
- fprintf (FILE, "\tcau r0,0(r0)\n"); \
- fprintf (FILE, "\toil r0,r0,0\n"); \
- fprintf (FILE, "\tmts r10,r15\n"); \
- fprintf (FILE, "\tst r0,-36(r1)\n"); \
- fprintf (FILE, "\tcau r15,0(r0)\n"); \
- fprintf (FILE, "\toil r15,r15,0\n"); \
- fprintf (FILE, "\tcas r0,r15,r0\n"); \
- fprintf (FILE, "\tls r15,0(r15)\n"); \
- fprintf (FILE, "\tbrx r15\n"); \
- fprintf (FILE, "\tmfs r10,r15\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-
-#define TRAMPOLINE_SIZE 36
-
-/* 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.
-
- On the RT, the static chain and function addresses are written in
- two 16-bit sections.
-
- We also need to write the address of the first instruction in
- the trampoline into the first word of the trampoline to simulate a
- data area. */
-
-#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
-{ \
- rtx _addr, _temp; \
- rtx _val; \
- \
- _temp = expand_binop (SImode, add_optab, ADDR, \
- GEN_INT (4), \
- 0, 1, OPTAB_LIB_WIDEN); \
- emit_move_insn (gen_rtx (MEM, SImode, \
- memory_address (SImode, ADDR)), _temp); \
- \
- _val = force_reg (SImode, CXT); \
- _addr = memory_address (HImode, plus_constant (ADDR, 10)); \
- emit_move_insn (gen_rtx (MEM, HImode, _addr), \
- gen_lowpart (HImode, _val)); \
- _temp = expand_shift (RSHIFT_EXPR, SImode, _val, \
- build_int_2 (16, 0), 0, 1); \
- _addr = memory_address (HImode, plus_constant (ADDR, 6)); \
- emit_move_insn (gen_rtx (MEM, HImode, _addr), \
- gen_lowpart (HImode, _temp)); \
- \
- _val = force_reg (SImode, FNADDR); \
- _addr = memory_address (HImode, plus_constant (ADDR, 24)); \
- emit_move_insn (gen_rtx (MEM, HImode, _addr), \
- gen_lowpart (HImode, _val)); \
- _temp = expand_shift (RSHIFT_EXPR, SImode, _val, \
- build_int_2 (16, 0), 0, 1); \
- _addr = memory_address (HImode, plus_constant (ADDR, 20)); \
- emit_move_insn (gen_rtx (MEM, HImode, _addr), \
- gen_lowpart (HImode, _temp)); \
- \
-}
-
-/* Definitions for register eliminations.
-
- We have two registers that can be eliminated on the ROMP. First, the
- frame pointer register can often be eliminated in favor of the stack
- pointer register. Secondly, the argument pointer register can always be
- eliminated; it is replaced with either the stack or frame pointer.
-
- In addition, we use the elimination mechanism to see if r14 is needed.
- Initially we assume that it isn't. If it is, we spill it. This is done
- by making it an eliminable register. It doesn't matter what we replace
- it with, since it will never occur in the rtl at this point. */
-
-/* This is an array of structures. Each structure initializes one pair
- of eliminable registers. The "from" register number is given first,
- followed by "to". Eliminations of the same "from" register are listed
- in order of preference. */
-#define ELIMINABLE_REGS \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- { 14, 0}}
-
-/* Given FROM and TO register numbers, say whether this elimination is allowed.
- Frame pointer elimination is automatically handled.
-
- For the ROMP, if frame pointer elimination is being done, we would like to
- convert ap into fp, not sp.
-
- We need r14 if various conditions (tested in romp_using_r14) are true.
-
- All other eliminations are valid. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
- ? ! frame_pointer_needed \
- : (FROM) == 14 ? ! romp_using_r14 () \
- : 1)
-
-/* Define the offset between two registers, one to be eliminated, and the other
- its replacement, at the start of a routine. */
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- { \
- if (romp_pushes_stack ()) \
- (OFFSET) = ((get_frame_size () - 64) \
- + current_function_outgoing_args_size); \
- else \
- (OFFSET) = - (romp_sa_size () + 64); \
- } \
- else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \
- (OFFSET) = romp_sa_size () - 16 + 64; \
- else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- { \
- if (romp_pushes_stack ()) \
- (OFFSET) = (get_frame_size () + (romp_sa_size () - 16) \
- + current_function_outgoing_args_size); \
- else \
- (OFFSET) = -16; \
- } \
- else if ((FROM) == 14) \
- (OFFSET) = 0; \
- else \
- abort (); \
-}
-
-/* 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) 0
-#define REGNO_OK_FOR_BASE_P(REGNO) \
-((REGNO) < FIRST_PSEUDO_REGISTER \
- ? (REGNO) < 16 && (REGNO) != 0 && (REGNO) != 16 \
- : (reg_renumber[REGNO] < 16 && reg_renumber[REGNO] >= 0 \
- && reg_renumber[REGNO] != 16))
-
-/* Maximum number of registers that can appear in a valid memory address. */
-
-#define MAX_REGS_PER_ADDRESS 1
-
-/* 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 ROMP, there is a bit of a hack here. Basically, we wish to
- only issue instructions that are not `as' macros. However, in the
- case of `get', `load', and `store', if the operand is a relocatable
- symbol (possibly +/- an integer), there is no way to express the
- resulting split-relocation except with the macro. Therefore, allow
- either a constant valid in a normal (sign-extended) D-format insn or
- a relocatable expression.
-
- Also, for DFmode and DImode, we must ensure that both words are
- addressable.
-
- We define two macros: The first is given an offset (0 or 4) and indicates
- that the operand is a CONST_INT that is valid for that offset. The second
- indicates a valid non-CONST_INT constant. */
-
-#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET) \
- (GET_CODE (X) == CONST_INT \
- && (unsigned) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
-
-#define LEGITIMATE_ADDRESS_CONSTANT_P(X) \
- (GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && (GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
- || GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF) \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))
-
-/* Include all constant integers and constant double, but exclude
- SYMBOL_REFs that are to be obtained from the data area (see below). */
-#define LEGITIMATE_CONSTANT_P(X) \
- ((LEGITIMATE_ADDRESS_CONSTANT_P (X) \
- || GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE) \
- && ! (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
-
-/* For no good reason, we do the same as the other RT compilers and load
- the addresses of data areas for a function from our data area. That means
- that we need to mark such SYMBOL_REFs. We do so here. */
-#define ENCODE_SECTION_INFO(DECL) \
- if (TREE_CODE (TREE_TYPE (DECL)) == FUNCTION_TYPE) \
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 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) 0
-/* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) != 0 && (REGNO (X) < 17 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
-
-#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 ROMP, a legitimate address is either a legitimate constant,
- a register plus a legitimate constant, or a register. See the
- discussion at the LEGITIMATE_ADDRESS_CONSTANT_P macro. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
- goto ADDR; \
- if (GET_CODE (X) != CONST_INT && LEGITIMATE_ADDRESS_CONSTANT_P (X)) \
- goto ADDR; \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && LEGITIMATE_ADDRESS_CONSTANT_P (XEXP (X, 1))) \
- goto ADDR; \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
- && (((MODE) != DFmode && (MODE) != DImode) \
- || (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4)))) \
- 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 ROMP, check for the sum of a register with a constant
- integer that is out of range. If so, generate code to add the
- constant with the low-order 16 bits masked to the register and force
- this result into another register (this can be done with `cau').
- Then generate an address of REG+(CONST&0xffff), allowing for the
- possibility of bit 16 being a one.
-
- If the register is not OK for a base register, abort. */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned) (INTVAL (XEXP (X, 1)) + 0x8000) >= 0x10000) \
- { int high_int, low_int; \
- if (! REG_OK_FOR_BASE_P (XEXP (X, 0))) \
- abort (); \
- high_int = INTVAL (XEXP (X, 1)) >> 16; \
- low_int = INTVAL (XEXP (X, 1)) & 0xffff; \
- if (low_int & 0x8000) \
- high_int += 1, low_int |= 0xffff0000; \
- (X) = gen_rtx (PLUS, SImode, \
- force_operand \
- (gen_rtx (PLUS, SImode, XEXP (X, 0), \
- GEN_INT (high_int << 16)), 0),\
- GEN_INT (low_int)); \
- } \
-}
-
-/* Go to LABEL if ADDR (a legitimate address expression)
- has an effect that depends on the machine mode it is used for.
-
- On the ROMP this is true only if the address is valid with a zero offset
- but not with an offset of four (this means it cannot be used as an
- address for DImode or DFmode). Since we know it is valid, we just check
- for an address that is not valid with an offset of four. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
-{ if (GET_CODE (ADDR) == PLUS \
- && ! LEGITIMATE_ADDRESS_CONSTANT_P (XEXP (ADDR, 1)) \
- && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1), 4)) \
- goto LABEL; \
-}
-
-/* Define this if some processing needs to be done immediately before
- emitting code for an insn.
-
- This is used on the ROMP, to compensate for a bug in the floating-point
- code. When a floating-point operation is done with the first and third
- operands both the same floating-point register, it will generate bad code
- for the MC68881. So we must detect this. If it occurs, we patch the
- first operand to be fr0 and insert a move insn to move it to the desired
- destination. */
-#define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) \
- { rtx op0, op1, op2, operation, tem; \
- if (NOPERANDS >= 3 && get_attr_type (INSN) == TYPE_FP) \
- { \
- op0 = OPERANDS[0]; \
- operation = OPERANDS[1]; \
- if (float_conversion (operation, VOIDmode)) \
- operation = XEXP (operation, 0); \
- if (float_binary (operation, VOIDmode)) \
- { \
- op1 = XEXP (operation, 0), op2 = XEXP (operation, 1); \
- if (float_conversion (op1, VOIDmode)) \
- op1 = XEXP (op1, 0); \
- if (float_conversion (op2, VOIDmode)) \
- op2 = XEXP (op2, 0); \
- if (rtx_equal_p (op0, op2) \
- && (GET_CODE (operation) == PLUS \
- || GET_CODE (operation) == MULT)) \
- tem = op1, op1 = op2, op2 = tem; \
- if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)) \
- && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)) \
- && REGNO (op0) == REGNO (op2)) \
- { \
- tem = gen_rtx (REG, GET_MODE (op0), 17); \
- emit_insn_after (gen_move_insn (op0, tem), INSN); \
- SET_DEST (XVECEXP (PATTERN (INSN), 0, 0)) = tem; \
- OPERANDS[0] = tem; \
- } \
- } \
- } \
- }
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#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 */
-
-/* Specify the tree operation to be used to convert reals to integers. */
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-/* This is the kind of divide that is easiest to do in the general case. */
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* This flag, if defined, says the same insns that convert to a signed fixnum
- also convert validly to an unsigned one.
-
- We actually lie a bit here as overflow conditions are different. But
- they aren't being checked anyway. */
-
-#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
-
-/* Max number of bytes we can move from memory to memory
- in one reasonably fast instruction. */
-#define MOVE_MAX 4
-
-/* Nonzero if access to memory by bytes is no faster than for words.
- Also non-zero if doing byte operations (specifically shifts) in registers
- is undesirable. */
-#define SLOW_BYTE_ACCESS 1
-
-/* Define if operations between registers always perform the operation
- on the full register even if a narrower mode is specified. */
-#define WORD_REGISTER_OPERATIONS
-
-/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
- will either zero-extend or sign-extend. The value of this macro should
- be the code that says which one of the two operations is implicitly
- done, NIL if none. */
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-/* This is BSD, so it wants DBX format. */
-#define DBX_DEBUGGING_INFO
-
-/* Define the letter code used in a stabs entry for parameters passed
- with the register attribute.
-
- GCC's default value, 'P', is used by dbx to refers to an external
- procedure. The section 5 manual page for dbx implies that 'R' would be the
- right letter, but dbx 1.5 has a bug in it that precludes its use.
- Probably that is why neither hc or pcc use this. pcc puts in two
- stabs entries: one for the parameter location and one for the register
- location. The letter `r' (register)
- would be okay, but it loses parameter attribute of the stabs entry. */
-#define DBX_REGPARM_STABS_LETTER 'R'
-
-/* A C expression for the integer offset value of an automatic variable
- (N_LSYM) having address X (an RTX). This gets used in .stabs entries
- for the local variables. Compare with the default definition. */
-extern int romp_debugger_auto_correction();
-#define DEBUGGER_AUTO_OFFSET(X) \
- (GET_CODE (X) == PLUS \
- ? romp_debugger_auto_correction (INTVAL (XEXP (X, 1)) ) \
- : 0 )
-
-/* A C expression for the integer offset value of an argument (N_PSYM)
- having address X (an RTX). The nominal offset is OFFSET. */
-extern int romp_debugger_arg_correction();
-#define DEBUGGER_ARG_OFFSET(OFFSET, X) \
- romp_debugger_arg_correction (OFFSET);
-
-/* We don't have GAS for the RT yet, so don't write out special
- .stabs in cc1plus. */
-
-#define FASCIST_ASSEMBLER
-
-/* Do not break .stabs pseudos into continuations. */
-#define DBX_CONTIN_LENGTH 0
-
-/* Don't try to use the `x' type-cross-reference character in DBX data.
- Also has the consequence of putting each struct, union or enum
- into a separate .stabs, containing only cross-refs to the others. */
-#define DBX_NO_XREFS
-
-/* 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
-
-/* Mode of a function address in a call instruction (for indexing purposes).
-
- Doesn't matter on ROMP. */
-#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
-
-/* Define this if shift instructions ignore all but the low-order
- few bits.
-
- This is not true on the RT since it uses the low-order 6, not 5, bits.
- At some point, this should be extended to see how to express that. */
-
-/* #define SHIFT_COUNT_TRUNCATED */
-
-/* Compute the cost of computing a constant rtl expression RTX whose
- rtx-code is CODE, contained within an expression of code OUTER_CODE.
- The body of this macro is a portion of a switch statement. If the
- code is computed here, return it with a return statement. Otherwise,
- break from the switch. */
-
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
- case CONST_INT: \
- if ((OUTER_CODE) == IOR && exact_log2 (INTVAL (RTX)) >= 0 \
- || (OUTER_CODE) == AND && exact_log2 (~INTVAL (RTX)) >= 0 \
- || (((OUTER_CODE) == PLUS || (OUTER_CODE) == MINUS) \
- && (unsigned int) (INTVAL (RTX) + 15) < 31) \
- || ((OUTER_CODE) == SET && (unsigned int) INTVAL (RTX) < 16))\
- return 0; \
- return ((unsigned int) (INTVAL(RTX) + 0x8000) < 0x10000 \
- || (INTVAL (RTX) & 0xffff0000) == 0) ? 0 : COSTS_N_INSNS (2);\
- case CONST: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- if (current_function_operand (RTX, Pmode)) return 0; \
- return COSTS_N_INSNS (2); \
- case CONST_DOUBLE: \
- if ((RTX) == CONST0_RTX (GET_MODE (RTX))) return 2; \
- return ((GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT) \
- ? COSTS_N_INSNS (5) : COSTS_N_INSNS (4));
-
-/* Provide the costs of a rtl expression. This is in the body of a
- switch on CODE.
-
- References to our own data area are really references to r14, so they
- are very cheap. Multiples and divides are very expensive. */
-
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
- case MEM: \
- return current_function_operand (X, Pmode) ? 0 : COSTS_N_INSNS (2); \
- case MULT: \
- return (TARGET_IN_LINE_MUL && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT)\
- ? COSTS_N_INSNS (19) : COSTS_N_INSNS (25); \
- case DIV: \
- case UDIV: \
- case MOD: \
- case UMOD: \
- return COSTS_N_INSNS (45);
-
-/* Compute the cost of an address. This is meant to approximate the size
- and/or execution delay of an insn using that address. If the cost is
- approximated by the RTL complexity, including CONST_COSTS above, as
- is usually the case for CISC machines, this macro should not be defined.
- For aggressively RISCy machines, only one insn format is allowed, so
- this macro should be a constant. The value of this macro only matters
- for valid addresses.
-
- For the ROMP, everything is cost 0 except for addresses involving
- symbolic constants, which are cost 1. */
-
-#define ADDRESS_COST(RTX) \
- ((GET_CODE (RTX) == SYMBOL_REF \
- && ! CONSTANT_POOL_ADDRESS_P (RTX)) \
- || GET_CODE (RTX) == LABEL_REF \
- || (GET_CODE (RTX) == CONST \
- && ! constant_pool_address_operand (RTX, Pmode)) \
- || (GET_CODE (RTX) == PLUS \
- && ((GET_CODE (XEXP (RTX, 1)) == SYMBOL_REF \
- && ! CONSTANT_POOL_ADDRESS_P (XEXP (RTX, 0))) \
- || GET_CODE (XEXP (RTX, 1)) == LABEL_REF \
- || GET_CODE (XEXP (RTX, 1)) == CONST)))
-
-/* Adjust the length of an INSN. LENGTH is the currently-computed length and
- should be adjusted to reflect any required changes. This macro is used when
- there is some systematic length adjustment required that would be difficult
- to express in the length attribute.
-
- On the ROMP, there are two adjustments: First, a 2-byte insn in the delay
- slot of a CALL (including floating-point operations) actually takes four
- bytes. Second, we have to make the worst-case alignment assumption for
- address vectors. */
-
-#define ADJUST_INSN_LENGTH(X,LENGTH) \
- if (GET_CODE (X) == INSN && GET_CODE (PATTERN (X)) == SEQUENCE \
- && GET_CODE (XVECEXP (PATTERN (X), 0, 0)) != JUMP_INSN \
- && get_attr_length (XVECEXP (PATTERN (X), 0, 1)) == 2) \
- (LENGTH) += 2; \
- else if (GET_CODE (X) == JUMP_INSN && GET_CODE (PATTERN (X)) == ADDR_VEC) \
- (LENGTH) += 2;
-
-/* Tell final.c how to eliminate redundant test instructions. */
-
-/* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
-/* Set if condition code (really not-Z) is stored in `test bit'. */
-#define CC_IN_TB 01000
-
-/* Set if condition code is set by an unsigned compare. */
-#define CC_UNSIGNED 02000
-
-/* 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(BODY,INSN) \
- update_cc (BODY, INSN)
-
-/* Control the assembler format that we output. */
-
-/* Output at beginning of assembler file. */
-
-#define ASM_FILE_START(FILE) \
-{ extern char *version_string; \
- char *p; \
- \
- fprintf (FILE, "\t.globl .oVncs\n\t.set .oVncs,0\n") ; \
- fprintf (FILE, "\t.globl .oVgcc"); \
- for (p = version_string; *p != ' ' && *p != 0; p++) \
- fprintf (FILE, "%c", *p); \
- fprintf (FILE, "\n\t.set .oVgcc"); \
- for (p = version_string; *p != ' ' && *p != 0; p++) \
- fprintf (FILE, "%c", *p); \
- fprintf (FILE, ",0\n"); \
-}
-
-/* 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 instructions and read-only data. */
-
-#define TEXT_SECTION_ASM_OP ".text"
-
-/* Output before writable data. */
-
-#define DATA_SECTION_ASM_OP ".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", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", \
- "r10", "r11", "r12", "r13", "r14", "r15", "ap", \
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7" }
-
-/* How to renumber registers for dbx and gdb. */
-
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
-
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
-
-/* The prefix to add to user-visible assembler symbols. */
-
-#define USER_LABEL_PREFIX "_"
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, "%s%d:\n", PREFIX, NUM)
-
-/* This is how to output a label for a jump table. Arguments are the same as
- for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
- passed. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
-{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
-
-/* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*%s%d", PREFIX, NUM)
-
-/* This is how to output an assembler line defining a `double' constant. */
-
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
-
-/* This is how to output an assembler line defining a `float' constant.
-
- WARNING: Believe it or not, the ROMP assembler has a bug in its
- handling of single-precision floating-point values making it impossible
- to output such values in the expected way. Therefore, it must be output
- in hex. THIS WILL NOT WORK IF CROSS-COMPILING FROM A MACHINE THAT DOES
- NOT USE IEEE-FORMAT FLOATING-POINT, but there is nothing that can be done
- about it short of fixing the assembler. */
-
-#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- do { union { int i; float f; } u_i_f; \
- u_i_f.f = (VALUE); \
- fprintf (FILE, "\t.long 0x%x\n", u_i_f.i);\
- } while (0)
-
-/* This is how to output an assembler line defining an `int' constant. */
-
-#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "\t.long "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-/* Likewise for `char' and `short' constants. */
-
-#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t.short "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t.byte "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-
-#define ASM_OUTPUT_BYTE(FILE,VALUE) \
- fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
-
-/* This is how to output code to push a register on the stack.
- It need not be very fast code. */
-
-#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
- fprintf (FILE, "\tsis r1,4\n\tsts %s,0(r1)\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, "\tls r1,0(r1)\n\tais r1,4\n", reg_names[REGNO])
-
-/* 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.
- Don't define this if it is not supported. */
-
-/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, 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", (LOG))
-
-#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.space %d\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), ",%d\n", (SIZE)))
-
-/* 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), ",%d\n", (SIZE)))
-
-/* Store in OUTPUT a string (made with alloca) containing
- an assembler-name for a local static variable named NAME.
- LABELNO is an integer which is different for each call. */
-
-#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
-( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
- sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-
-/* Define the parentheses used to group arithmetic operations
- in assembler code. */
-
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* Print operand X (an rtx) in assembler syntax to file FILE.
- CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-
-#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
-
-/* Define which CODE values are valid. */
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- ((CODE) == '.' || (CODE) == '#')
-
-/* Print a memory address as an operand to reference that memory location. */
-
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
-{ register rtx addr = ADDR; \
- register rtx base = 0, offset = addr; \
- if (GET_CODE (addr) == REG) \
- base = addr, offset = const0_rtx; \
- else if (GET_CODE (addr) == PLUS \
- && GET_CODE (XEXP (addr, 0)) == REG) \
- base = XEXP (addr, 0), offset = XEXP (addr, 1); \
- else if (GET_CODE (addr) == SYMBOL_REF \
- && CONSTANT_POOL_ADDRESS_P (addr)) \
- { \
- offset = GEN_INT (get_pool_offset (addr) + 12); \
- base = gen_rtx (REG, SImode, 14); \
- } \
- else if (GET_CODE (addr) == CONST \
- && GET_CODE (XEXP (addr, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT \
- && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF \
- && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addr, 0), 0))) \
- { \
- offset = plus_constant (XEXP (XEXP (addr, 0), 1), \
- (get_pool_offset (XEXP (XEXP (addr, 0), 0)) \
- + 12)); \
- base = gen_rtx (REG, SImode, 14); \
- } \
- output_addr_const (FILE, offset); \
- if (base) \
- fprintf (FILE, "(%s)", reg_names [REGNO (base)]); \
-}
-
-/* Define the codes that are matched by predicates in aux-output.c. */
-
-#define PREDICATE_CODES \
- {"zero_memory_operand", {SUBREG, MEM}}, \
- {"short_memory_operand", {SUBREG, MEM}}, \
- {"symbolic_memory_operand", {SUBREG, MEM}}, \
- {"current_function_operand", {MEM}}, \
- {"constant_pool_address_operand", {SUBREG, CONST}}, \
- {"romp_symbolic_operand", {LABEL_REF, SYMBOL_REF, CONST}}, \
- {"constant_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST, CONST_INT}}, \
- {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_any_cint_operand", {SUBREG, REG, CONST_INT}}, \
- {"short_cint_operand", {CONST_INT}}, \
- {"reg_or_D_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_add_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, \
- PLUS, CONST, CONST_INT}}, \
- {"reg_or_and_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_mem_operand", {SUBREG, REG, MEM}}, \
- {"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \
- {"romp_operand", {SUBREG, MEM, REG, CONST_INT, CONST, LABEL_REF, \
- SYMBOL_REF, CONST_DOUBLE}}, \
- {"reg_0_operand", {REG}}, \
- {"reg_15_operand", {REG}}, \
- {"float_binary", {PLUS, MINUS, MULT, DIV}}, \
- {"float_unary", {NEG, ABS}}, \
- {"float_conversion", {FLOAT_TRUNCATE, FLOAT_EXTEND, FLOAT, FIX}},
-
-/* Define functions defined in aux-output.c and used in templates. */
-
-extern char *output_in_line_mul ();
-extern char *output_fpop ();
diff --git a/gcc/config/romp/romp.md b/gcc/config/romp/romp.md
deleted file mode 100755
index 3abd56b..0000000
--- a/gcc/config/romp/romp.md
+++ /dev/null
@@ -1,2776 +0,0 @@
-;;- Machine description for ROMP chip for GNU C compiler
-;; Copyright (C) 1988, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
-;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
-
-;; This file is part of GNU CC.
-
-;; GNU CC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU CC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-
-;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-
-;; Define the attributes for the ROMP.
-
-;; Insn type. Used to default other attribute values.
-
-(define_attr "type"
- "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc"
- (const_string "arith"))
-
-;; Length in bytes.
-
-(define_attr "length" ""
- (cond [(eq_attr "type" "branch")
- (if_then_else (and (ge (minus (pc) (match_dup 0))
- (const_int -256))
- (le (minus (pc) (match_dup 0))
- (const_int 254)))
- (const_int 2)
- (const_int 4))
- (eq_attr "type" "return,ibranch") (const_int 2)
- (eq_attr "type" "fp") (const_int 10)
- (eq_attr "type" "call") (const_int 4)
- (eq_attr "type" "load")
- (cond [(match_operand 1 "short_memory_operand" "") (const_int 2)
- (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]
- (const_int 4))
- (eq_attr "type" "loadz")
- (cond [(match_operand 1 "zero_memory_operand" "") (const_int 2)
- (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]
- (const_string "4"))
- (eq_attr "type" "store")
- (cond [(match_operand 0 "short_memory_operand" "") (const_int 2)
- (match_operand 0 "symbolic_memory_operand" "") (const_int 8)]
- (const_int 4))]
- (const_int 4)))
-
-;; Whether insn can be placed in a delay slot.
-
-(define_attr "in_delay_slot" "yes,no"
- (cond [(eq_attr "length" "8,10,38") (const_string "no")
- (eq_attr "type" "branch,ibranch,return,call,multi")
- (const_string "no")]
- (const_string "yes")))
-
-;; Whether insn needs a delay slot. We have to say that two-byte
-;; branches do not need a delay slot. Otherwise, branch shortening will
-;; try to do something with delay slot insns (we want it to on the PA).
-;; This is a kludge, which should be cleaned up at some point.
-
-(define_attr "needs_delay_slot" "yes,no"
- (if_then_else (ior (and (eq_attr "type" "branch")
- (eq_attr "length" "4"))
- (eq_attr "type" "ibranch,return,call"))
- (const_string "yes") (const_string "no")))
-
-;; What insn does to the condition code.
-
-(define_attr "cc"
- "clobber,none,sets,change0,copy1to0,compare,tbit"
- (cond [(eq_attr "type" "load,loadz") (const_string "change0")
- (eq_attr "type" "store") (const_string "none")
- (eq_attr "type" "fp,call") (const_string "clobber")
- (eq_attr "type" "branch,ibranch,return") (const_string "none")
- (eq_attr "type" "address") (const_string "change0")
- (eq_attr "type" "compare") (const_string "compare")
- (eq_attr "type" "arith") (const_string "sets")]
- (const_string "clobber")))
-
-;; Define attributes for `asm' insns.
-
-(define_asm_attributes [(set_attr "type" "misc")
- (set_attr "length" "8")
- (set_attr "in_delay_slot" "no")
- (set_attr "cc" "clobber")])
-
-;; Define the delay slot requirements for branches and calls. We don't have
-;; any annulled insns.
-;;
-(define_delay (eq_attr "needs_delay_slot" "yes")
- [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
-
-;; We cannot give a floating-point comparison a delay slot, even though it
-;; could make use of it. This is because it would confuse next_cc0_user
-;; to do so. Other fp insns can't get a delay slow because they set their
-;; result and use their input after the delay slot insn is executed. This
-;; isn't what reorg.c expects.
-
-;; Define load & store delays. These were obtained by measurements done by
-;; jfc@athena.mit.edu.
-;;
-;; In general, the memory unit can support at most two simultaneous operations.
-;;
-;; Loads take 5 cycles to return the data and can be pipelined up to the
-;; limit of two simultaneous operations.
-(define_function_unit "memory" 1 2 (eq_attr "type" "load,loadz") 5 0)
-
-;; Stores do not return data, but tie up the memory unit for 2 cycles if the
-;; next insn is also a store.
-(define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 2
- [(eq_attr "type" "store")])
-
-;; Move word instructions.
-;;
-;; If destination is memory but source is not register, force source to
-;; register.
-;;
-;; If source is a constant that is too large to load in a single insn, build
-;; it in two pieces.
-;;
-;; If destination is memory and source is a register, a temporary register
-;; will be needed. In that case, make a PARALLEL of the SET and a
-;; CLOBBER of a SCRATCH to allocate the required temporary.
-;;
-;; This temporary is ACTUALLY only needed when the destination is a
-;; relocatable expression. For generating RTL, however, we always
-;; place the CLOBBER. In insns where it is not needed, the SCRATCH will
-;; not be allocated to a register.
-;;
-;; Also, avoid creating pseudo-registers or SCRATCH rtx's during reload as
-;; they will not be correctly handled. We never need pseudos for that
-;; case anyway.
-;;
-;; We do not use DEFINE_SPLIT for loading constants because the number
-;; of cases in the resulting unsplit insn would be too high to deal
-;; with practically.
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
-{ rtx op0 = operands[0];
- rtx op1 = operands[1];
-
- if (GET_CODE (op1) == REG && REGNO (op1) == 16)
- DONE;
-
- if (GET_CODE (op0) == REG && REGNO (op0) == 16)
- DONE;
-
- if (GET_CODE (op0) == MEM && ! reload_in_progress)
- {
- emit_insn (gen_storesi (operands[0], force_reg (SImode, operands[1])));
- DONE;
- }
- else if (GET_CODE (op1) == CONST_INT)
- {
- int const_val = INTVAL (op1);
-
- /* Try a number of cases to see how to best load the constant. */
- if ((const_val & 0xffff) == 0
- || (const_val & 0xffff0000) == 0
- || (unsigned) (const_val + 0x8000) < 0x10000)
- /* Can do this in one insn, so generate it. */
- ;
- else if (((- const_val) & 0xffff) == 0
- || ((- const_val) & 0xffff0000) == 0
- || (unsigned) ((- const_val) + 0x8000) < 0x10000)
- {
- /* Can do this by loading the negative constant and then negating. */
- emit_move_insn (operands[0],
- GEN_INT (- const_val));
- emit_insn (gen_negsi2 (operands[0], operands[0]));
- DONE;
- }
- else
- /* Do this the long way. */
- {
- unsigned int high_part = const_val & 0xffff0000;
- unsigned int low_part = const_val & 0xffff;
- int i;
-
- if (low_part >= 0x10 && exact_log2 (low_part) >= 0)
- i = high_part, high_part = low_part, low_part = i;
-
- emit_move_insn (operands[0],
- GEN_INT (low_part));
- emit_insn (gen_iorsi3 (operands[0], operands[0],
- GEN_INT (high_part)));
- DONE;
- }
- }
-}")
-
-;; Move from a symbolic memory location to a register is special. In this
-;; case, we know in advance that the register cannot be r0, so we can improve
-;; register allocation by treating it separately.
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=b")
- (match_operand:SI 1 "symbolic_memory_operand" "m"))]
- ""
- "load %0,%1"
- [(set_attr "type" "load")])
-
-;; Generic single-word move insn. We avoid the case where the destination is
-;; a symbolic address, as that needs a temporary register.
-
-(define_insn ""
- [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,r,r,r,b,Q")
- (match_operand:SI 1 "romp_operand" "rR,I,K,L,M,S,s,Q,m,r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- cas %0,%1,r0
- lis %0,%1
- cal %0,%1(r0)
- cal16 %0,%1(r0)
- cau %0,%H1(r0)
- ail %0,r14,%C1
- get %0,$%1
- l%M1 %0,%1
- load %0,%1
- st%M0 %1,%0"
- [(set_attr "type" "address,address,address,address,address,arith,misc,load,load,store")
- (set_attr "length" "2,2,4,4,4,4,8,*,*,*")])
-
-(define_insn "storesi"
- [(set (match_operand:SI 0 "memory_operand" "=Q,m")
- (match_operand:SI 1 "register_operand" "r,r"))
- (clobber (match_scratch:SI 2 "=X,&b"))]
- ""
- "@
- st%M0 %1,%0
- store %1,%0,%2"
- [(set_attr "type" "store")])
-
-;; This pattern is used by reload when we store into a symbolic address. It
-;; provides the temporary register required. This pattern is only used
-;; when SECONDARY_OUTPUT_RELOAD_CLASS returns something other than
-;; NO_REGS, so we need not have any predicates here.
-
-(define_expand "reload_outsi"
- [(parallel [(set (match_operand:SI 0 "symbolic_memory_operand" "=m")
- (match_operand:SI 1 "" "r"))
- (clobber (match_operand:SI 2 "" "=&b"))])]
- ""
- "")
-
-;; Now do the same for the QI move instructions.
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{ rtx op0 = operands[0];
-
- if (GET_CODE (op0) == MEM && ! reload_in_progress)
- {
- emit_insn (gen_storeqi (operands[0], force_reg (QImode, operands[1])));
- DONE;
- }
-}")
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=b")
- (match_operand:QI 1 "symbolic_memory_operand" "m"))]
- ""
- "loadc %0,%1"
- [(set_attr "type" "load")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")
- (match_operand:QI 1 "romp_operand" "r,I,n,s,Q,m,r"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- cas %0,%1,r0
- lis %0,%1
- cal %0,%L1(r0)
- get %0,$%1
- lc%M1 %0,%1
- loadc %0,%1
- stc%M0 %1,%0"
- [(set_attr "type" "address,address,address,misc,load,load,store")
- (set_attr "length" "2,2,4,8,*,*,*")])
-
-(define_insn "storeqi"
- [(set (match_operand:QI 0 "memory_operand" "=Q,m")
- (match_operand:QI 1 "register_operand" "r,r"))
- (clobber (match_scratch:SI 2 "=X,&b"))]
- ""
- "@
- stc%M0 %1,%0
- storec %1,%0,%2"
- [(set_attr "type" "store")])
-
-(define_expand "reload_outqi"
- [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m")
- (match_operand:QI 1 "" "r"))
- (clobber (match_operand:SI 2 "" "=&b"))])]
- ""
- "")
-
-;; Finally, the HI instructions.
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{ rtx op0 = operands[0];
-
- if (GET_CODE (op0) == MEM && ! reload_in_progress)
- {
- emit_insn (gen_storehi (operands[0], force_reg (HImode, operands[1])));
- DONE;
- }
-}")
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=b")
- (match_operand:HI 1 "symbolic_memory_operand" "m"))]
- ""
- "loadha %0,%1"
- [(set_attr "type" "load")])
-
-
-;; use cal16 instead of cal for constant source because combine requires
-;; the high bits of the register to be 0 after a HImode load of a constant
-
-(define_insn ""
- [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")
- (match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- cas %0,%1,r0
- lis %0,%1
- cal16 %0,%L1(r0)
- get %0,$%1
- lh%N1 %0,%1
- loadh %0,%1
- sth%M0 %1,%0"
- [(set_attr "type" "address,address,address,misc,loadz,loadz,store")
- (set_attr "length" "2,2,4,8,*,*,*")])
-
-(define_insn "storehi"
- [(set (match_operand:HI 0 "memory_operand" "=Q,m")
- (match_operand:HI 1 "register_operand" "r,r"))
- (clobber (match_scratch:SI 2 "=X,&b"))]
- ""
- "@
- sth%M0 %1,%0
- storeh %1,%0,%2"
- [(set_attr "type" "store")])
-
-(define_expand "reload_outhi"
- [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m")
- (match_operand:HI 1 "" "r"))
- (clobber (match_operand:SI 2 "" "=&b"))])]
- ""
- "")
-
-;; For DI move, if we have a constant, break the operation apart into
-;; two SImode moves because the optimizer may be able to do a better job
-;; with the resulting code.
-;;
-;; For memory stores, make the required pseudo for a temporary in case we
-;; are storing into an absolute address.
-;;
-;; We need to be careful about the cases where the output is a register that is
-;; the second register of the input.
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
-{ rtx op0 = operands[0];
- rtx op1 = operands[1];
-
- if (CONSTANT_P (op1))
- {
- rtx insns;
-
- start_sequence ();
- emit_move_insn (operand_subword (op0, 0, 1, DImode),
- operand_subword (op1, 0, 1, DImode));
- emit_move_insn (operand_subword (op0, 1, 1, DImode),
- operand_subword (op1, 1, 1, DImode));
- insns = get_insns ();
- end_sequence ();
-
- emit_no_conflict_block (insns, op0, op1, 0, op1);
- DONE;
- }
-
- if (GET_CODE (op0) == MEM && ! reload_in_progress)
- {
- emit_insn (gen_storedi (operands[0], force_reg (DImode, operands[1])));
- DONE;
- }
-}")
-
-(define_insn ""
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
- (match_operand:DI 1 "reg_or_mem_operand" "r,Q,m,r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"cas %O0,%O1,r0\;cas %0,%1,r0\";
- else
- return \"cas %0,%1,r0\;cas %O0,%O1,r0\";
- case 1:
- /* Here we must see which word to load first. We default to the
- low-order word unless it occurs in the address. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"l%M1 %O0,%O1\;l%M1 %0,%1\";
- else
- return \"l%M1 %0,%1\;l%M1 %O0,%O1\";
- case 2:
- return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\";
- case 3:
- return \"st%M0 %1,%0\;st%M0 %O1,%O0\";
- }
-}"
- [(set_attr "type" "multi")
- (set_attr "cc" "change0,change0,change0,none")
- (set_attr "length" "4,12,8,8")])
-
-(define_insn "storedi"
- [(set (match_operand:DI 0 "memory_operand" "=Q,m")
- (match_operand:DI 1 "register_operand" "r,r"))
- (clobber (match_scratch:SI 2 "=X,&b"))]
- ""
- "@
- st%M0 %1,%0\;st%M0 %O1,%O0
- get %2,$%0\;sts %1,0(%2)\;sts %O1,4(%2)"
- [(set_attr "type" "multi,multi")
- (set_attr "cc" "none,none")
- (set_attr "length" "8,12")])
-
-(define_expand "reload_outdi"
- [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m")
- (match_operand:DI 1 "" "r"))
- (clobber (match_operand:SI 2 "" "=&b"))])]
- ""
- "")
-
-;; Split symbolic memory operands differently. We first load the address
-;; into a register and then do the two loads or stores. We can only do
-;; this if operand_subword won't produce a SUBREG, which is only when
-;; operands[0] is a hard register. Thus, these won't be used during the
-;; first insn scheduling pass.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "symbolic_memory_operand" ""))]
- "GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "
-{ operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = XEXP (operands[1], 0);
- operands[4] = operand_subword (operands[0], 0, 0, DImode);
- operands[5] = gen_rtx (MEM, SImode, operands[2]);
- operands[6] = operands[2];
- operands[7] = gen_rtx (MEM, SImode,
- gen_rtx (PLUS, SImode, operands[2],
- GEN_INT (4)));
-
- if (operands[2] == 0 || operands[4] == 0)
- FAIL;
-}")
-
-(define_split
- [(set (match_operand:DI 0 "symbolic_memory_operand" "")
- (match_operand:DI 1 "register_operand" ""))
- (clobber (match_operand:SI 2 "register_operand" ""))]
- "GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "
-{ operands[3] = XEXP (operands[0], 0);
- operands[4] = gen_rtx (MEM, SImode, operands[2]);
- operands[5] = operand_subword (operands[1], 0, 0, DImode);
- operands[6] = gen_rtx (MEM, SImode,
- gen_rtx (PLUS, SImode, operands[2],
- GEN_INT (4)));
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
-
- if (operands[5] == 0 || operands[7] == 0)
- FAIL;
-}")
-
-;; If the output is a register and the input is memory, we have to be careful
-;; and see which word needs to be loaded first.
-;;
-;; Note that this case doesn't have a CLOBBER. Therefore, we must either
-;; be after reload or operand[0] must not be a MEM. So we don't need a
-;; CLOBBER on the new insns either.
-;;
-;; Due to a bug in sched.c, we do not want to split this insn if both
-;; operands are registers and they overlap unless reload has completed.
-(define_split
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- "! symbolic_memory_operand (operands[0], DImode)
- && ! symbolic_memory_operand (operands[1], DImode)
- && ! (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
- && ! (GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
- && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
- && ! reload_completed
- && reg_overlap_mentioned_p (operands[0], operands[1]))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "
-{ if (GET_CODE (operands[0]) != REG
- || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- {
- operands[2] = operand_subword (operands[0], 0, 0, DImode);
- operands[3] = operand_subword (operands[1], 0, 0, DImode);
- operands[4] = operand_subword (operands[0], 1, 0, DImode);
- operands[5] = operand_subword (operands[1], 1, 0, DImode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = operand_subword (operands[1], 1, 0, DImode);
- operands[4] = operand_subword (operands[0], 0, 0, DImode);
- operands[5] = operand_subword (operands[1], 0, 0, DImode);
- }
-
- if (operands[2] == 0 || operands[3] == 0
- || operands[4] == 0 || operands[5] == 0)
- FAIL;
-}")
-
-(define_split
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))
- (clobber (match_operand:SI 6 "register_operand" ""))]
- "! symbolic_memory_operand (operands[0], DImode)
- && ! symbolic_memory_operand (operands[1], DImode)
- && ! (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
- && ! (GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
- && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
- && ! reload_completed
- && reg_overlap_mentioned_p (operands[0], operands[1]))"
- [(parallel [(set (match_dup 2) (match_dup 3))
- (clobber (match_dup 7))])
- (parallel [(set (match_dup 4) (match_dup 5))
- (clobber (match_dup 8))])]
- "
-{ if (GET_CODE (operands[0]) != REG
- || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- {
- operands[2] = operand_subword (operands[0], 0, 0, DImode);
- operands[3] = operand_subword (operands[1], 0, 0, DImode);
- operands[4] = operand_subword (operands[0], 1, 0, DImode);
- operands[5] = operand_subword (operands[1], 1, 0, DImode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = operand_subword (operands[1], 1, 0, DImode);
- operands[4] = operand_subword (operands[0], 0, 0, DImode);
- operands[5] = operand_subword (operands[1], 0, 0, DImode);
- }
-
- if (operands[2] == 0 || operands[3] == 0
- || operands[4] == 0 || operands[5] == 0)
- FAIL;
-
- /* We must be sure to make two different SCRATCH operands, since they
- are not allowed to be shared. After reload, however, we only have
- a SCRATCH if we won't use the operand, so it is allowed to share it
- then. */
- if (reload_completed || GET_CODE (operands[6]) != SCRATCH)
- operands[7] = operands[8] = operands[6];
- else
- {
- operands[7] = gen_rtx (SCRATCH, SImode);
- operands[8] = gen_rtx (SCRATCH, SImode);
- }
-}")
-
-;; Define move insns for SF, and DF.
-;;
-;; For register-register copies or a copy of something to itself, emit a
-;; single SET insn since it will likely be optimized away.
-;;
-;; Otherwise, emit a floating-point move operation unless both input and
-;; output are either constant, memory, or a non-floating-point hard register.
-(define_expand "movdf"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "
-{ rtx op0 = operands[0];
- rtx op1 = operands[1];
-
- if (op0 == op1)
- {
- emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
- DONE;
- }
-
- if ((GET_CODE (op0) == MEM
- || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER
- && ! FP_REGNO_P (REGNO (op0))))
- && (GET_CODE (op1) == MEM
- || GET_CODE (op1) == CONST_DOUBLE
- || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER
- && ! FP_REGNO_P (REGNO (op1)) && ! rtx_equal_p (op0, op1))))
- {
- rtx insns;
-
- if (GET_CODE (op1) == CONST_DOUBLE)
- op1 = force_const_mem (DFmode, op1);
-
- start_sequence ();
- if (GET_CODE (operands[0]) != REG
- || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1]), 0)
- {
- emit_move_insn (operand_subword (op0, 0, 1, DFmode),
- operand_subword_force (op1, 0, DFmode));
- emit_move_insn (operand_subword (op0, 1, 1, DFmode),
- operand_subword_force (op1, 1, DFmode));
- }
- else
- {
- emit_move_insn (operand_subword (op0, 1, 1, DFmode),
- operand_subword_force (op1, 1, DFmode));
- emit_move_insn (operand_subword (op0, 0, 1, DFmode),
- operand_subword_force (op1, 0, DFmode));
- }
-
- insns = get_insns ();
- end_sequence ();
-
- emit_no_conflict_block (insns, op0, op1, 0, op1);
- DONE;
- }
-}")
-
-(define_expand "movsf"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "
-{ rtx op0 = operands[0];
- rtx op1 = operands[1];
-
- if (op0 == op1)
- {
- emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
- DONE;
- }
-
- if ((GET_CODE (op0) == MEM
- || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER
- && ! FP_REGNO_P (REGNO (op0))))
- && (GET_CODE (op1) == MEM
- || GET_CODE (op1) == CONST_DOUBLE
- || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER
- && ! FP_REGNO_P (REGNO (op1)))))
- {
- rtx last;
-
- if (GET_CODE (op1) == CONST_DOUBLE)
- op1 = force_const_mem (SFmode, op1);
-
- last = emit_move_insn (operand_subword (op0, 0, 1, SFmode),
- operand_subword_force (op1, 0, SFmode));
-
- REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, op1, REG_NOTES (last));
- DONE;
- }
-}")
-
-;; Define the move insns for SF and DF. Check for all general regs
-;; in the FP insns and make them non-FP if so. Do the same if the input and
-;; output are the same (the insn will be deleted in this case and we don't
-;; want to think there are FP insns when there might not be).
-(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=*frg")
- (match_dup 0))]
- ""
- "nopr r0"
- [(set_attr "type" "address")
- (set_attr "length" "2")])
-
-(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=r,*fr,r,r,Q,m,frg")
- (match_operand:SF 1 "general_operand" "r,0,Q,m,r,r,frg"))
- (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z"))
- (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))]
- ""
- "*
-{ switch (which_alternative)
- {
- case 0:
- return \"cas %0,%1,r0\";
- case 1:
- return \"nopr r0\";
- case 2:
- return \"l%M1 %0,%1\";
- case 3:
- return \"load %0,%1\";
- case 4:
- return \"st%M0 %1,%0\";
- case 5:
- return \"store %1,%0,%3\";
- default:
- return output_fpop (SET, operands[0], operands[1], 0, insn);
- }
-}"
- [(set_attr "type" "address,address,load,load,store,store,fp")
- (set_attr "length" "2,2,*,*,*,*,*")])
-
-(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=*frg")
- (match_dup 0))]
- ""
- "nopr r0"
- [(set_attr "type" "address")
- (set_attr "length" "2")])
-
-(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=r,*fr,r,r,Q,m,frg")
- (match_operand:DF 1 "general_operand" "r,0,Q,m,r,r,*frg"))
- (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z"))
- (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))]
- ""
- "*
-{ switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"cas %O0,%O1,r0\;cas %0,%1,r0\";
- else
- return \"cas %0,%1,r0\;cas %O0,%O1,r0\";
- case 1:
- return \"nopr r0\";
- case 2:
- /* Here we must see which word to load first. We default to the
- low-order word unless it occurs in the address. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"l%M1 %O0,%O1\;l%M1 %0,%1\";
- else
- return \"l%M1 %0,%1\;l%M1 %O0,%O1\";
- case 3:
- return \"get %3,$%1\;ls %0,0(%3)\;ls %O0,4(%3)\";
- case 4:
- return \"st%M0 %1,%0\;st%M0 %O1,%O0\";
- case 5:
- return \"get %3,$%0\;sts %1,0(%3)\;sts %O1,4(%3)\";
- default:
- return output_fpop (SET, operands[0], operands[1], 0, insn);
- }
-}"
- [(set_attr "type" "address,multi,multi,multi,multi,multi,fp")
- (set_attr "length" "2,4,*,*,*,*,*")])
-
-;; Split all the above cases that involve multiple insns and no floating-point
-;; data block. If before reload, we can make a SCRATCH. Otherwise, use
-;; register 15.
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "symbolic_memory_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 16"
- [(set (reg:SI 15) (match_dup 2))
- (set (match_dup 3) (match_dup 4))
- (set (match_dup 5) (match_dup 6))]
- "
-{ operands[2] = XEXP (operands[1], 0);
- operands[3] = operand_subword (operands[0], 0, 0, DFmode);
- operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
- operands[5] = operand_subword (operands[0], 1, 0, DFmode);
- operands[6] = gen_rtx (MEM, SImode,
- gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
- GEN_INT (4)));
-
- if (operands[3] == 0 || operands[5] == 0)
- FAIL;
-}")
-
-(define_split
- [(set (match_operand:DF 0 "symbolic_memory_operand" "")
- (match_operand:DF 1 "register_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 16"
- [(set (reg:SI 15) (match_dup 2))
- (set (match_dup 3) (match_dup 4))
- (set (match_dup 5) (match_dup 6))]
- "
-{ operands[2] = XEXP (operands[0], 0);
- operands[3] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
- operands[4] = operand_subword (operands[1], 0, 0, DFmode);
- operands[5] = gen_rtx (MEM, SImode,
- gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
- GEN_INT (4)));
- operands[6] = operand_subword (operands[1], 1, 0, DFmode);
-
- if (operands[4] == 0 || operands[6] == 0)
- FAIL;
-}")
-
-;; If the output is a register and the input is memory, we have to be careful
-;; and see which word needs to be loaded first. We also cannot to the
-;; split if the input is a constant because it would result in invalid
-;; insns. When the output is a MEM, we must put a CLOBBER on each of the
-;; resulting insn, when it is not a MEM, we must not.
-(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (match_operand:DF 1 "register_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 15"
- [(parallel [(set (match_dup 2) (match_dup 3))
- (clobber (match_dup 6))])
- (parallel [(set (match_dup 4) (match_dup 5))
- (clobber (match_dup 7))])]
- "
-{ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
- operands[3] = operand_subword (operands[1], 0, 0, DFmode);
- operands[4] = operand_subword (operands[0], 1, 0, DFmode);
- operands[5] = operand_subword (operands[1], 1, 0, DFmode);
-
- if (operands[2] == 0 || operands[3] == 0
- || operands[4] == 0 || operands[5] == 0)
- FAIL;
-
- if (reload_completed)
- operands[6] = operands[7] = gen_rtx (REG, SImode, 15);
- else
- {
- operands[6] = gen_rtx (SCRATCH, SImode);
- operands[7] = gen_rtx (SCRATCH, SImode);
- }
-}")
-
-(define_split
- [(set (match_operand:DF 0 "nonmemory_operand" "")
- (match_operand:DF 1 "general_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- "! symbolic_memory_operand (operands[1], DFmode)
- && GET_CODE (operands[1]) != CONST_DOUBLE
- && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15)
- && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15)
- && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
- && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
- && ! reload_completed
- && reg_overlap_mentioned_p (operands[0], operands[1]))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "
-{ if (GET_CODE (operands[0]) != REG
- || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- {
- operands[2] = operand_subword (operands[0], 0, 0, DFmode);
- operands[3] = operand_subword (operands[1], 0, 0, DFmode);
- operands[4] = operand_subword (operands[0], 1, 0, DFmode);
- operands[5] = operand_subword (operands[1], 1, 0, DFmode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, DFmode);
- operands[3] = operand_subword (operands[1], 1, 0, DFmode);
- operands[4] = operand_subword (operands[0], 0, 0, DFmode);
- operands[5] = operand_subword (operands[1], 0, 0, DFmode);
- }
-
- if (operands[2] == 0 || operands[3] == 0
- || operands[4] == 0 || operands[5] == 0)
- FAIL;
-}")
-
-;; Conversions from one integer mode to another.
-;; It is possible sometimes to sign- or zero-extend while fetching from memory.
-;;
-;; First, sign-extensions:
-(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
- ""
- "")
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=b")
- (sign_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))]
- ""
- "loadha %0,%1"
- [(set_attr "type" "load")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,b")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))]
- ""
- "@
- exts %0,%1
- lha%M1 %0,%1
- loadha %0,%1"
- [(set_attr "type" "arith,load,load")
- (set_attr "length" "2,*,*")])
-
-(define_expand "extendqisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "register_operand" "")
- (const_int 24)))
- (set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 24)))]
- ""
- "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode); }")
-
-(define_expand "extendqihi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "register_operand" "")
- (const_int 24)))
- (set (match_operand:HI 0 "register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 24)))]
- ""
- "
-{ operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode); }")
-
-;; Define peepholes to eliminate an instruction when we are doing a sign
-;; extension but cannot clobber the input.
-;;
-;; In this case we will shift left 24 bits, but need a copy first. The shift
-;; can be replaced by a "mc03" instruction, but this can only be done if
-;; followed by the right shift of 24 or more bits.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "")
- (subreg:SI (match_operand:QI 1 "register_operand" "") 0))
- (set (match_dup 0)
- (ashift:SI (match_dup 0)
- (const_int 24)))
- (set (match_dup 0)
- (ashiftrt:SI (match_dup 0)
- (match_operand:SI 2 "const_int_operand" "")))]
- "INTVAL (operands[2]) >= 24"
- "mc03 %0,%1\;sari16 %0,%S2"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "sets")])
-
-;; Now zero extensions:
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
- ""
- "")
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=b")
- (zero_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))]
- ""
- "loadh %0,%1"
- [(set_attr "type" "load")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,b")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))]
- ""
- "@
- nilz %0,%1,65535
- lh%N1 %0,%1
- loadh %0,%1"
- [(set_attr "type" "arith,loadz,load")])
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
- ""
- "")
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=b")
- (zero_extend:SI (match_operand:QI 1 "symbolic_memory_operand" "m")))]
- ""
- "loadc %0,%1"
- [(set_attr "type" "load")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,b")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))]
- ""
- "@
- nilz %0,%1,255
- lc%M1 %0,%1
- loadc %0,%1"
- [(set_attr "type" "arith,load,load")])
-
-(define_expand "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "")
- (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
- ""
- "")
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=b")
- (zero_extend:HI (match_operand:QI 1 "symbolic_memory_operand" "m")))]
- ""
- "loadc %0,%1"
- [(set_attr "type" "load")])
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r,r,b")
- (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))]
- ""
- "@
- nilz %0,%1,255
- lc%M1 %0,%1
- loadc %0,%1"
- [(set_attr "type" "arith,load,load")])
-
-;; Various extract and insertion operations.
-(define_expand "extzv"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
- FAIL;
-
- if (GET_CODE (operands[3]) != CONST_INT)
- FAIL;
-
- if (INTVAL (operands[3]) != 0 && INTVAL (operands[3]) != 8
- && INTVAL (operands[3]) != 16 && INTVAL (operands[3]) != 24)
- FAIL;
-}")
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=&r")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 8)
- (match_operand:SI 2 "const_int_operand" "n")))]
- "(INTVAL (operands[2]) & 7) == 0"
- "lis %0,0\;mc3%B2 %0,%1"
- [(set_attr "type" "multi")
- (set_attr "cc" "change0")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "=&r")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 8)
- (match_operand:SI 2 "const_int_operand" "n")))]
- "(INTVAL (operands[2]) & 7) == 0"
- [(set (match_dup 0) (const_int 0))
- (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 24))
- (zero_extract:SI (match_dup 1) (const_int 8) (match_dup 2)))]
- "")
-
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
- (const_int 8)
- (const_int 24))
- (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 8)
- (match_operand:SI 2 "const_int_operand" "n")))]
- "(INTVAL (operands[2]) & 7) == 0"
- "mc3%B2 %0,%1"
- [(set_attr "type" "address")
- (set_attr "length" "2")])
-
-(define_expand "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "const_int_operand" ""))
- (match_operand:SI 3 "register_operand" ""))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- FAIL;
-
- if (GET_CODE (operands[1]) != CONST_INT)
- FAIL;
-
- if (INTVAL (operands[1]) == 1)
- {
- emit_insn (gen_bit_insv (operands[0], operands[1], operands[2],
- operands[3]));
- DONE;
- }
- else if (INTVAL (operands[1]) == 8
- && (INTVAL (operands[2]) % 8 == 0))
- ; /* Accept aligned byte-wide field. */
- else
- FAIL;
-}")
-
-;; For a single-bit insert, it is better to explicitly generate references
-;; to the T bit. We will call the T bit "CC0" because it can be clobbered
-;; by some CC0 sets (single-bit tests).
-
-(define_expand "bit_insv"
- [(set (cc0)
- (zero_extract:SI (match_operand:SI 3 "register_operand" "")
- (const_int 1)
- (const_int 31)))
- (parallel [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "const_int_operand" ""))
- (ne (cc0) (const_int 0)))
- (clobber (match_scratch:SI 4 ""))])]
- ""
- "")
-
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
- (const_int 8)
- (match_operand:SI 1 "const_int_operand" "n"))
- (match_operand:SI 2 "register_operand" "r"))]
- "(INTVAL (operands[1]) & 7) == 0"
- "mc%B1%.3 %0,%2"
- [(set_attr "type" "address")
- (set_attr "length" "2")])
-
-;; This pattern cannot have any input reloads since if references CC0.
-;; So we have to add code to support memory, which is the only other
-;; thing that a "register_operand" can become. There is still a problem
-;; if the address isn't valid and *it* needs a reload, but there is no
-;; way to solve that problem, so let's hope it never happens.
-
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,m")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n,m"))
- (ne (cc0) (const_int 0)))
- (clobber (match_scratch:SI 2 "=X,b"))]
- ""
- "@
- mftbi%t1 %0,%S1
- l%M0 %2,%0\;mftb%t1 %2,%S1\;st%M0 %2,%0"
- [(set_attr "type" "*,multi")
- (set_attr "cc" "none,none")
- (set_attr "length" "2,10")])
-
-;; Arithmetic instructions. First, add and subtract.
-;;
-;; It may be that the second input is either large or small enough that
-;; the operation cannot be done in a single insn. In that case, emit two.
-(define_expand "addsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000
- && (INTVAL (operands[2]) & 0xffff) != 0)
- {
- int low = INTVAL (operands[2]) & 0xffff;
- int high = (unsigned) INTVAL (operands[2]) >> 16;
-
- if (low & 0x8000)
- high++, low |= 0xffff0000;
-
- emit_insn (gen_addsi3 (operands[0], operands[1],
- GEN_INT (high << 16)));
- operands[1] = operands[0];
- operands[2] = GEN_INT (low);
- }
-}")
-
-;; Put the insn to add a symbolic constant to a register separately to
-;; improve register allocation since it has different register requirements.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=b")
- (plus:SI (match_operand:SI 1 "register_operand" "%b")
- (match_operand:SI 2 "romp_symbolic_operand" "s")))]
- ""
- "get %0,$%2(%1)"
- [(set_attr "type" "address")
- (set_attr "length" "8")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,b")
- (plus:SI (match_operand:SI 1 "reg_or_add_operand" "%0,0,r,b,0,r,b")
- (match_operand:SI 2 "reg_or_add_operand" "I,J,K,M,r,b,s")))]
- "register_operand (operands[1], SImode)
- || register_operand (operands[2], SImode)"
- "@
- ais %0,%2
- sis %0,%n2
- ail %0,%1,%2
- cau %0,%H2(%1)
- a %0,%2
- cas %0,%1,%2
- get %0,$%2(%1)"
- [(set_attr "type" "arith,arith,arith,address,arith,address,misc")
- (set_attr "length" "2,2,4,4,2,2,8")])
-
-;; Now subtract.
-;;
-;; 1. If third operand is constant integer, convert it to add of the negative
-;; of that integer.
-;; 2. If the second operand is not a valid constant integer, force it into a
-;; register.
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "reg_or_any_cint_operand" "")
- (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands [2]) == CONST_INT)
- {
- emit_insn (gen_addsi3 (operands[0], operands[1],
- GEN_INT (- INTVAL (operands[2]))));
- DONE;
- }
- else
- operands[2] = force_reg (SImode, operands[2]);
-
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000)
- operands[1] = force_reg (SImode, operands[1]);
-}")
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (minus:SI (match_operand:SI 1 "reg_or_D_operand" "K,0,r")
- (match_operand:SI 2 "register_operand" "r,r,0")))]
- ""
- "@
- sfi %0,%2,%1
- s %0,%2
- sf %0,%1"
- [(set_attr "length" "4,2,2")])
-
-;; Multiply either calls a special RT routine or is done in-line, depending
-;; on the value of a -m flag.
-;;
-;; First define the way we call the subroutine.
-(define_expand "mulsi3_subr"
- [(set (reg:SI 2) (match_operand:SI 1 "register_operand" ""))
- (set (reg:SI 3) (match_operand:SI 2 "register_operand" ""))
- (parallel [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])
- (set (match_operand:SI 0 "register_operand" "")
- (reg:SI 2))]
- ""
- "")
-
-(define_expand "mulsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (mult:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))]
- ""
- "
-{
- if (! TARGET_IN_LINE_MUL)
- {
- emit_insn (gen_mulsi3_subr (operands[0], operands[1], operands[2]));
- DONE;
- }
-}")
-
-;; Define the patterns to match.
-;; We would like to provide a delay slot for the insns that call internal
-;; routines, but doing so is risky since reorg will think that the use of
-;; r2 and r3 is completed in the insn needing the delay slot. Also, it
-;; won't know that the cc will be clobbered. So take the safe approach
-;; and don't give them delay slots.
-(define_insn ""
- [(set (reg:SI 2)
- (mult:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- "! TARGET_IN_LINE_MUL"
- "bali%# r15,lmul$$"
- [(set_attr "type" "misc")
- (set_attr "in_delay_slot" "no")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=&r")
- (mult:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "register_operand" "r")))]
- "TARGET_IN_LINE_MUL"
- "*
-{ return output_in_line_mul (); }"
- [(set_attr "length" "38")
- (set_attr "type" "multi")])
-
-;; Handle divide and modulus. The same function returns both values,
-;; so use divmodsi4. This divides arg 1 by arg 2 with quotient to go
-;; into arg 0 and remainder in arg 3.
-;;
-;; We want to put REG_EQUAL notes for the two outputs. So we need a
-;; function to do everything else.
-(define_expand "divmodsi4_doit"
- [(set (reg:SI 2)
- (match_operand:SI 0 "register_operand" ""))
- (set (reg:SI 3)
- (match_operand:SI 1 "register_operand" ""))
- (parallel [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3)))
- (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "divmodsi4"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (div:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (set (match_operand:SI 3 "register_operand" "")
- (mod:SI (match_dup 1) (match_dup 2)))])]
- ""
- "
-{
- rtx insn;
-
- emit_insn (gen_divmodsi4_doit (operands[1], operands[2]));
- insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (DIV, SImode, operands[1],
- operands[2]),
- REG_NOTES (insn));
- insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (MOD, SImode, operands[1],
- operands[2]),
- REG_NOTES (insn));
- DONE;
-}")
-
-(define_insn ""
- [(set (reg:SI 2)
- (div:SI (reg:SI 2) (reg:SI 3)))
- (set (reg:SI 3)
- (mod:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- ""
- "bali%# r15,ldiv$$"
- [(set_attr "type" "misc")
- (set_attr "in_delay_slot" "no")])
-
-;; Similarly for unsigned divide.
-(define_expand "udivmodsi4_doit"
- [(set (reg:SI 2)
- (match_operand:SI 0 "register_operand" ""))
- (set (reg:SI 3)
- (match_operand:SI 1 "register_operand" ""))
- (parallel [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3)))
- (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "udivmodsi4"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (udiv:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (set (match_operand:SI 3 "register_operand" "")
- (umod:SI (match_dup 1) (match_dup 2)))])]
- ""
- "
-{
- rtx insn;
-
- emit_insn (gen_udivmodsi4_doit (operands[1], operands[2]));
- insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (UDIV, SImode, operands[1],
- operands[2]),
- REG_NOTES (insn));
- insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (UMOD, SImode, operands[1],
- operands[2]),
- REG_NOTES (insn));
- DONE;
-}")
-
-(define_insn ""
- [(set (reg:SI 2)
- (udiv:SI (reg:SI 2) (reg:SI 3)))
- (set (reg:SI 3)
- (umod:SI (reg:SI 2) (reg:SI 3)))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))]
- ""
- "bali%# r15,uldiv$$"
- [(set_attr "type" "misc")
- (set_attr "in_delay_slot" "no")])
-
-;; Define DImode arithmetic operations.
-;;
-;; It is possible to do certain adds and subtracts with constants in a single
-;; insn, but it doesn't seem worth the trouble.
-;;
-;; Don't use DEFINE_SPLIT on these because the dependency on CC can't be
-;; easily tracked in that case!
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "register_operand" "r")))]
- ""
- "a %O0,%O2\;ae %0,%2"
- [(set_attr "type" "multi")])
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "register_operand" "r")))]
- ""
- "s %O0,%O2\;se %0,%2"
- [(set_attr "type" "multi")])
-
-(define_insn "negdi2"
- [(set (match_operand:DI 0 "register_operand" "=r,&r")
- (neg:DI (match_operand:DI 1 "register_operand" "0,r")))]
- ""
- "twoc %O0,%O1\;onec %0,%1\;aei %0,%0,0"
- [(set_attr "type" "multi")
- (set_attr "length" "8")])
-
-;; Unary arithmetic operations.
-(define_insn "abssi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (abs:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "abs %0,%1"
- [(set_attr "length" "2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "twoc %0,%1"
- [(set_attr "length" "2")])
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "onec %0,%1"
- [(set_attr "length" "2")])
-
-
-;; Logical insns: AND, IOR, and XOR
-;;
-;; If the operation is being performed on a 32-bit constant such that
-;; it cannot be done in one insn, do it in two. We may lose a bit on
-;; CSE in pathological cases, but it seems better doing it this way.
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (and:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int top = (unsigned) INTVAL (operands[2]) >> 16;
- int bottom = INTVAL (operands[2]) & 0xffff;
-
- if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff)
- {
- emit_insn (gen_andsi3 (operands[0], operands[1],
- GEN_INT ((top << 16) | 0xffff)));
- operands[1] = operands[0];
- operands[2] = GEN_INT (0xffff0000 | bottom);
- }
- }
-}");
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (and:SI (match_operand:SI 1 "reg_or_and_operand" "%0,r,0")
- (match_operand:SI 2 "reg_or_and_operand" "P,LMO,r")))]
- "register_operand (operands[1], SImode)
- || register_operand (operands[2], SImode)"
- "@
- clrb%k2 %0,%b2
- ni%z2 %0,%1,%Z2
- n %0,%2"
- [(set_attr "length" "2,4,2")])
-
-;; logical OR (IOR)
-(define_expand "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ior:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int top = (unsigned) INTVAL (operands[2]) >> 16;
- int bottom = INTVAL (operands[2]) & 0xffff;
-
- if (top != 0 && bottom != 0)
- {
- emit_insn (gen_iorsi3 (operands[0], operands[1],
- GEN_INT ((top << 16))));
- operands[1] = operands[0];
- operands[2] = GEN_INT (bottom);
- }
- }
-}");
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (ior:SI (match_operand:SI 1 "reg_or_cint_operand" "%0,r,0")
- (match_operand:SI 2 "reg_or_cint_operand" "N,LM,r")))]
- "register_operand (operands[1], SImode)
- || register_operand (operands[2], SImode)"
- "@
- setb%h2 %0,%b2
- oi%h2 %0,%1,%H2
- o %0,%2"
- [(set_attr "length" "2,4,2")])
-
-;; exclusive-or (XOR)
-(define_expand "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (xor:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int top = (unsigned) INTVAL (operands[2]) >> 16;
- int bottom = INTVAL (operands[2]) & 0xffff;
-
- if (top == 0xffff && bottom == 0xffff)
- {
- emit_insn (gen_one_cmplsi2 (operands[0], operands[1]));
- DONE;
- }
- else if (top != 0 && bottom != 0)
- {
- emit_insn (gen_xorsi3 (operands[0], operands[1],
- GEN_INT ((top << 16))));
- operands[1] = operands[0];
- operands[2] = GEN_INT (bottom);
- }
- }
-}");
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (xor:SI (match_operand:SI 1 "reg_or_cint_operand" "%r,0")
- (match_operand:SI 2 "reg_or_cint_operand" "LM,r")))]
- "register_operand (operands[1], SImode)
- || register_operand (operands[2], SImode)"
- "@
- xi%h2 %0,%1,%H2
- x %0,%2"
- [(set_attr "length" "4,2")])
-
-;; Various shift insns
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
- ""
- "@
- sar %0,%2
- sari%s2 %0,%S2"
- [(set_attr "length" "2")])
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
- ""
- "@
- sr %0,%2
- sri%s2 %0,%S2"
- [(set_attr "length" "2")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ashift:SI (match_operand:SI 1 "register_operand" "b")
- (const_int 1)))]
- ""
- "cas %0,%1,%1"
- [(set_attr "length" "2")
- (set_attr "type" "address")])
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
- ""
- "@
- sl %0,%2
- sli%s2 %0,%S2"
- [(set_attr "length" "2")])
-
-;; Function call insns:
-;;
-;; On the ROMP, &fcn is actually a pointer to the data area, which is passed
-;; to the function in r0. &.fcn is the actual starting address of the
-;; function. Also, the word at &fcn contains &.fcn.
-;;
-;; For both functions that do and don't return values, there are two cases:
-;; where the function's address is a constant, and where it isn't.
-;;
-;; Operand 1 (2 for `call_value') is the number of arguments and is not used.
-(define_expand "call"
- [(use (match_operand:SI 0 "address_operand" ""))
- (use (match_operand 1 "" ""))]
- ""
- "
-{
- rtx reg0 = gen_rtx (REG, SImode, 0);
- rtx call_insn;
-
- if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
- abort();
-
- operands[0] = XEXP (operands[0], 0);
- if (GET_CODE (operands[0]) == SYMBOL_REF)
- {
- extern rtx get_symref ();
- char *real_fcnname =
- (char *) alloca (strlen (XSTR (operands[0], 0)) + 2);
-
- /* Copy the data area address to r0. */
- emit_move_insn (reg0, force_reg (SImode, operands[0]));
- strcpy (real_fcnname, \".\");
- strcat (real_fcnname, XSTR (operands[0], 0));
- operands[0] = get_symref (real_fcnname);
- }
- else
- {
- rtx data_access;
-
- emit_move_insn (reg0, force_reg (SImode, operands[0]));
- data_access = gen_rtx (MEM, SImode, operands[0]);
- RTX_UNCHANGING_P (data_access) = 1;
- operands[0] = copy_to_reg (data_access);
- }
-
- call_insn = emit_call_insn (gen_call_internal (operands[0], operands[1]));
- use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0);
- DONE;
-}")
-
-(define_insn "call_internal"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
- (match_operand 1 "" "g"))
- (clobber (reg:SI 15))]
- ""
- "balr%# r15,%0"
- [(set_attr "type" "call")
- (set_attr "length" "2")])
-
-(define_insn ""
- [(call (mem:SI (match_operand:SI 0 "romp_symbolic_operand" "i"))
- (match_operand 1 "" "g"))
- (clobber (reg:SI 15))]
- "GET_CODE (operands[0]) == SYMBOL_REF"
- "bali%# r15,%0"
- [(set_attr "type" "call")])
-
-;; Call a function and return a value.
-(define_expand "call_value"
- [(use (match_operand 0 "" ""))
- (use (match_operand:SI 1 "address_operand" ""))
- (use (match_operand 2 "" ""))]
- ""
- "
-{
- rtx reg0 = gen_rtx (REG, SImode, 0);
- rtx call_insn;
-
- if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
- abort();
-
- operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[1]) == SYMBOL_REF)
- {
- extern rtx get_symref ();
- char *real_fcnname =
- (char *) alloca (strlen (XSTR (operands[1], 0)) + 2);
-
- /* Copy the data area address to r0. */
- emit_move_insn (reg0,force_reg (SImode, operands[1]));
- strcpy (real_fcnname, \".\");
- strcat (real_fcnname, XSTR (operands[1], 0));
- operands[1] = get_symref (real_fcnname);
- }
- else
- {
- rtx data_access;
-
- emit_move_insn (reg0,force_reg (SImode, operands[1]));
- data_access = gen_rtx (MEM, SImode, operands[1]);
- RTX_UNCHANGING_P (data_access) = 1;
- operands[1] = copy_to_reg (data_access);
- }
-
- call_insn = emit_call_insn (gen_call_value_internal (operands[0],
- operands[1],
- operands[2]));
- use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0);
- DONE;
-}")
-
-(define_insn "call_value_internal"
- [(set (match_operand 0 "" "=fg")
- (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
- (match_operand 2 "" "g")))
- (clobber (reg:SI 15))]
- ""
- "balr%# r15,%1"
- [(set_attr "length" "2")
- (set_attr "type" "call")])
-
-(define_insn ""
- [(set (match_operand 0 "" "=fg")
- (call (mem:SI (match_operand:SI 1 "romp_symbolic_operand" "i"))
- (match_operand 2 "" "g")))
- (clobber (reg:SI 15))]
- "GET_CODE (operands[1]) == SYMBOL_REF"
- "bali%# r15,%1"
- [(set_attr "type" "call")])
-
-;; 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)]
- ""
- "")
-
-;; No operation insn.
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nopr r0"
- [(set_attr "type" "address")
- (set_attr "length" "2")
- (set_attr "cc" "none")])
-
-;; Here are the floating-point operations.
-;;
-;; Start by providing DEFINE_EXPAND for each operation.
-;; The insns will be handled with MATCH_OPERATOR; the methodology will be
-;; discussed below.
-
-;; First the conversion operations.
-
-(define_expand "truncdfsf2"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (float_truncate:SF (match_operand:DF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "extendsfdf2"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (float_extend:DF (match_operand:SF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "floatsisf2"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (float:SF (match_operand:SI 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "floatsidf2"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (float:DF (match_operand:SI 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "fix_truncsfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI (match_operand:SF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "fix_truncdfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI (match_operand:DF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-;; Now the binary operations.
-
-(define_expand "addsf3"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (plus:SF (match_operand:SF 1 "general_operand" "")
- (match_operand:SF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "adddf3"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (plus:DF (match_operand:DF 1 "general_operand" "")
- (match_operand:DF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "subsf3"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (minus:SF (match_operand:SF 1 "general_operand" "")
- (match_operand:SF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "subdf3"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (minus:DF (match_operand:DF 1 "general_operand" "")
- (match_operand:DF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "mulsf3"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (mult:SF (match_operand:SF 1 "general_operand" "")
- (match_operand:SF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "muldf3"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (mult:DF (match_operand:DF 1 "general_operand" "")
- (match_operand:DF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "divsf3"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (div:SF (match_operand:SF 1 "general_operand" "")
- (match_operand:SF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "divdf3"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (div:DF (match_operand:DF 1 "general_operand" "")
- (match_operand:DF 2 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-;; Unary floating-point operations.
-;;
-;; Negations can be done without floating-point, since this is IEEE.
-;; But we cannot do this if an operand is a hard FP register, since
-;; the SUBREG we create would not be valid.
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))]
- ""
- "
-{
- if (! (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
- && FP_REGNO_P (REGNO (operands[0])))
- && ! (GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
- && FP_REGNO_P (REGNO (operands[1]))))
- {
- rtx result;
- rtx target = operand_subword (operands[0], 0, 1, SFmode);
-
- result = expand_binop (SImode, xor_optab,
- operand_subword_force (operands[1], 0, SFmode),
- GEN_INT (0x80000000),
- target, 0, OPTAB_WIDEN);
- if (result == 0)
- abort ();
-
- if (result != target)
- emit_move_insn (result, target);
-
- /* Make a place for REG_EQUAL. */
- emit_move_insn (operands[0], operands[0]);
- DONE;
- }
-}")
-
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))]
- ""
- "
-{
- if (! (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
- && FP_REGNO_P (REGNO (operands[0])))
- && ! (GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
- && FP_REGNO_P (REGNO (operands[1]))))
- {
- rtx result;
- rtx target = operand_subword (operands[0], 0, 1, DFmode);
- rtx insns;
-
- start_sequence ();
- result = expand_binop (SImode, xor_optab,
- operand_subword_force (operands[1], 0, DFmode),
- GEN_INT (0x80000000),
- target, 0, OPTAB_WIDEN);
- if (result == 0)
- abort ();
-
- if (result != target)
- emit_move_insn (result, target);
-
- emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
- operand_subword_force (operands[1], 1, DFmode));
-
- insns = get_insns ();
- end_sequence ();
-
- emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
- DONE;
- }
-}")
-
-(define_expand "abssf2"
- [(parallel [(set (match_operand:SF 0 "general_operand" "")
- (abs:SF (match_operand:SF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "absdf2"
- [(parallel [(set (match_operand:DF 0 "general_operand" "")
- (abs:DF (match_operand:DF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-;; Any floating-point operation can be either SFmode or DFmode, and each
-;; operand (including the output) can be either a normal operand or a
-;; conversion from a normal operand.
-;;
-;; We use MATCH_OPERATOR to match a floating-point binary or unary operator
-;; and input and output conversions. So we need 2^N patterns for each type
-;; of operation, where N is the number of operands, including the output.
-;; There are thus a total of 14 patterns, 8 for binary operations, 4 for
-;; unary operations and two for conversion/move operations (only one
-;; operand can have a conversion for move operations). In addition, we have
-;; to be careful that a floating-point reload register doesn't get allocated
-;; for an integer. We take care of this for inputs with PREFERRED_RELOAD_CLASS
-;; but need to have two different constraints for outputs. This means that
-;; we have to duplicate each pattern where the output could be an integer.
-;; This adds another 7 patterns, for a total of 21.
-
-;; Start with conversion operations (moves are done above).
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operand 2 "general_operand" "frg")]))
- (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (SET, operands[0], operands[2], 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operand 2 "general_operand" "frg")]))
- (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (SET, operands[0], operands[2], 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-;; Next, binary floating-point operations.
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_binary"
- [(match_operand 2 "general_operand" "frg")
- (match_operand 3 "general_operand" "frg")]))
- (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[2], operands[3])"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0],
- operands[2], operands[3], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_binary"
- [(match_operand 2 "general_operand" "frg")
- (match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[2], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0],
- operands[2], operands[4], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_binary"
- [(match_operator 2 "float_conversion"
- [(match_operand 3 "general_operand" "frg")])
- (match_operand 4 "general_operand" "frg")]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[3], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0],
- operands[3], operands[4], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_binary"
- [(match_operator 2 "float_conversion"
- [(match_operand 3 "general_operand" "frg")])
- (match_operator 4 "float_conversion"
- [(match_operand 5 "general_operand" "frg")])]))
- (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[3], operands[5])"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0],
- operands[3], operands[5], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operand 3 "general_operand" "frg")
- (match_operand 4 "general_operand" "frg")])]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[3], operands[4], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operand 3 "general_operand" "frg")
- (match_operand 4 "general_operand" "frg")])]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[3], operands[4], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operand 3 "general_operand" "frg")
- (match_operator 4 "float_conversion"
- [(match_operand 5 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[3], operands[5], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operand 3 "general_operand" "frg")
- (match_operator 4 "float_conversion"
- [(match_operand 5 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[3], operands[5], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])
- (match_operand 5 "general_operand" "frg")])]))
- (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], operands[5])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[4], operands[5], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])
- (match_operand 5 "general_operand" "frg")])]))
- (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], operands[5])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[4], operands[5], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])
- (match_operator 5 "float_conversion"
- [(match_operand 6 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 7 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], operands[6])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[4], operands[6], insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_binary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])
- (match_operator 5 "float_conversion"
- [(match_operand 6 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 7 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], operands[6])"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0],
- operands[4], operands[6], insn);
-}"
- [(set_attr "type" "fp")])
-
-;; Unary floating-point operations.
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_unary"
- [(match_operand 2 "general_operand" "frg")]))
- (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[2], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0], operands[2],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_unary"
- [(match_operator 2 "float_conversion"
- [(match_operand 3 "general_operand" "frg")])]))
- (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[1]), operands[3], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[1]), operands[0], operands[3],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_unary"
- [(match_operand 3 "general_operand" "frg")])]))
- (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[3],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_unary"
- [(match_operand 3 "general_operand" "frg")])]))
- (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[3], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[3],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_unary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[4],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand 0 "general_operand" "=frg")
- (match_operator 1 "float_conversion"
- [(match_operator 2 "float_unary"
- [(match_operator 3 "float_conversion"
- [(match_operand 4 "general_operand" "frg")])])]))
- (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
- "check_precision (GET_MODE (operands[2]), operands[4], 0)"
- "*
-{ return output_fpop (GET_CODE (operands[2]), operands[0], operands[4],
- 0, insn);
-}"
- [(set_attr "type" "fp")])
-
-;; Compare insns are next. Note that the ROMP has two types of compares,
-;; signed & unsigned, and one type of branch. Use the routine
-;; `next_insn_tests_no_unsigned' to see which type to use.
-(define_expand "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "register_operand" "r"))]
- ""
- "")
-
-(define_expand "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "reg_or_cint_operand" "")))]
- ""
- "")
-
-;; Signed compare, `test' first.
-
-(define_insn ""
- [(set (cc0)
- (match_operand:SI 0 "register_operand" "r"))]
- "next_insn_tests_no_unsigned (insn)"
- "cis %0,0"
- [(set_attr "length" "2")
- (set_attr "type" "compare")])
-
-(define_insn ""
- [(set (cc0) (match_operand:SI 0 "register_operand" "r,r,r"))
- (set (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "=0,r,Q")
- (match_dup 0))]
- "next_insn_tests_no_unsigned (insn)"
- "@
- cis %1,0
- nilo %1,%0,65535
- st%M1 %0,%1\;cis %0,0"
- [(set_attr "type" "compare,compare,store")
- (set_attr "length" "2,4,6")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "reg_or_cint_operand" "I,K,r")))]
- "next_insn_tests_no_unsigned (insn)"
- "@
- cis %0,%1
- cil %0,%1
- c %0,%1"
- [(set_attr "length" "2,4,2")
- (set_attr "type" "compare")])
-
-;; Unsigned comparisons, `test' first, again.
-(define_insn ""
- [(set (cc0)
- (match_operand:SI 0 "register_operand" "r"))]
- "! next_insn_tests_no_unsigned (insn)"
- "clil %0,0"
- [(set_attr "type" "compare")])
-
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "reg_or_cint_operand" "K,r")))]
- "! next_insn_tests_no_unsigned (insn)"
- "@
- clil %0,%1
- cl %0,%1"
- [(set_attr "length" "4,2")
- (set_attr "type" "compare")])
-
-;; Bit test insn. Many cases are converted into this by combine. This
-;; uses the ROMP test bit.
-
-(define_insn ""
- [(set (cc0)
- (zero_extract (match_operand:SI 0 "register_operand" "r,r")
- (const_int 1)
- (match_operand:SI 1 "reg_or_any_cint_operand" "r,n")))]
- "next_insn_tests_no_inequality (insn)"
- "@
- mttb %0,%1
- mttbi%t1 %0,%S1"
- [(set_attr "length" "2")
- (set_attr "type" "compare")
- (set_attr "cc" "tbit")])
-
-;; Floating-point comparisons. There are two, equality and order.
-;; The difference will be that a trap for NaN will be given on the orderr
-;; comparisons only.
-
-(define_expand "cmpsf"
- [(parallel [(set (cc0) (compare (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "cmpdf"
- [(parallel [(set (cc0) (compare (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" "")))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "tstsf"
- [(parallel [(set (cc0) (match_operand:SF 0 "general_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-(define_expand "tstdf"
- [(parallel [(set (cc0) (match_operand:DF 0 "general_operand" ""))
- (clobber (reg:SI 0))
- (clobber (reg:SI 15))])]
- ""
- "")
-
-;; There are four cases for compare and two for test. These correspond
-;; to each input having a floating-point conversion or not.
-
-(define_insn ""
- [(set (cc0) (compare (match_operand 0 "general_operand" "frg")
- (match_operand 1 "general_operand" "frg")))
- (clobber (match_operand:SI 2 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))]
- "GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode"
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[0], operands[1], 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0) (compare (match_operand 0 "general_operand" "frg")
- (match_operator 1 "float_conversion"
- [(match_operand 2 "general_operand" "frg")])))
- (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[0], operands[2], 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0) (compare (match_operator 0 "float_conversion"
- [(match_operand 1 "general_operand" "frg")])
- (match_operand 2 "general_operand" "frg")))
- (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[1], operands[2], 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0) (compare (match_operator 0 "float_conversion"
- [(match_operand 1 "general_operand" "frg")])
- (match_operator 2 "float_conversion"
- [(match_operand 3 "general_operand" "frg")])))
- (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[1], operands[3], 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0) (match_operand 0 "general_operand" "frg"))
- (clobber (match_operand:SI 1 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 2 "reg_15_operand" "=&t"))]
- "GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode"
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[0], CONST0_RTX (GET_MODE (operands[0])),
- 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-(define_insn ""
- [(set (cc0) (match_operator 0 "float_conversion"
- [(match_operand 1 "general_operand" "frg")]))
- (clobber (match_operand:SI 2 "reg_0_operand" "=&z"))
- (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))]
- ""
- "*
-{ return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
- operands[1], CONST0_RTX (GET_MODE (operands[1])),
- 0, insn);
-}"
- [(set_attr "type" "fp")
- (set_attr "cc" "compare")])
-
-;; Branch insns. Unsigned vs. signed have already
-;; been taken care of. The only insns that need to be concerned about the
-;; test bit are beq and bne because the rest are either always true,
-;; always false, or converted to EQ or NE.
-
-;; For conditional branches, we use `define_expand' and just have two patterns
-;; that match them. Operand printing does most of the work.
-
-(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 "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)))]
- ""
- "")
-
-(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 "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 "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 both directions of branch and return.
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (restore_compare_p (operands[1]))
- return 0;
- else if (get_attr_length (insn) == 2)
- return \"j%j1 %l0\";
- else
- return \"b%j1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(cc0) (const_int 0)])
- (return)
- (pc)))]
- "null_epilogue ()"
- "*
-{
- if (restore_compare_p (operands[0]))
- return 0;
- else
- return \"b%j0r%# r15\";
-}"
- [(set_attr "type" "return")])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (restore_compare_p (operands[1]))
- return 0;
- else if (get_attr_length (insn) == 2)
- return \"j%J1 %l0\";
- else
- return \"b%J1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (return)))]
- "null_epilogue ()"
- "*
-{
- if (restore_compare_p (operands[0]))
- return 0;
- else
- return \"b%J0r%# r15\";
-}"
- [(set_attr "type" "return")])
-
-;; Unconditional branch and return.
-
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "*
-{
- if (get_attr_length (insn) == 2)
- return \"j %l0\";
- else
- return \"b%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-(define_insn "return"
- [(return)]
- "null_epilogue ()"
- "br%# r15"
- [(set_attr "type" "return")])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
- ""
- "br%# %0"
- [(set_attr "type" "ibranch")])
-
-;; Table jump for switch statements:
-(define_insn "tablejump"
- [(set (pc)
- (match_operand:SI 0 "register_operand" "r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "br%# %0"
- [(set_attr "type" "ibranch")])
diff --git a/gcc/config/romp/x-mach b/gcc/config/romp/x-mach
deleted file mode 100755
index a181e1b..0000000
--- a/gcc/config/romp/x-mach
+++ /dev/null
@@ -1,5 +0,0 @@
-# Ensure that CPATH is used and suppress lots of warnings.
-CC=hc2 -Hcpp -w
-
-# The default `make' on the RT doesn't define MAKE, so do it here.
-MAKE=make
diff --git a/gcc/config/romp/x-romp b/gcc/config/romp/x-romp
deleted file mode 100755
index 82f9e64..0000000
--- a/gcc/config/romp/x-romp
+++ /dev/null
@@ -1,11 +0,0 @@
-# obstack.h assumes that if __STDC__ is defined an ANSI C preprocessor is
-# being used. -Hnocpp makes hc use its builtin preprocessor instead of
-# /lib/cpp. gcc doesn't use <sys/ioctl.h>, so it doesn't matter whether
-# fixincludes has been run.
-#
-# hc's warnings do nothing but obscure the output, hence the -w.
-#
-CC=hc -Hnocpp -w -U__STDC__
-
-# The default `make' on the RT doesn't define MAKE, so do it here.
-MAKE=make
diff --git a/gcc/config/romp/xm-romp.h b/gcc/config/romp/xm-romp.h
deleted file mode 100755
index 37de6de..0000000
--- a/gcc/config/romp/xm-romp.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Configuration for GNU C-compiler for IBM RT PC.
- Copyright (C) 1989, 1991, 1993 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
-/* This describes the machine the compiler is hosted on. */
-#define HOST_BITS_PER_CHAR 8
-#define HOST_BITS_PER_SHORT 16
-#define HOST_BITS_PER_INT 32
-#define HOST_BITS_PER_LONG 32
-#define HOST_BITS_PER_LONGLONG 64
-
-#define HOST_WORDS_BIG_ENDIAN
-
-/* target machine dependencies.
- tm.h is a symbolic link to the actual target specific file. */
-#include "tm.h"
-
-/* Arguments to use with `exit'. */
-#define SUCCESS_EXIT_CODE 0
-#define FATAL_EXIT_CODE 33
-
-/* If compiled with hc, use the built-in alloca and memcpy.
- These definitions assume hc version 2. */
-#ifdef __HIGHC__
-#define alloca _Alloca
-#define bcopy(s,d,l) memcpy(d,s,l)
-#define FUNCTION_CONVERSION_BUG
-#endif
-
-/* We cannot allow cccp.o to contain a copy of BCOPY as this will
- cause multiple definitions since BLT and BCOPY share an object file
- in libc.a and the library references BLT. */
-#define BSTRING