summaryrefslogtreecommitdiff
path: root/gcc/config/c4x
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/c4x')
-rwxr-xr-xgcc/config/c4x/c4x.c4341
-rwxr-xr-xgcc/config/c4x/c4x.h2671
-rwxr-xr-xgcc/config/c4x/c4x.md6877
-rwxr-xr-xgcc/config/c4x/libgcc.S1501
-rwxr-xr-xgcc/config/c4x/t-c4x22
-rwxr-xr-xgcc/config/c4x/xm-c4x.h21
6 files changed, 0 insertions, 15433 deletions
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
deleted file mode 100755
index abbfba1..0000000
--- a/gcc/config/c4x/c4x.c
+++ /dev/null
@@ -1,4341 +0,0 @@
-/* Subroutines for assembler code output on the TMS320C[34]x
- Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
-
- Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
- and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* Some output-actions in c4x.md need these. */
-#include "config.h"
-#include "system.h"
-#include "toplev.h"
-#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "real.h"
-#include "insn-config.h"
-#include "insn-attr.h"
-#include "insn-codes.h"
-#include "conditions.h"
-#include "insn-flags.h"
-#include "output.h"
-#include "tree.h"
-#include "expr.h"
-#include "flags.h"
-#include "loop.h"
-#include "recog.h"
-#include "c-tree.h"
-
-static int c4x_leaf_function;
-
-static char *float_reg_names[] = FLOAT_REGISTER_NAMES;
-
-/* Array of the smallest class containing reg number REGNO, indexed by
- REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these
- registers are available and set the class to NO_REGS for registers
- that the target switches say are unavailable. */
-
-enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] =
-{
- /* Reg Modes Saved */
- R0R1_REGS, /* R0 QI, QF, HF No */
- R0R1_REGS, /* R1 QI, QF, HF No */
- R2R3_REGS, /* R2 QI, QF, HF No */
- R2R3_REGS, /* R3 QI, QF, HF No */
- EXT_LOW_REGS, /* R4 QI, QF, HF QI */
- EXT_LOW_REGS, /* R5 QI, QF, HF QI */
- EXT_LOW_REGS, /* R6 QI, QF, HF QF */
- EXT_LOW_REGS, /* R7 QI, QF, HF QF */
- ADDR_REGS, /* AR0 QI No */
- ADDR_REGS, /* AR1 QI No */
- ADDR_REGS, /* AR2 QI No */
- ADDR_REGS, /* AR3 QI QI */
- ADDR_REGS, /* AR4 QI QI */
- ADDR_REGS, /* AR5 QI QI */
- ADDR_REGS, /* AR6 QI QI */
- ADDR_REGS, /* AR7 QI QI */
- DP_REG, /* DP QI No */
- INDEX_REGS, /* IR0 QI No */
- INDEX_REGS, /* IR1 QI No */
- BK_REG, /* BK QI QI */
- SP_REG, /* SP QI No */
- ST_REG, /* ST CC No */
- NO_REGS, /* DIE/IE No */
- NO_REGS, /* IIE/IF No */
- NO_REGS, /* IIF/IOF No */
- INT_REGS, /* RS QI No */
- INT_REGS, /* RE QI No */
- RC_REG, /* RC QI No */
- EXT_REGS, /* R8 QI, QF, HF QI */
- EXT_REGS, /* R9 QI, QF, HF No */
- EXT_REGS, /* R10 QI, QF, HF No */
- EXT_REGS, /* R11 QI, QF, HF No */
-};
-
-enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] =
-{
- /* Reg Modes Saved */
- HFmode, /* R0 QI, QF, HF No */
- HFmode, /* R1 QI, QF, HF No */
- HFmode, /* R2 QI, QF, HF No */
- HFmode, /* R3 QI, QF, HF No */
- QFmode, /* R4 QI, QF, HF QI */
- QFmode, /* R5 QI, QF, HF QI */
- QImode, /* R6 QI, QF, HF QF */
- QImode, /* R7 QI, QF, HF QF */
- QImode, /* AR0 QI No */
- QImode, /* AR1 QI No */
- QImode, /* AR2 QI No */
- QImode, /* AR3 QI QI */
- QImode, /* AR4 QI QI */
- QImode, /* AR5 QI QI */
- QImode, /* AR6 QI QI */
- QImode, /* AR7 QI QI */
- VOIDmode, /* DP QI No */
- QImode, /* IR0 QI No */
- QImode, /* IR1 QI No */
- QImode, /* BK QI QI */
- VOIDmode, /* SP QI No */
- VOIDmode, /* ST CC No */
- VOIDmode, /* DIE/IE No */
- VOIDmode, /* IIE/IF No */
- VOIDmode, /* IIF/IOF No */
- QImode, /* RS QI No */
- QImode, /* RE QI No */
- VOIDmode, /* RC QI No */
- QFmode, /* R8 QI, QF, HF QI */
- HFmode, /* R9 QI, QF, HF No */
- HFmode, /* R10 QI, QF, HF No */
- HFmode, /* R11 QI, QF, HF No */
-};
-
-
-/* Test and compare insns in c4x.md store the information needed to
- generate branch and scc insns here. */
-
-struct rtx_def *c4x_compare_op0 = NULL_RTX;
-struct rtx_def *c4x_compare_op1 = NULL_RTX;
-
-char *c4x_rpts_cycles_string;
-int c4x_rpts_cycles = 0; /* Max. cycles for RPTS */
-char *c4x_cpu_version_string;
-int c4x_cpu_version = 40; /* CPU version C30/31/32/40/44 */
-
-/* Pragma definitions. */
-
-tree code_tree = NULL_TREE;
-tree data_tree = NULL_TREE;
-tree pure_tree = NULL_TREE;
-tree noreturn_tree = NULL_TREE;
-tree interrupt_tree = NULL_TREE;
-
-
-/* Override command line options.
- Called once after all options have been parsed.
- Mostly we process the processor
- type and sometimes adjust other TARGET_ options. */
-
-void
-c4x_override_options ()
-{
- if (c4x_rpts_cycles_string)
- c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);
- else
- c4x_rpts_cycles = 0;
-
- if (TARGET_C30)
- c4x_cpu_version = 30;
- else if (TARGET_C31)
- c4x_cpu_version = 31;
- else if (TARGET_C32)
- c4x_cpu_version = 32;
- else if (TARGET_C40)
- c4x_cpu_version = 40;
- else if (TARGET_C44)
- c4x_cpu_version = 44;
- else
- c4x_cpu_version = 40;
-
- /* -mcpu=xx overrides -m40 etc. */
- if (c4x_cpu_version_string)
- c4x_cpu_version = atoi (c4x_cpu_version_string);
-
- target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C40_FLAG | C44_FLAG);
-
- switch (c4x_cpu_version)
- {
- case 30: target_flags |= C30_FLAG; break;
- case 31: target_flags |= C31_FLAG; break;
- case 32: target_flags |= C32_FLAG; break;
- case 40: target_flags |= C40_FLAG; break;
- case 44: target_flags |= C44_FLAG; break;
- default:
- warning ("Unknown CPU version %d, using 40.\n", c4x_cpu_version);
- c4x_cpu_version = 40;
- target_flags |= C40_FLAG;
- }
-
- if (TARGET_C30 || TARGET_C31 || TARGET_C32)
- target_flags |= C3X_FLAG;
- else
- target_flags &= ~C3X_FLAG;
-
- /* Convert foo / 8.0 into foo * 0.125, etc. */
- flag_fast_math = 1;
-
- /* We should phase out the following at some stage.
- This provides compatibility with the old -mno-aliases option. */
- if (! TARGET_ALIASES && ! flag_argument_noalias)
- flag_argument_noalias = 1;
-}
-
-/* This is called before c4x_override_options. */
-void
-c4x_optimization_options (level, size)
- int level;
- int size ATTRIBUTE_UNUSED;
-{
- /* Scheduling before register allocation can screw up global
- register allocation, especially for functions that use MPY||ADD
- instructions. The benefit we gain we get by scheduling before
- register allocation is probably marginal anyhow. */
- flag_schedule_insns = 0;
-
- /* When optimizing, enable use of RPTB instruction. */
- if (level >= 1)
- flag_branch_on_count_reg = 1;
-}
-
-/* Write an ASCII string. */
-
-#define C4X_ASCII_LIMIT 40
-
-void
-c4x_output_ascii (stream, ptr, len)
- FILE *stream;
- unsigned char *ptr;
- int len;
-{
- char sbuf[C4X_ASCII_LIMIT + 1];
- int s, first, onlys;
-
- if (len)
- {
- fprintf (stream, "\t.byte\t");
- first = 1;
- }
-
- for (s = 0; len > 0; --len, ++ptr)
- {
- onlys = 0;
-
- /* Escape " and \ with a \". */
- if (*ptr == '\"' || *ptr == '\\')
- sbuf[s++] = '\\';
-
- /* If printable - add to buff. */
- if (*ptr >= 0x20 && *ptr < 0x7f)
- {
- sbuf[s++] = *ptr;
- if (s < C4X_ASCII_LIMIT - 1)
- continue;
- onlys = 1;
- }
- if (s)
- {
- if (first)
- first = 0;
- else
- fputc (',', stream);
-
- sbuf[s] = 0;
- fprintf (stream, "\"%s\"", sbuf);
- s = 0;
- }
- if (onlys)
- continue;
-
- if (first)
- first = 0;
- else
- fputc (',', stream);
-
- fprintf (stream, "%d", *ptr);
- }
- if (s)
- {
- if (! first)
- fputc (',', stream);
-
- sbuf[s] = 0;
- fprintf (stream, "\"%s\"", sbuf);
- s = 0;
- }
- fputc ('\n', stream);
-}
-
-
-int
-c4x_hard_regno_mode_ok (regno, mode)
- int regno;
- enum machine_mode mode;
-{
- switch (mode)
- {
-#if Pmode != QImode
- case Pmode: /* Pointer (24/32 bits) */
-#endif
- case QImode: /* Integer (32 bits) */
- return IS_INT_REG (regno);
-
- case QFmode: /* Float, Double (32 bits) */
- case HFmode: /* Long Double (40 bits) */
- return IS_EXT_REG (regno);
-
- case CCmode: /* Condition Codes */
- case CC_NOOVmode: /* Condition Codes */
- return IS_ST_REG (regno);
-
- case HImode: /* Long Long (64 bits) */
- /* We need two registers to store long longs. Note that
- it is much easier to constrain the first register
- to start on an even boundary. */
- return IS_INT_REG (regno)
- && IS_INT_REG (regno + 1)
- && (regno & 1) == 0;
-
- default:
- return 0; /* We don't support these modes */
- }
-
- return 0;
-}
-
-
-/* The TI C3x C compiler register argument runtime model uses 6 registers,
- AR2, R2, R3, RC, RS, RE.
-
- The first two floating point arguments (float, double, long double)
- that are found scanning from left to right are assigned to R2 and R3.
-
- The remaining integer (char, short, int, long) or pointer arguments
- are assigned to the remaining registers in the order AR2, R2, R3,
- RC, RS, RE when scanning left to right, except for the last named
- argument prior to an ellipsis denoting variable number of
- arguments. We don't have to worry about the latter condition since
- function.c treats the last named argument as anonymous (unnamed).
-
- All arguments that cannot be passed in registers are pushed onto
- the stack in reverse order (right to left). GCC handles that for us.
-
- c4x_init_cumulative_args() is called at the start, so we can parse
- the args to see how many floating point arguments and how many
- integer (or pointer) arguments there are. c4x_function_arg() is
- then called (sometimes repeatedly) for each argument (parsed left
- to right) to obtain the register to pass the argument in, or zero
- if the argument is to be passed on the stack. Once the compiler is
- happy, c4x_function_arg_advance() is called.
-
- Don't use R0 to pass arguments in, we use 0 to indicate a stack
- argument. */
-
-static int c4x_int_reglist[3][6] =
-{
- {AR2_REGNO, R2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO},
- {AR2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0},
- {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0}
-};
-
-static int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
-
-
-/* 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. */
-
-void
-c4x_init_cumulative_args (cum, fntype, libname)
- CUMULATIVE_ARGS *cum; /* argument info to initialize */
- tree fntype; /* tree ptr for function decl */
- rtx libname; /* SYMBOL_REF of library name or 0 */
-{
- tree param, next_param;
-
- cum->floats = cum->ints = 0;
- cum->init = 0;
- cum->var = 0;
- cum->args = 0;
-
- if (TARGET_DEBUG)
- {
- fprintf (stderr, "\nc4x_init_cumulative_args (");
- if (fntype)
- {
- tree ret_type = TREE_TYPE (fntype);
-
- fprintf (stderr, "fntype code = %s, ret code = %s",
- tree_code_name[(int) TREE_CODE (fntype)],
- tree_code_name[(int) TREE_CODE (ret_type)]);
- }
- else
- fprintf (stderr, "no fntype");
-
- if (libname)
- fprintf (stderr, ", libname = %s", XSTR (libname, 0));
- }
-
- cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
-
- for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
- param; param = next_param)
- {
- tree type;
-
- next_param = TREE_CHAIN (param);
-
- type = TREE_VALUE (param);
- if (type && type != void_type_node)
- {
- enum machine_mode mode;
-
- /* If the last arg doesn't have void type then we have
- variable arguments. */
- if (! next_param)
- cum->var = 1;
-
- if ((mode = TYPE_MODE (type)))
- {
- if (! MUST_PASS_IN_STACK (mode, type))
- {
- /* Look for float, double, or long double argument. */
- if (mode == QFmode || mode == HFmode)
- cum->floats++;
- /* Look for integer, enumeral, boolean, char, or pointer
- argument. */
- else if (mode == QImode || mode == Pmode)
- cum->ints++;
- }
- }
- cum->args++;
- }
- }
-
- if (TARGET_DEBUG)
- fprintf (stderr, "%s%s, args = %d)\n",
- cum->prototype ? ", prototype" : "",
- cum->var ? ", variable args" : "",
- cum->args);
-}
-
-
-/* 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.) */
-
-void
-c4x_function_arg_advance (cum, mode, type, named)
- CUMULATIVE_ARGS *cum; /* current arg information */
- enum machine_mode mode; /* current arg mode */
- tree type; /* type of the argument or 0 if lib support */
- int named; /* whether or not the argument was named */
-{
- if (TARGET_DEBUG)
- fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n",
- GET_MODE_NAME (mode), named);
- if (! TARGET_MEMPARM
- && named
- && type
- && ! MUST_PASS_IN_STACK (mode, type))
- {
- /* Look for float, double, or long double argument. */
- if (mode == QFmode || mode == HFmode)
- cum->floats++;
- /* Look for integer, enumeral, boolean, char, or pointer argument. */
- else if (mode == QImode || mode == Pmode)
- cum->ints++;
- }
- else if (! TARGET_MEMPARM && ! type)
- {
- /* Handle libcall arguments. */
- if (mode == QFmode || mode == HFmode)
- cum->floats++;
- else if (mode == QImode || mode == Pmode)
- cum->ints++;
- }
- return;
-}
-
-
-/* Define where to put the arguments to a function. Value is zero to
- push the argument on the stack, or a hard register in which to
- store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-struct rtx_def *
-c4x_function_arg (cum, mode, type, named)
- CUMULATIVE_ARGS *cum; /* current arg information */
- enum machine_mode mode; /* current arg mode */
- tree type; /* type of the argument or 0 if lib support */
- int named; /* != 0 for normal args, == 0 for ... args */
-{
- int reg = 0; /* default to passing argument on stack */
-
- if (! cum->init)
- {
- /* We can handle at most 2 floats in R2, R3 */
- cum->maxfloats = (cum->floats > 2) ? 2 : cum->floats;
-
- /* We can handle at most 6 integers minus number of floats passed
- in registers. */
- cum->maxints = (cum->ints > 6 - cum->maxfloats) ?
- 6 - cum->maxfloats : cum->ints;
-
- /* If there is no prototype, assume all the arguments are integers. */
- if (! cum->prototype)
- cum->maxints = 6;
-
- cum->ints = cum->floats = 0;
- cum->init = 1;
- }
-
- if (! TARGET_MEMPARM
- && named
- && type
- && ! MUST_PASS_IN_STACK (mode, type))
- {
- /* Look for float, double, or long double argument. */
- if (mode == QFmode || mode == HFmode)
- {
- if (cum->floats < cum->maxfloats)
- reg = c4x_fp_reglist[cum->floats];
- }
- /* Look for integer, enumeral, boolean, char, or pointer argument. */
- else if (mode == QImode || mode == Pmode)
- {
- if (cum->ints < cum->maxints)
- reg = c4x_int_reglist[cum->maxfloats][cum->ints];
- }
- }
- else if (! TARGET_MEMPARM && ! type)
- {
- /* We could use a different argument calling model for libcalls,
- since we're only calling functions in libgcc. Thus we could
- pass arguments for long longs in registers rather than on the
- stack. In the meantime, use the odd TI format. We make the
- assumption that we won't have more than two floating point
- args, six integer args, and that all the arguments are of the
- same mode. */
- if (mode == QFmode || mode == HFmode)
- reg = c4x_fp_reglist[cum->floats];
- else if (mode == QImode || mode == Pmode)
- reg = c4x_int_reglist[0][cum->ints];
- }
-
- if (TARGET_DEBUG)
- {
- fprintf (stderr, "c4x_function_arg(mode=%s, named=%d",
- GET_MODE_NAME (mode), named);
- if (reg)
- fprintf (stderr, ", reg=%s", reg_names[reg]);
- else
- fprintf (stderr, ", stack");
- fprintf (stderr, ")\n");
- }
- if (reg)
- return gen_rtx_REG (mode, reg);
- else
- return NULL_RTX;
-}
-
-
-static int
-c4x_isr_reg_used_p (regno)
- int regno;
-{
- /* Don't save/restore FP or ST, we handle them separately. */
- if (regno == FRAME_POINTER_REGNUM
- || IS_ST_REG (regno))
- return 0;
-
- /* We could be a little smarter abut saving/restoring DP.
- We'll only save if for the big memory model or if
- we're paranoid. ;-) */
- if (IS_DP_REG (regno))
- return ! TARGET_SMALL || TARGET_PARANOID;
-
- /* Only save/restore regs in leaf function that are used. */
- if (c4x_leaf_function)
- return regs_ever_live[regno] && fixed_regs[regno] == 0;
-
- /* Only save/restore regs that are used by the ISR and regs
- that are likely to be used by functions the ISR calls
- if they are not fixed. */
- return IS_EXT_REG (regno)
- || ((regs_ever_live[regno] || call_used_regs[regno])
- && fixed_regs[regno] == 0);
-}
-
-
-static int
-c4x_leaf_function_p ()
-{
- /* A leaf function makes no calls, so we only need
- to save/restore the registers we actually use.
- For the global variable leaf_function to be set, we need
- to define LEAF_REGISTERS and all that it entails.
- Let's check ourselves... */
-
- if (lookup_attribute ("leaf_pretend",
- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
- return 1;
-
- /* Use the leaf_pretend attribute at your own risk. This is a hack
- to speed up ISRs that call a function infrequently where the
- overhead of saving and restoring the additional registers is not
- warranted. You must save and restore the additional registers
- required by the called function. Caveat emptor. Here's enough
- rope... */
-
- if (leaf_function_p ())
- return 1;
-
- return 0;
-}
-
-
-static int
-c4x_assembler_function_p ()
-{
- tree type;
-
- type = TREE_TYPE (current_function_decl);
- return lookup_attribute ("assembler", TYPE_ATTRIBUTES (type)) != NULL;
-}
-
-
-static int
-c4x_interrupt_function_p ()
-{
- if (lookup_attribute ("interrupt",
- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
- return 1;
-
- /* Look for TI style c_intnn */
- return current_function_name[0] == 'c'
- && current_function_name[1] == '_'
- && current_function_name[2] == 'i'
- && current_function_name[3] == 'n'
- && current_function_name[4] == 't'
- && isdigit (current_function_name[5])
- && isdigit (current_function_name[6]);
-}
-
-
-/* Write function prologue. */
-
-void
-c4x_function_prologue (file, size)
- FILE *file;
- int size;
-{
- int regno;
-
-/* In functions where ar3 is not used but frame pointers are still
- specified, frame pointers are not adjusted (if >= -O2) and this is
- used so it won't be needlessly push the frame pointer. */
- int dont_push_ar3;
-
- /* For __assembler__ function don't build a prologue. */
- if (c4x_assembler_function_p ())
- {
- fprintf (file, "; *** Assembler Function ***\n");
- return;
- }
-
- /* For __interrupt__ function build specific prologue. */
- if (c4x_interrupt_function_p ())
- {
- c4x_leaf_function = c4x_leaf_function_p ();
- fprintf (file, "; *** Interrupt Entry %s ***\n",
- c4x_leaf_function ? "(leaf)" : "");
-
- fprintf (file, "\tpush\tst\n");
- if (size)
- {
- fprintf (file, "\tpush\tar3\n\tldi\tsp,ar3\n");
- /* FIXME: Assume ISR doesn't require more than 32767 words
- of local variables. */
- if (size > 32767)
- error ("ISR %s requires %d words of local variables, "
- "maximum is 32767.", current_function_name, size);
- fprintf (file, "\taddi\t%d,sp\n", size);
- }
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (c4x_isr_reg_used_p (regno))
- {
- fprintf (file, "\tpush\t%s\n", reg_names[regno]);
- if (IS_EXT_REG (regno)) /* save 32MSB of R0--R11 */
- fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]);
- }
- }
- /* We need to clear the repeat mode flag if the ISR is
- going to use a RPTB instruction or uses the RC, RS, or RE
- registers. */
- if (regs_ever_live[RC_REGNO]
- || regs_ever_live[RS_REGNO]
- || regs_ever_live[RE_REGNO])
- fprintf (file, "\tandn\t0100h,st\n");
-
- /* Reload DP reg if we are paranoid about some turkey
- violating small memory model rules. */
- if (TARGET_SMALL && TARGET_PARANOID)
- fprintf (file, TARGET_C3X ?
- "\tldp\t@data_sec\n" :
- "\tldpk\t@data_sec\n");
- }
- else
- {
- if (frame_pointer_needed)
- {
- if ((size != 0)
- || (current_function_args_size != 0)
- || (optimize < 2))
- {
- fprintf (file, "\tpush\tar3\n");
- fprintf (file, "\tldi\tsp,ar3\n");
- dont_push_ar3 = 1;
- }
- else
- {
- /* Since ar3 is not used, we don't need to push it. */
- dont_push_ar3 = 1;
- }
- }
- else
- {
- /* If we use ar3, we need to push it. */
- dont_push_ar3 = 0;
- if ((size != 0) || (current_function_args_size != 0))
- {
- /* If we are omitting the frame pointer, we still have
- to make space for it so the offsets are correct
- unless we don't use anything on the stack at all. */
- size += 1;
- }
- }
-
- if (size > 32767)
- {
- /* Local vars are too big, it will take multiple operations
- to increment SP. */
- if (TARGET_C3X)
- {
- fprintf (file, "\tldi\t%d,r1\n", size >> 16);
- fprintf (file, "\tlsh\t16,r1\n");
- }
- else
- fprintf (file, "\tldhi\t%d,r1\n", size >> 16);
- fprintf (file, "\tor\t%d,r1\n", size & 0xffff);
- fprintf (file, "\taddi\tr1,sp\n");
- }
- else if (size != 0)
- {
- /* Local vars take up less than 32767 words, so we can directly
- add the number. */
- fprintf (file, "\taddi\t%d,sp\n", size);
- }
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- {
- if ((regno == R6_REGNO) || (regno == R7_REGNO))
- {
- /* R6 and R7 are saved as floating point */
- if (TARGET_PRESERVE_FLOAT)
- fprintf (file, "\tpush\t%s\n", reg_names[regno]);
- fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]);
- }
- else if ((! dont_push_ar3) || (regno != AR3_REGNO))
- {
- fprintf (file, "\tpush\t%s\n", reg_names[regno]);
- }
- }
- }
- }
-}
-
-
-/* Write function epilogue. */
-
-void
-c4x_function_epilogue (file, size)
- FILE *file;
- int size;
-{
- int regno;
- int restore_count = 0;
- int delayed_jump = 0;
- int dont_pop_ar3;
- rtx insn;
-
- insn = get_last_insn ();
- if (insn && GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
-
- if (insn && GET_CODE (insn) == BARRIER)
- return;
-
- /* For __assembler__ function build no epilogue. */
- if (c4x_assembler_function_p ())
- {
- fprintf (file, "\trets\n"); /* Play it safe */
- return;
- }
-
-#ifdef FUNCTION_BLOCK_PROFILER_EXIT
- if (profile_block_flag == 2)
- {
- FUNCTION_BLOCK_PROFILER_EXIT (file);
- }
-#endif
-
- /* For __interrupt__ function build specific epilogue. */
- if (c4x_interrupt_function_p ())
- {
- for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
- {
- if (! c4x_isr_reg_used_p (regno))
- continue;
- if (IS_EXT_REG (regno))
- fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]);
- fprintf (file, "\tpop\t%s\n", reg_names[regno]);
- }
- if (size)
- {
- fprintf (file, "\tsubi\t%d,sp\n", size);
- fprintf (file, "\tpop\tar3\n");
- }
- fprintf (file, "\tpop\tst\n");
- fprintf (file, "\treti\n");
- }
- else
- {
- if (frame_pointer_needed)
- {
- if ((size != 0)
- || (current_function_args_size != 0)
- || (optimize < 2))
- {
- /* R2 holds the return value. */
- fprintf (file, "\tldi\t*-ar3(1),r2\n");
-
- /* We already have the return value and the fp,
- so we need to add those to the stack. */
- size += 2;
- delayed_jump = 1;
- restore_count = 1;
- dont_pop_ar3 = 1;
- }
- else
- {
- /* Since ar3 is not used for anything, we don't need to
- pop it. */
- dont_pop_ar3 = 1;
- }
- }
- else
- {
- dont_pop_ar3 = 0; /* If we use ar3, we need to pop it */
- if (size || current_function_args_size)
- {
- /* If we are ommitting the frame pointer, we still have
- to make space for it so the offsets are correct
- unless we don't use anything on the stack at all. */
- size += 1;
- }
- }
-
- /* Now get the number of instructions required to restore the
- registers. */
- for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
- {
- if ((regs_ever_live[regno] && ! call_used_regs[regno])
- && ((! dont_pop_ar3) || (regno != AR3_REGNO)))
- {
- restore_count++;
- if (TARGET_PRESERVE_FLOAT
- && ((regno == R6_REGNO) || (regno == R7_REGNO)))
- restore_count++;
- }
- }
-
- /* Get the number of instructions required to restore the stack. */
- if (size > 32767)
- restore_count += (TARGET_C3X ? 4 : 3);
- else if (size != 0)
- restore_count += 1;
-
- if (delayed_jump && (restore_count < 3))
- {
- /* We don't have enough instructions to account for the delayed
- branch, so put some nops in. */
-
- fprintf (file, "\tbud\tr2\n");
- while (restore_count < 3)
- {
- fprintf (file, "\tnop\n");
- restore_count++;
- }
- restore_count = 0;
- }
-
- /* Now restore the saved registers, putting in the delayed branch
- where required. */
- for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- {
- if (regno == AR3_REGNO && dont_pop_ar3)
- continue;
-
- if (delayed_jump && (restore_count == 3))
- fprintf (file, "\tbud\tr2\n");
-
- /* R6 and R7 are saved as floating point. */
- if ((regno == R6_REGNO) || (regno == R7_REGNO))
- {
- fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]);
- if (TARGET_PRESERVE_FLOAT)
- {
- restore_count--;
- if (delayed_jump && (restore_count == 3))
- fprintf (file, "\tbud\tr2\n");
- fprintf (file, "\tpop\t%s\n", reg_names[regno]);
- }
- }
- else
- fprintf (file, "\tpop\t%s\n", reg_names[regno]);
- restore_count--;
- }
- }
-
- if (delayed_jump && (restore_count == 3))
- fprintf (file, "\tbud\tr2\n");
-
- if (frame_pointer_needed)
- {
- if ((size != 0)
- || (current_function_args_size != 0)
- || (optimize < 2))
- {
- /* Restore the old FP. */
- fprintf (file, "\tldi\t*ar3,ar3\n");
- restore_count--;
-
- if (delayed_jump && (restore_count == 3))
- fprintf (file, "\tbud\tr2\n");
- }
- }
-
- if (size > 32767)
- {
- /* Local vars are too big, it will take multiple operations
- to decrement SP. */
- if (TARGET_C3X)
- {
- fprintf (file, "\tldi\t%d,r3\n", size >> 16);
- if (delayed_jump)
- fprintf (file, "\tbud\tr2\n");
- fprintf (file, "\tlsh\t16,r3\n");
- }
- else
- fprintf (file, "\tldhi\t%d,r3\n", size >> 16);
- fprintf (file, "\tor\t%d,r3\n", size & 0xffff);
- fprintf (file, "\tsubi\tr3,sp\n");
- }
- else if (size != 0)
- {
- /* Local vars take up less than 32768 words, so we can directly
- subtract the number. */
- fprintf (file, "\tsubi\t%d,sp\n", size);
- }
-
- if (! delayed_jump)
- fprintf (file, "\trets\n");
- }
-}
-
-int
-c4x_null_epilogue_p ()
-{
- int regno;
-
- if (reload_completed
- && ! c4x_assembler_function_p ()
- && ! c4x_interrupt_function_p ()
- && ! current_function_calls_alloca
- && ! current_function_args_size
- && ! (profile_block_flag == 2)
- && ! (optimize < 2)
- && ! get_frame_size ())
- {
- for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
- if (regs_ever_live[regno] && ! call_used_regs[regno]
- && (regno != AR3_REGNO))
- return 0;
- return 1;
- }
- return 0;
-}
-
-
-void
-c4x_emit_libcall (name, code, dmode, smode, noperands, operands)
- char *name;
- enum rtx_code code;
- enum machine_mode dmode;
- enum machine_mode smode;
- int noperands;
- rtx *operands;
-{
- rtx ret;
- rtx insns;
- rtx libcall;
- rtx equiv;
-
- start_sequence ();
- libcall = gen_rtx_SYMBOL_REF (Pmode, name);
- switch (noperands)
- {
- case 2:
- ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
- operands[1], smode);
- equiv = gen_rtx (code, dmode, operands[1]);
- break;
-
- case 3:
- ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2,
- operands[1], smode, operands[2], smode);
- equiv = gen_rtx (code, dmode, operands[1], operands[2]);
- break;
-
- default:
- fatal ("c4x_emit_libcall: Bad number of operands");
- }
-
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret, equiv);
-}
-
-
-void
-c4x_emit_libcall3 (name, code, mode, operands)
- const char *name;
- enum rtx_code code;
- enum machine_mode mode;
- rtx *operands;
-{
- return c4x_emit_libcall (name, code, mode, mode, 3, operands);
-}
-
-void
-c4x_emit_libcall_mulhi (name, code, mode, operands)
- char *name;
- enum rtx_code code;
- enum machine_mode mode;
- rtx *operands;
-{
- rtx ret;
- rtx insns;
- rtx libcall;
- rtx equiv;
-
- start_sequence ();
- libcall = gen_rtx_SYMBOL_REF (Pmode, name);
- ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2,
- operands[1], mode, operands[2], mode);
- equiv = gen_rtx_TRUNCATE (mode,
- gen_rtx_LSHIFTRT (HImode,
- gen_rtx_MULT (HImode,
- gen_rtx (code, HImode, operands[1]),
- gen_rtx (code, HImode, operands[2])),
- GEN_INT (32)));
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret, equiv);
-}
-
-
-enum reg_class
-c4x_preferred_reload_class (x, class)
- rtx x;
- enum reg_class class;
-{
- return class;
-}
-
-
-enum reg_class
-c4x_limit_reload_class (mode, class)
- enum machine_mode mode ATTRIBUTE_UNUSED;
- enum reg_class class;
-{
- return class;
-}
-
-
-enum reg_class
-c4x_secondary_memory_needed (class1, class2, mode)
- enum reg_class class1 ATTRIBUTE_UNUSED;
- enum reg_class class2 ATTRIBUTE_UNUSED;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return 0;
-}
-
-
-int
-c4x_check_legit_addr (mode, addr, strict)
- enum machine_mode mode;
- rtx addr;
- int strict;
-{
- rtx base = NULL_RTX; /* Base register (AR0-AR7) */
- rtx indx = NULL_RTX; /* Index register (IR0,IR1) */
- rtx disp = NULL_RTX; /* Displacement */
- enum rtx_code code;
-
- code = GET_CODE (addr);
- switch (code)
- {
- /* Register indirect with auto increment/decrement. We don't
- allow SP here---push_operand should recognise an operand
- being pushed on the stack. */
-
- case PRE_DEC:
- case POST_DEC:
- if (mode != QImode && mode != QFmode)
- return 0;
- case PRE_INC:
- case POST_INC:
- base = XEXP (addr, 0);
- if (! REG_P (base))
- return 0;
- break;
-
- case PRE_MODIFY:
- case POST_MODIFY:
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
-
- if (mode != QImode && mode != QFmode)
- return 0;
-
- if (! REG_P (op0)
- || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS))
- return 0;
- base = XEXP (op1, 0);
- if (base != op0)
- return 0;
- if (REG_P (XEXP (op1, 1)))
- indx = XEXP (op1, 1);
- else
- disp = XEXP (op1, 1);
- }
- break;
-
- /* Register indirect. */
- case REG:
- base = addr;
- break;
-
- /* Register indirect with displacement or index. */
- case PLUS:
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
- enum rtx_code code0 = GET_CODE (op0);
-
- switch (code0)
- {
- case USE:
- /* The uses are put in to avoid problems
- with referenced things disappearing. */
- return c4x_check_legit_addr (mode, op1, strict);
-
- case PLUS:
- /* This is another reference to keep things
- from disappearing, but it contains a plus
- of a use and DP. */
- if (GET_CODE (XEXP (op0, 0)) == USE)
- return c4x_check_legit_addr (mode, op1, strict);
- return 0;
-
- case REG:
- if (REG_P (op1))
- {
- base = op0; /* base + index */
- indx = op1;
- if (IS_INDEX_REGNO (base) || IS_ADDR_REGNO (indx))
- {
- base = op1;
- indx = op0;
- }
- }
- else
- {
- base = op0; /* base + displacement */
- disp = op1;
- }
- break;
-
- default:
- return 0;
- }
- }
- break;
-
- /* Direct addressing with some work for the assembler... */
- case CONST:
- if (GET_CODE (XEXP (addr, 0)) == PLUS
- && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
- || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF)
- && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
- return 1;
-
- /* Direct addressing. */
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- /* Do not allow direct memory access to absolute addresses.
- This is more pain than its worth, especially for the
- small memory model where we can't guarantee that
- this address is within the data page---we don't want
- to modify the DP register in the small memory model,
- even temporarily, since an interrupt can sneak in.... */
- case CONST_INT:
- return 0;
-
- /* Indirect indirect addressing. */
- case MEM:
- return 0;
-
- case CONST_DOUBLE:
- fatal_insn ("Using CONST_DOUBLE for address", addr);
-
- default:
- return 0;
- }
-
- /* Validate the base register. */
- if (base)
- {
- /* Check that the address is offsettable for HImode and HFmode. */
- if (indx && (mode == HImode || mode == HFmode))
- return 0;
-
- /* Handle DP based stuff. */
- if (REGNO (base) == DP_REGNO)
- return 1;
- if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base)))
- return 0;
- else if (! strict && ! IS_ADDR_OR_PSEUDO_REGNO (base))
- return 0;
- }
-
- /* Now validate the index register. */
- if (indx)
- {
- if (GET_CODE (indx) != REG)
- return 0;
- if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx)))
- return 0;
- else if (! strict && ! IS_INDEX_OR_PSEUDO_REGNO (indx))
- return 0;
- }
-
- /* Validate displacement. */
- if (disp)
- {
- if (GET_CODE (disp) != CONST_INT)
- return 0;
- if (mode == HImode || mode == HFmode)
- {
- /* The offset displacement must be legitimate. */
- if (! IS_DISP8_OFF_CONST (INTVAL (disp)))
- return 0;
- }
- else
- {
- if (! IS_DISP8_CONST (INTVAL (disp)))
- return 0;
- }
- /* Can't add an index with a disp. */
- if (indx)
- return 0;
- }
- return 1;
-}
-
-
-rtx
-c4x_legitimize_address (orig, mode)
- rtx orig ATTRIBUTE_UNUSED;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return NULL_RTX;
-}
-
-
-/* Provide the costs of an addressing mode that contains ADDR.
- If ADDR is not a valid address, its cost is irrelevant.
- This is used in cse and loop optimisation to determine
- if it is worthwhile storing a common address into a register.
- Unfortunately, the C4x address cost depends on other operands. */
-
-int
-c4x_address_cost (addr)
-rtx addr;
-{
- switch (GET_CODE (addr))
- {
- case REG:
- return 1;
-
- case CONST:
- {
- rtx offset = const0_rtx;
- addr = eliminate_constant_term (addr, &offset);
-
- if (GET_CODE (addr) == LABEL_REF)
- return 3;
-
- if (GET_CODE (addr) != SYMBOL_REF)
- return 4;
-
- if (INTVAL (offset) == 0)
- return 3;
- }
-
- /* fall through */
-
- case POST_INC:
- case POST_DEC:
- case PRE_INC:
- case PRE_DEC:
- return 1;
-
- case SYMBOL_REF:
- case LABEL_REF:
- return TARGET_SMALL ? 3 : 4;
-
- case PLUS:
- {
- register rtx op0 = XEXP (addr, 0);
- register rtx op1 = XEXP (addr, 1);
-
- if (GET_CODE (op0) != REG)
- break;
-
- switch (GET_CODE (op1))
- {
- default:
- break;
-
- case REG:
- return 2;
-
- case CONST_INT:
- if (IS_DISP1_CONST (INTVAL (op1)))
- return 1;
-
- if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1)))
- return 2;
-
- return 3;
- }
- }
- default:
- }
-
- return 4;
-}
-
-
-rtx
-c4x_gen_compare_reg (code, x, y)
- enum rtx_code code;
- rtx x, y;
-{
- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- rtx cc_reg;
-
- if (mode == CC_NOOVmode
- && (code == LE || code == GE || code == LT || code == GT))
- return NULL_RTX;
-
- cc_reg = gen_rtx_REG (mode, ST_REGNO);
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- gen_rtx_COMPARE (mode, x, y)));
- return cc_reg;
-}
-
-char *
-c4x_output_cbranch (form, seq)
- char *form;
- rtx seq;
-{
- int delayed = 0;
- int annultrue = 0;
- int annulfalse = 0;
- rtx delay;
- char *cp;
- static char str[100];
-
- if (final_sequence)
- {
- delay = XVECEXP (final_sequence, 0, 1);
- delayed = ! INSN_ANNULLED_BRANCH_P (seq);
- annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay);
- annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay);
- }
- strcpy (str, form);
- cp = &str [strlen (str)];
- if (delayed)
- {
- *cp++ = '%';
- *cp++ = '#';
- }
- if (annultrue)
- {
- *cp++ = 'a';
- *cp++ = 't';
- }
- if (annulfalse)
- {
- *cp++ = 'a';
- *cp++ = 'f';
- }
- *cp++ = '\t';
- *cp++ = '%';
- *cp++ = 'l';
- *cp++ = '1';
- *cp = 0;
- return str;
-}
-
-void
-c4x_print_operand (file, op, letter)
- FILE *file; /* file to write to */
- rtx op; /* operand to print */
- int letter; /* %<letter> or 0 */
-{
- rtx op1;
- enum rtx_code code;
-
- switch (letter)
- {
- case '#': /* delayed */
- if (final_sequence)
- asm_fprintf (file, "d");
- return;
- }
-
- code = GET_CODE (op);
- switch (letter)
- {
- case 'A': /* direct address */
- if (code == CONST_INT || code == SYMBOL_REF)
- asm_fprintf (file, "@");
- break;
-
- case 'C': /* call */
- if (code != MEM)
- fatal_insn ("c4x_print_operand: %%C inconsistency", op);
- op1 = XEXP (op, 0);
- SYMBOL_REF_FLAG (op1) = 1;
- output_addr_const (file, op1);
- return;
-
- case 'H': /* sethi */
- if (code == SYMBOL_REF)
- SYMBOL_REF_FLAG (op) = 1;
- break;
-
- case 'I': /* reversed condition */
- code = reverse_condition (code);
- break;
-
- case 'L': /* log 2 of constant */
- if (code != CONST_INT)
- fatal_insn ("c4x_print_operand: %%L inconsistency", op);
- fprintf (file, "%d", exact_log2 (INTVAL (op)));
- return;
-
- case 'N': /* ones complement of small constant */
- if (code != CONST_INT)
- fatal_insn ("c4x_print_operand: %%N inconsistency", op);
- fprintf (file, "%d", ~INTVAL (op));
- return;
-
- case 'K': /* generate ldp(k) if direct address */
- if (! TARGET_SMALL
- && code == MEM
- && GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE(XEXP (XEXP (op, 0), 0)) == REG
- && REGNO(XEXP (XEXP (op, 0), 0)) == DP_REGNO)
- {
- op1 = XEXP (XEXP (op, 0), 1);
- if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF)
- {
- asm_fprintf (file, "\t%s\t", TARGET_C3X ? "ldp" : "ldpk");
- output_address (XEXP (adj_offsettable_operand (op, 1), 0));
- asm_fprintf (file, "\n");
- }
- }
- return;
-
- case 'M': /* generate ldp(k) if direct address */
- if (! TARGET_SMALL /* only used in asm statements */
- && code == MEM
- && (GET_CODE (XEXP (op, 0)) == CONST
- || GET_CODE (XEXP (op, 0)) == SYMBOL_REF))
- {
- asm_fprintf (file, "%s\t", TARGET_C3X ? "ldp" : "ldpk");
- output_address (XEXP (op, 0));
- asm_fprintf (file, "\n\t");
- }
- return;
-
- case 'O': /* offset address */
- if (code == MEM && c4x_autoinc_operand (op, Pmode))
- break;
- else if (code == MEM)
- output_address (XEXP (adj_offsettable_operand (op, 1), 0));
- else if (code == REG)
- fprintf (file, "%s", reg_names[REGNO (op) + 1]);
- else
- fatal_insn ("c4x_print_operand: %%O inconsistency", op);
- return;
-
- case 'R': /* call register */
- op1 = XEXP (op, 0);
- if (code != MEM || GET_CODE (op1) != REG)
- fatal_insn ("c4x_print_operand: %%R inconsistency", op);
- else
- fprintf (file, "%s", reg_names[REGNO (op1)]);
- return;
-
- default:
- break;
- }
-
- switch (code)
- {
- case REG:
- if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
- fprintf (file, "%s", float_reg_names[REGNO (op)]);
- else
- fprintf (file, "%s", reg_names[REGNO (op)]);
- break;
-
- case MEM:
- output_address (XEXP (op, 0));
- break;
-
- case CONST_DOUBLE:
- {
- char str[30];
- REAL_VALUE_TYPE r;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_DECIMAL (r, "%20f", str);
- fprintf (file, "%s", str);
- }
- break;
-
- case CONST_INT:
- fprintf (file, "%d", INTVAL (op));
- break;
-
- case NE:
- asm_fprintf (file, "ne");
- break;
-
- case EQ:
- asm_fprintf (file, "eq");
- break;
-
- case GE:
- asm_fprintf (file, "ge");
- break;
-
- case GT:
- asm_fprintf (file, "gt");
- break;
-
- case LE:
- asm_fprintf (file, "le");
- break;
-
- case LT:
- asm_fprintf (file, "lt");
- break;
-
- case GEU:
- asm_fprintf (file, "hs");
- break;
-
- case GTU:
- asm_fprintf (file, "hi");
- break;
-
- case LEU:
- asm_fprintf (file, "ls");
- break;
-
- case LTU:
- asm_fprintf (file, "lo");
- break;
-
- case SYMBOL_REF:
- output_addr_const (file, op);
- break;
-
- case CONST:
- output_addr_const (file, XEXP (op, 0));
- break;
-
- case CODE_LABEL:
- break;
-
- default:
- fatal_insn ("c4x_print_operand: Bad operand case", op);
- break;
- }
-}
-
-
-void
-c4x_print_operand_address (file, addr)
- FILE *file;
- rtx addr;
-{
- switch (GET_CODE (addr))
- {
- case REG:
- fprintf (file, "*%s", reg_names[REGNO (addr)]);
- break;
-
- case PRE_DEC:
- fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]);
- break;
-
- case POST_INC:
- fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
- break;
-
- case POST_MODIFY:
- {
- rtx op0 = XEXP (XEXP (addr, 1), 0);
- rtx op1 = XEXP (XEXP (addr, 1), 1);
-
- if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
- fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)],
- reg_names[REGNO (op1)]);
- else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
- fprintf (file, "*%s++(%d)", reg_names[REGNO (op0)],
- INTVAL (op1));
- else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
- fprintf (file, "*%s--(%d)", reg_names[REGNO (op0)],
- -INTVAL (op1));
- else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
- fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)],
- reg_names[REGNO (op1)]);
- else
- fatal_insn ("c4x_print_operand_address: Bad post_modify", addr);
- }
- break;
-
- case PRE_MODIFY:
- {
- rtx op0 = XEXP (XEXP (addr, 1), 0);
- rtx op1 = XEXP (XEXP (addr, 1), 1);
-
- if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
- fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)],
- reg_names[REGNO (op1)]);
- else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
- fprintf (file, "*++%s(%d)", reg_names[REGNO (op0)],
- INTVAL (op1));
- else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
- fprintf (file, "*--%s(%d)", reg_names[REGNO (op0)],
- -INTVAL (op1));
- else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
- fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)],
- reg_names[REGNO (op1)]);
- else
- fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr);
- }
- break;
-
- case PRE_INC:
- fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]);
- break;
-
- case POST_DEC:
- fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
- break;
-
- case PLUS: /* Indirect with displacement. */
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
- enum rtx_code code0 = GET_CODE (op0);
-
- if (code0 == USE || code0 == PLUS)
- {
- asm_fprintf (file, "@");
- output_addr_const (file, op1);
- }
- else if (REG_P (op0))
- {
- if (REGNO (op0) == DP_REGNO)
- {
- c4x_print_operand_address (file, op1);
- }
- else if (REG_P (op1))
- {
- if (IS_INDEX_REGNO (op0))
- {
- fprintf (file, "*+%s(%s)",
- reg_names[REGNO (op1)],
- reg_names[REGNO (op0)]); /* index + base */
- }
- else
- {
- fprintf (file, "*+%s(%s)",
- reg_names[REGNO (op0)],
- reg_names[REGNO (op1)]); /* base + index */
- }
- }
- else if (INTVAL (op1) < 0)
- {
- fprintf (file, "*-%s(%d)",
- reg_names[REGNO (op0)],
- -INTVAL (op1)); /* base - displacement */
- }
- else
- {
- fprintf (file, "*+%s(%d)",
- reg_names[REGNO (op0)],
- INTVAL (op1)); /* base + displacement */
- }
- }
- }
- break;
-
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- if (! SYMBOL_REF_FLAG (addr))
- fprintf (file, "@");
- output_addr_const (file, addr);
- SYMBOL_REF_FLAG (addr) = 0;
- break;
-
- /* We shouldn't access CONST_INT addresses. */
- case CONST_INT:
-
- default:
- fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
- break;
- }
-}
-
-
-static int
-c4x_immed_float_p (operand)
- rtx operand;
-{
- long convval[2];
- int exponent;
- REAL_VALUE_TYPE r;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
- if (GET_MODE (operand) == HFmode)
- REAL_VALUE_TO_TARGET_DOUBLE (r, convval);
- else
- {
- REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]);
- convval[1] = 0;
- }
-
- /* sign extend exponent */
- exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80;
- if (exponent == -128)
- return 1; /* 0.0 */
- if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0)
- return 0; /* Precision doesn't fit */
- return (exponent <= 7) /* Positive exp */
- && (exponent >= -7); /* Negative exp */
-}
-
-
-/* This function checks for an insn operand that requires direct
- addressing and inserts a load of the DP register prior to the
- insn if the big memory model is being compiled for. Immediate
- operands that do not fit within the opcode field get changed
- into memory references using direct addressing. At this point
- all pseudos have been converted to hard registers. */
-
-int
-c4x_scan_for_ldp (newop, insn, operand0)
- rtx *newop;
- rtx insn;
- rtx operand0;
-{
- int i;
- char *format_ptr;
- rtx op0, op1, op2, addr;
- rtx operand = *newop;
-
- switch (GET_CODE (operand))
- {
- case MEM:
- op0 = XEXP (operand, 0);
-
- /* We have something we need to emit a load dp insn for.
- The first operand should hold the rtx for the instruction
- required. */
-
- switch (GET_CODE (op0))
- {
- case CONST_INT:
- fatal_insn ("c4x_scan_for_ldp: Direct memory access to const_int",
- op0);
- break;
-
- case CONST:
- case SYMBOL_REF:
- if (! TARGET_C3X && ! TARGET_SMALL
- && recog_memoized (insn) == CODE_FOR_movqi_noclobber
- && ((addr = find_reg_note (insn, REG_EQUAL, NULL_RTX))
- || (addr = find_reg_note (insn, REG_EQUIV, NULL_RTX)))
- && (IS_STD_OR_PSEUDO_REGNO (operand0)))
- {
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == CONST_INT)
- {
- op1 = GEN_INT (INTVAL (addr) & ~0xffff);
- emit_insn_before (gen_movqi (operand0, op1), insn);
- op1 = GEN_INT (INTVAL (addr) & 0xffff);
- emit_insn_before (gen_iorqi3_noclobber (operand0,
- operand0, op1), insn);
- delete_insn (insn);
- return 1;
- }
- else if (GET_CODE (addr) == SYMBOL_REF)
- {
- emit_insn_before (gen_set_high_use (operand0, addr, addr),
- insn);
- emit_insn_before (gen_set_ior_lo_use (operand0, addr, addr),
- insn);
- delete_insn (insn);
- return 1;
- }
- else if (GET_CODE (addr) == CONST
- && GET_CODE (op1 = XEXP (addr, 0)) == PLUS
- && GET_CODE (op2 = XEXP (op1, 0)) == SYMBOL_REF
- && GET_CODE (XEXP (op1, 1)) == CONST_INT)
- {
- emit_insn_before (gen_set_high_use (operand0, addr, op2),
- insn);
- emit_insn_before (gen_set_ior_lo_use (operand0, addr, op2),
- insn);
- delete_insn (insn);
- return 1;
- }
- }
- if (! TARGET_SMALL)
- emit_insn_before (gen_set_ldp (gen_rtx_REG (Pmode, DP_REGNO),
- operand), insn);
-
- /* Replace old memory reference with direct reference. */
- *newop = gen_rtx_MEM (GET_MODE (operand),
- gen_rtx_PLUS (Pmode,
- gen_rtx_REG (Pmode, DP_REGNO),
- op0));
-
- /* Use change_address? */
- RTX_UNCHANGING_P (*newop) = RTX_UNCHANGING_P (operand);
- MEM_COPY_ATTRIBUTES (*newop, operand);
- break;
-
- default:
- break;
- }
-
- return 0;
-
- case CONST_INT:
- if (SMALL_CONST (INTVAL (operand), insn))
- break;
- fatal_insn ("Immediate integer too large", insn);
-
- case CONST_DOUBLE:
- if (c4x_immed_float_p (operand))
- break;
-
- /* We'll come here if a CONST_DOUBLE integer has slipped
- though the net... */
- fatal_insn ("Immediate CONST_DOUBLE integer too large", insn);
-
- case CONST:
- fatal_insn ("Immediate integer not known", insn);
-
- /* Symbol and label immediate addresses cannot be stored
- within a C[34]x instruction, so we store them in memory
- and use direct addressing instead. */
- case LABEL_REF:
- case SYMBOL_REF:
- if (GET_CODE (operand0) != REG)
- break;
-
- op0 = XEXP (force_const_mem (Pmode, operand), 0);
- *newop = gen_rtx_MEM (GET_MODE (operand),
- gen_rtx_PLUS (Pmode,
- gen_rtx_PLUS (Pmode,
- gen_rtx_USE (VOIDmode, operand),
- gen_rtx_REG (Pmode, DP_REGNO)),
- op0));
-
- if (! TARGET_SMALL)
- emit_insn_before (gen_set_ldp_use (gen_rtx_REG (Pmode, DP_REGNO),
- *newop, operand), insn);
- return 0;
-
- default:
- break;
- }
-
- format_ptr = GET_RTX_FORMAT (GET_CODE (operand));
-
- /* Recursively hunt for required loads of DP. */
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
- {
- if (*format_ptr++ == 'e') /* rtx expression */
- if (c4x_scan_for_ldp (&XEXP (operand, i), insn, operand0))
- break;
- }
- return 0;
-}
-
-
-/* The last instruction in a repeat block cannot be a Bcond, DBcound,
- CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS.
-
- None of the last four instructions from the bottom of the block can
- be a BcondD, BRD, DBcondD, RPTBD, LAJ, LAJcond, LATcond, BcondAF,
- BcondAT or RETIcondD.
-
- This routine scans the four previous insns for a jump insn, and if
- one is found, returns 1 so that we bung in a nop instruction.
- This simple minded strategy will add a nop, when it may not
- be required. Say when there is a JUMP_INSN near the end of the
- block that doesn't get converted into a delayed branch.
-
- Note that we cannot have a call insn, since we don't generate
- repeat loops with calls in them (although I suppose we could, but
- there's no benefit.)
-
- !!! FIXME. The rptb_top insn may be sucked into a SEQUENCE. */
-
-int
-c4x_rptb_nop_p (insn)
- rtx insn;
-{
- rtx start_label;
- int i;
-
- /* Extract the start label from the jump pattern (rptb_end). */
- start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
-
- /* If there is a label at the end of the loop we must insert
- a NOP. */
- insn = prev_nonnote_insn (insn);
- if (GET_CODE (insn) == CODE_LABEL)
- return 1;
-
- for (i = 0; i < 4; i++)
- {
- /* Search back for prev non-note and non-label insn. */
- while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER)
- {
- if (insn == start_label)
- return i == 0;
-
- insn = PREV_INSN (insn);
- };
-
- /* If we have a jump instruction we should insert a NOP. If we
- hit repeat block top we should only insert a NOP if the loop
- is empty. */
- if (GET_CODE (insn) == JUMP_INSN)
- return 1;
- insn = PREV_INSN (insn);
- }
- return 0;
-}
-
-
-void
-c4x_rptb_insert (insn)
- rtx insn;
-{
- rtx end_label;
- rtx start_label;
- rtx count_reg;
-
- /* If the count register has not been allocated to RC, say if
- there is a movstr pattern in the loop, then do not insert a
- RPTB instruction. Instead we emit a decrement and branch
- at the end of the loop. */
- count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0);
- if (REGNO (count_reg) != RC_REGNO)
- return;
-
- /* Extract the start label from the jump pattern (rptb_end). */
- start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
-
- /* We'll have to update the basic blocks. */
- end_label = gen_label_rtx ();
- emit_label_after (end_label, insn);
-
- for (; insn; insn = PREV_INSN (insn))
- if (insn == start_label)
- break;
- if (! insn)
- fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label);
-
- /* We'll have to update the basic blocks. */
- emit_insn_before (gen_rptb_top (start_label, end_label), insn);
-}
-
-/* This function is a C4x special. It scans through all the insn
- operands looking for places where the DP register needs to be
- reloaded and for large immediate operands that need to be converted
- to memory references. The latter should be avoidable with proper
- definition of patterns in machine description. We come here right
- near the end of things, immediately before delayed branch
- scheduling. */
-
-void
-c4x_process_after_reload (first)
- rtx first;
-{
- rtx insn;
- int i;
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- /* Look for insn. */
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- int insn_code_number;
-
- insn_code_number = recog_memoized (insn);
-
- if (insn_code_number < 0)
- continue;
-
- /* Insert the RTX for RPTB at the top of the loop
- and a label at the end of the loop. */
- if (insn_code_number == CODE_FOR_rptb_end)
- c4x_rptb_insert(insn);
-
- /* We split all insns here if they have a # for the output
- template if we are using the big memory model since there
- is a chance that we might be accessing memory across a
- page boundary. */
-
- if (! TARGET_SMALL)
- {
- char *template;
-
- template = insn_template[insn_code_number];
- if (template && template[0] == '#' && template[1] == '\0')
- {
- rtx new = try_split (PATTERN(insn), insn, 0);
-
- /* If we didn't split the insn, go away. */
- if (new == insn && PATTERN (new) == PATTERN(insn))
- fatal_insn ("Couldn't split pattern", insn);
-
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-
- /* Do we have to update the basic block info here?
- Maybe reorg wants it sorted out... */
-
- /* Continue with the first of the new insns generated
- by the split. */
- insn = new;
-
- insn_code_number = recog_memoized (insn);
-
- if (insn_code_number < 0)
- continue;
- }
- }
-
- /* Ignore jumps and calls. */
- if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- continue;
-
- insn_extract (insn);
- for (i = 0; i < insn_n_operands[insn_code_number]; i++)
- if (c4x_scan_for_ldp (recog_operand_loc[i], insn,
- recog_operand[0]))
- break;
- }
- }
-}
-
-
-static int
-c4x_a_register (op)
- rtx op;
-{
- return REG_P (op) && IS_ADDR_OR_PSEUDO_REGNO (op);
-}
-
-
-static int
-c4x_x_register (op)
- rtx op;
-{
- return REG_P (op) && IS_INDEX_OR_PSEUDO_REGNO (op);
-}
-
-
-static int
-c4x_int_constant (op)
- rtx op;
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return GET_MODE (op) == VOIDmode
- || GET_MODE_CLASS (op) == MODE_INT
- || GET_MODE_CLASS (op) == MODE_PARTIAL_INT;
-}
-
-
-static int
-c4x_float_constant (op)
- rtx op;
-{
- if (GET_CODE (op) != CONST_DOUBLE)
- return 0;
- return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;
-}
-
-
-int
-c4x_H_constant (op)
- rtx op;
-{
- return c4x_float_constant (op) && c4x_immed_float_p (op);
-}
-
-
-int
-c4x_I_constant (op)
- rtx op;
-{
- return c4x_int_constant (op) && IS_INT16_CONST (INTVAL (op));
-}
-
-
-int
-c4x_J_constant (op)
- rtx op;
-{
- if (TARGET_C3X)
- return 0;
- return c4x_int_constant (op) && IS_INT8_CONST (INTVAL (op));
-}
-
-
-static int
-c4x_K_constant (op)
- rtx op;
-{
- if (TARGET_C3X)
- return 0;
- return c4x_int_constant (op) && IS_INT5_CONST (INTVAL (op));
-}
-
-
-int
-c4x_L_constant (op)
- rtx op;
-{
- return c4x_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
-}
-
-
-static int
-c4x_N_constant (op)
- rtx op;
-{
- return c4x_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
-}
-
-
-static int
-c4x_O_constant (op)
- rtx op;
-{
- return c4x_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
-}
-
-
-/* The constraints do not have to check the register class,
- except when needed to discriminate between the constraints.
- The operand has been checked by the predicates to be valid. */
-
-/* ARx + 9-bit signed const or IRn
- *ARx, *+ARx(n), *-ARx(n), *+ARx(IRn), *-Arx(IRn) for -256 < n < 256
- We don't include the pre/post inc/dec forms here since
- they are handled by the <> constraints. */
-
-int
-c4x_Q_constraint (op)
- rtx op;
-{
- enum machine_mode mode = GET_MODE (op);
-
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case REG:
- return 1;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (! REG_P (op0))
- return 0;
-
- if (REG_P (op1))
- return 1;
-
- if (GET_CODE (op1) != CONST_INT)
- return 0;
-
- /* HImode and HFmode must be offsettable. */
- if (mode == HImode || mode == HFmode)
- return IS_DISP8_OFF_CONST (INTVAL (op1));
-
- return IS_DISP8_CONST (INTVAL (op1));
- }
- break;
- default:
- break;
- }
- return 0;
-}
-
-
-/* ARx + 5-bit unsigned const
- *ARx, *+ARx(n) for n < 32 */
-
-int
-c4x_R_constraint (op)
- rtx op;
-{
- enum machine_mode mode = GET_MODE (op);
-
- if (TARGET_C3X)
- return 0;
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case REG:
- return 1;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (! REG_P (op0))
- return 0;
-
- if (GET_CODE (op1) != CONST_INT)
- return 0;
-
- /* HImode and HFmode must be offsettable. */
- if (mode == HImode || mode == HFmode)
- return IS_UINT5_CONST (INTVAL (op1) + 1);
-
- return IS_UINT5_CONST (INTVAL (op1));
- }
- break;
- default:
- break;
- }
- return 0;
-}
-
-
-static int
-c4x_R_indirect (op)
- rtx op;
-{
- enum machine_mode mode = GET_MODE (op);
-
- if (TARGET_C3X || GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case REG:
- return IS_ADDR_OR_PSEUDO_REGNO (op);
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- /* HImode and HFmode must be offsettable. */
- if (mode == HImode || mode == HFmode)
- return IS_ADDR_OR_PSEUDO_REGNO (op0)
- && GET_CODE (op1) == CONST_INT
- && IS_UINT5_CONST (INTVAL (op1) + 1);
-
- return REG_P (op0)
- && IS_ADDR_OR_PSEUDO_REGNO (op0)
- && GET_CODE (op1) == CONST_INT
- && IS_UINT5_CONST (INTVAL (op1));
- }
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-
-/* ARx + 1-bit unsigned const or IRn
- *ARx, *+ARx(1), *-ARx(1), *+ARx(IRn), *-Arx(IRn)
- We don't include the pre/post inc/dec forms here since
- they are handled by the <> constraints. */
-
-int
-c4x_S_constraint (op)
- rtx op;
-{
- enum machine_mode mode = GET_MODE (op);
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case REG:
- return 1;
-
- case PRE_MODIFY:
- case POST_MODIFY:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
- || (op0 != XEXP (op1, 0)))
- return 0;
-
- op0 = XEXP (op1, 0);
- op1 = XEXP (op1, 1);
- return REG_P (op0) && REG_P (op1);
- /* pre or post_modify with a displacement of 0 or 1
- should not be generated. */
- }
- break;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (!REG_P (op0))
- return 0;
-
- if (REG_P (op1))
- return 1;
-
- if (GET_CODE (op1) != CONST_INT)
- return 0;
-
- /* HImode and HFmode must be offsettable. */
- if (mode == HImode || mode == HFmode)
- return IS_DISP1_OFF_CONST (INTVAL (op1));
-
- return IS_DISP1_CONST (INTVAL (op1));
- }
- break;
- default:
- break;
- }
- return 0;
-}
-
-
-static int
-c4x_S_indirect (op)
- rtx op;
-{
- enum machine_mode mode = GET_MODE (op);
- if (GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case PRE_DEC:
- case POST_DEC:
- if (mode != QImode && mode != QFmode)
- return 0;
- case PRE_INC:
- case POST_INC:
- op = XEXP (op, 0);
-
- case REG:
- return IS_ADDR_OR_PSEUDO_REGNO (op);
-
- case PRE_MODIFY:
- case POST_MODIFY:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (mode != QImode && mode != QFmode)
- return 0;
-
- if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
- || (op0 != XEXP (op1, 0)))
- return 0;
-
- op0 = XEXP (op1, 0);
- op1 = XEXP (op1, 1);
- return REG_P (op0) && IS_ADDR_OR_PSEUDO_REGNO (op0)
- && REG_P (op1) && IS_INDEX_OR_PSEUDO_REGNO (op1);
- /* pre or post_modify with a displacement of 0 or 1
- should not be generated. */
- }
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (REG_P (op0))
- {
- /* HImode and HFmode must be offsettable. */
- if (mode == HImode || mode == HFmode)
- return IS_ADDR_OR_PSEUDO_REGNO (op0)
- && GET_CODE (op1) == CONST_INT
- && IS_DISP1_OFF_CONST (INTVAL (op1));
-
- if (REG_P (op1))
- return (IS_INDEX_OR_PSEUDO_REGNO (op1)
- && IS_ADDR_OR_PSEUDO_REGNO (op0))
- || (IS_ADDR_OR_PSEUDO_REGNO (op1)
- && IS_INDEX_OR_PSEUDO_REGNO (op0));
-
- return IS_ADDR_OR_PSEUDO_REGNO (op0)
- && GET_CODE (op1) == CONST_INT
- && IS_DISP1_CONST (INTVAL (op1));
- }
- }
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-
-/* Symbol ref. */
-
-int
-c4x_T_constraint (op)
- rtx op;
-{
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
-
- if ((GET_CODE (op) == PLUS)
- && (GET_CODE (XEXP (op, 0)) == REG)
- && (REGNO (XEXP (op, 0)) == DP_REGNO))
- {
- op = XEXP (op, 1);
- }
- else if ((GET_CODE (op) == PLUS)
- && (GET_CODE (XEXP (op, 0)) == PLUS)
- && (GET_CODE (XEXP (XEXP (op, 0), 0)) == USE))
- {
- op = XEXP (op, 1);
- }
- else if ((GET_CODE (op) == PLUS) && (GET_CODE (XEXP (op, 0)) == USE))
- {
- op = XEXP (op, 1);
- }
-
- /* Don't allow direct addressing to an arbitrary constant. */
- if (GET_CODE (op) == CONST
- && GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
- return 1;
-
- return GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF;
-}
-
-
-int
-c4x_autoinc_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (GET_CODE (op) == MEM)
- {
- enum rtx_code code = GET_CODE (XEXP (op, 0));
-
- if (code == PRE_INC
- || code == PRE_DEC
- || code == POST_INC
- || code == POST_DEC
- || code == PRE_MODIFY
- || code == POST_MODIFY
- )
- return 1;
- }
- return 0;
-}
-
-
-/* Match any operand. */
-
-int
-any_operand (op, mode)
- register rtx op ATTRIBUTE_UNUSED;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return 1;
-}
-
-
-/* Nonzero if OP is a floating point value with value 0.0. */
-
-int
-fp_zero_operand (op)
- rtx op;
-{
- REAL_VALUE_TYPE r;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- return REAL_VALUES_EQUAL (r, dconst0);
-}
-
-
-int
-const_operand (op, mode)
- register rtx op;
- register enum machine_mode mode;
-{
- switch (mode)
- {
- case QFmode:
- case HFmode:
- if (GET_CODE (op) != CONST_DOUBLE
- || GET_MODE (op) != mode
- || GET_MODE_CLASS (mode) != MODE_FLOAT)
- return 0;
-
- return c4x_immed_float_p (op);
-
-#if Pmode != QImode
- case Pmode:
-#endif
- case QImode:
- if (GET_CODE (op) != CONST_INT
- || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
- || GET_MODE_CLASS (mode) != MODE_INT)
- return 0;
-
- return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
-
- case HImode:
- return 0;
-
- default:
- return 0;
- }
-}
-
-
-int
-stik_const_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return c4x_K_constant (op);
-}
-
-
-int
-not_const_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return c4x_N_constant (op);
-}
-
-
-int
-reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return register_operand (op, mode);
-}
-
-int
-reg_imm_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (REG_P (op) || CONSTANT_P (op))
- return 1;
- return 0;
-}
-
-int
-not_modify_reg (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (REG_P (op) || CONSTANT_P (op))
- return 1;
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case REG:
- return 1;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (! REG_P (op0))
- return 0;
-
- if (REG_P (op1) || GET_CODE (op1) == CONST_INT)
- return 1;
- }
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
- default:
- break;
- }
- return 0;
-}
-
-int
-not_rc_reg (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (REG_P (op) && REGNO (op) == RC_REGNO)
- return 0;
- return 1;
-}
-
-/* Extended precision register R0-R1. */
-
-int
-r0r1_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R0R1_OR_PSEUDO_REGNO (op);
-}
-
-
-/* Extended precision register R2-R3. */
-
-int
-r2r3_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R2R3_OR_PSEUDO_REGNO (op);
-}
-
-
-/* Low extended precision register R0-R7. */
-
-int
-ext_low_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REGNO (op);
-}
-
-
-/* Extended precision register. */
-
-int
-ext_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (! REG_P (op))
- return 0;
- return IS_EXT_OR_PSEUDO_REGNO (op);
-}
-
-
-/* Standard precision register. */
-
-int
-std_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_STD_OR_PSEUDO_REGNO (op);
-}
-
-
-/* Address register. */
-
-int
-addr_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- return c4x_a_register (op);
-}
-
-
-/* Index register. */
-
-int
-index_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return c4x_x_register (op);
-}
-
-
-/* DP register. */
-
-int
-dp_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return REG_P (op) && IS_DP_OR_PSEUDO_REGNO (op);
-}
-
-
-/* SP register. */
-
-int
-sp_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return REG_P (op) && IS_SP_OR_PSEUDO_REGNO (op);
-}
-
-
-/* ST register. */
-
-int
-st_reg_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return REG_P (op) && IS_ST_OR_PSEUDO_REGNO (op);
-}
-
-
-/* RC register. */
-
-int
-rc_reg_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return REG_P (op) && IS_RC_OR_PSEUDO_REGNO (op);
-}
-
-
-int
-call_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case REG:
- return 1;
- default:
- }
- return 0;
-}
-
-
-/* Check src operand of two operand arithmetic instructions. */
-
-int
-src_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (REG_P (op))
- return reg_operand (op, mode);
-
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- /* We could allow certain CONST_INT values for HImode... */
- if (GET_CODE (op) == CONST_INT)
- return (mode == QImode || mode == Pmode) && c4x_I_constant (op);
-
- /* We don't like CONST_DOUBLE integers. */
- if (GET_CODE (op) == CONST_DOUBLE)
- return c4x_H_constant (op);
-
- return general_operand (op, mode);
-}
-
-
-int
-src_hi_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (c4x_O_constant (op))
- return 1;
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand logical instructions. */
-
-int
-lsrc_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("Mode not QImode", op);
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_J_constant (op);
-
- return general_operand (op, mode);
-}
-
-
-/* Check src operand of two operand tricky instructions. */
-
-int
-tsrc_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("Mode not QImode", op);
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
-
- return general_operand (op, mode);
-}
-
-
-int
-reg_or_const_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return reg_operand (op, mode) || const_operand (op, mode);
-}
-
-
-/* Check for indirect operands allowable in parallel instruction. */
-
-int
-par_ind_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- return c4x_S_indirect (op);
-}
-
-
-/* Check for operands allowable in parallel instruction. */
-
-int
-parallel_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
-}
-
-
-static void
-c4x_S_address_parse (op, base, incdec, index, disp)
- rtx op;
- int *base;
- int *incdec;
- int *index;
- int *disp;
-{
- *base = 0;
- *incdec = 0;
- *index = 0;
- *disp = 0;
-
- if (GET_CODE (op) != MEM)
- fatal_insn ("Invalid indirect memory address", op);
-
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case PRE_DEC:
- *base = REGNO (XEXP (op, 0));
- *incdec = 1;
- *disp = -1;
- return;
-
- case POST_DEC:
- *base = REGNO (XEXP (op, 0));
- *incdec = 1;
- *disp = 0;
- return;
-
- case PRE_INC:
- *base = REGNO (XEXP (op, 0));
- *incdec = 1;
- *disp = 1;
- return;
-
- case POST_INC:
- *base = REGNO (XEXP (op, 0));
- *incdec = 1;
- *disp = 0;
- return;
-
- case POST_MODIFY:
- *base = REGNO (XEXP (op, 0));
- if (REG_P (XEXP (XEXP (op, 1), 1)))
- {
- *index = REGNO (XEXP (XEXP (op, 1), 1));
- *disp = 0; /* ??? */
- }
- else
- *disp = INTVAL (XEXP (XEXP (op, 1), 1));
- *incdec = 1;
- return;
-
- case PRE_MODIFY:
- *base = REGNO (XEXP (op, 0));
- if (REG_P (XEXP (XEXP (op, 1), 1)))
- {
- *index = REGNO (XEXP (XEXP (op, 1), 1));
- *disp = 1; /* ??? */
- }
- else
- *disp = INTVAL (XEXP (XEXP (op, 1), 1));
- *incdec = 1;
-
- return;
-
- case REG:
- *base = REGNO (op);
- return;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (c4x_a_register (op0))
- {
- if (c4x_x_register (op1))
- {
- *base = REGNO (op0);
- *index = REGNO (op1);
- return;
- }
- else if ((GET_CODE (op1) == CONST_INT
- && IS_DISP1_CONST (INTVAL (op1))))
- {
- *base = REGNO (op0);
- *disp = INTVAL (op1);
- return;
- }
- }
- else if (c4x_x_register (op0) && c4x_a_register (op1))
- {
- *base = REGNO (op1);
- *index = REGNO (op0);
- return;
- }
- }
- /* Fallthrough */
-
- default:
- fatal_insn ("Invalid indirect (S) memory address", op);
- }
-}
-
-
-int
-c4x_address_conflict (op0, op1, store0, store1)
- rtx op0;
- rtx op1;
- int store0;
- int store1;
-{
- int base0;
- int base1;
- int incdec0;
- int incdec1;
- int index0;
- int index1;
- int disp0;
- int disp1;
-
- if (MEM_VOLATILE_P (op0) && MEM_VOLATILE_P (op1))
- return 1;
-
- c4x_S_address_parse (op0, &base0, &incdec0, &index0, &disp0);
- c4x_S_address_parse (op1, &base1, &incdec1, &index1, &disp1);
-
- if (store0 && store1)
- {
- /* If we have two stores in parallel to the same address, then
- the C4x only executes one of the stores. This is unlikely to
- cause problems except when writing to a hardware device such
- as a FIFO since the second write will be lost. The user
- should flag the hardware location as being volatile so that
- we don't do this optimisation. While it is unlikely that we
- have an aliased address if both locations are not marked
- volatile, it is probably safer to flag a potential conflict
- if either location is volatile. */
- if (! flag_argument_noalias)
- {
- if (MEM_VOLATILE_P (op0) || MEM_VOLATILE_P (op1))
- return 1;
- }
- }
-
- /* If have a parallel load and a store to the same address, the load
- is performed first, so there is no conflict. Similarly, there is
- no conflict if have parallel loads from the same address. */
-
- /* Cannot use auto increment or auto decrement twice for same
- base register. */
- if (base0 == base1 && incdec0 && incdec0)
- return 1;
-
- /* It might be too confusing for GCC if we have use a base register
- with a side effect and a memory reference using the same register
- in parallel. */
- if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1))
- return 1;
-
- /* We can not optimize the case where op1 and op2 refer to the same
- address. */
- if (base0 == base1 && disp0 == disp1 && index0 == index1)
- return 1;
-
- /* No conflict. */
- return 0;
-}
-
-
-/* Check for while loop inside a decrement and branch loop. */
-
-int
-c4x_label_conflict (insn, jump, db)
- rtx insn;
- rtx jump;
- rtx db;
-{
- while (insn)
- {
- if (GET_CODE (insn) == CODE_LABEL)
- {
- if (CODE_LABEL_NUMBER (jump) == CODE_LABEL_NUMBER (insn))
- return 1;
- if (CODE_LABEL_NUMBER (db) == CODE_LABEL_NUMBER (insn))
- return 0;
- }
- insn = PREV_INSN (insn);
- }
- return 1;
-}
-
-
-/* Validate combination of operands for parallel load/store instructions. */
-
-int
-valid_parallel_load_store (operands, mode)
- rtx *operands;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- rtx op0 = operands[0];
- rtx op1 = operands[1];
- rtx op2 = operands[2];
- rtx op3 = operands[3];
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
- if (GET_CODE (op1) == SUBREG)
- op1 = SUBREG_REG (op1);
- if (GET_CODE (op2) == SUBREG)
- op2 = SUBREG_REG (op2);
- if (GET_CODE (op3) == SUBREG)
- op3 = SUBREG_REG (op3);
-
- /* The patterns should only allow ext_low_reg_operand() or
- par_ind_operand() operands. Thus of the 4 operands, only 2
- should be REGs and the other 2 should be MEMs. */
-
- /* This test prevents the multipack pass from using this pattern if
- op0 is used as an index or base register in op2 or op3, since
- this combination will require reloading. */
- if (GET_CODE (op0) == REG
- && ((GET_CODE (op2) == MEM && reg_mentioned_p (op0, XEXP (op2, 0)))
- || (GET_CODE (op3) == MEM && reg_mentioned_p (op0, XEXP (op3, 0)))))
- return 0;
-
- /* LDI||LDI */
- if (GET_CODE (op0) == REG && GET_CODE (op2) == REG)
- return (REGNO (op0) != REGNO (op2))
- && GET_CODE (op1) == MEM && GET_CODE (op3) == MEM
- && ! c4x_address_conflict (op1, op3, 0, 0);
-
- /* STI||STI */
- if (GET_CODE (op1) == REG && GET_CODE (op3) == REG)
- return GET_CODE (op0) == MEM && GET_CODE (op2) == MEM
- && ! c4x_address_conflict (op0, op2, 1, 1);
-
- /* LDI||STI */
- if (GET_CODE (op0) == REG && GET_CODE (op3) == REG)
- return GET_CODE (op1) == MEM && GET_CODE (op2) == MEM
- && ! c4x_address_conflict (op1, op2, 0, 1);
-
- /* STI||LDI */
- if (GET_CODE (op1) == REG && GET_CODE (op2) == REG)
- return GET_CODE (op0) == MEM && GET_CODE (op3) == MEM
- && ! c4x_address_conflict (op0, op3, 1, 0);
-
- return 0;
-}
-
-
-int
-valid_parallel_operands_4 (operands, mode)
- rtx *operands;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- rtx op0 = operands[0];
- rtx op2 = operands[2];
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
- if (GET_CODE (op2) == SUBREG)
- op2 = SUBREG_REG (op2);
-
- /* This test prevents the multipack pass from using this pattern if
- op0 is used as an index or base register in op2, since this combination
- will require reloading. */
- if (GET_CODE (op0) == REG
- && GET_CODE (op2) == MEM
- && reg_mentioned_p (op0, XEXP (op2, 0)))
- return 0;
-
- return 1;
-}
-
-
-int
-valid_parallel_operands_5 (operands, mode)
- rtx *operands;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- int regs = 0;
- rtx op0 = operands[0];
- rtx op1 = operands[1];
- rtx op2 = operands[2];
- rtx op3 = operands[3];
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
- if (GET_CODE (op1) == SUBREG)
- op1 = SUBREG_REG (op1);
- if (GET_CODE (op2) == SUBREG)
- op2 = SUBREG_REG (op2);
-
- /* The patterns should only allow ext_low_reg_operand() or
- par_ind_operand() operands. Operands 1 and 2 may be commutative
- but only one of them can be a register. */
- if (GET_CODE (op1) == REG)
- regs++;
- if (GET_CODE (op2) == REG)
- regs++;
-
- if (regs != 1)
- return 0;
-
- /* This test prevents the multipack pass from using this pattern if
- op0 is used as an index or base register in op3, since this combination
- will require reloading. */
- if (GET_CODE (op0) == REG
- && GET_CODE (op3) == MEM
- && reg_mentioned_p (op0, XEXP (op3, 0)))
- return 0;
-
- return 1;
-}
-
-
-int
-valid_parallel_operands_6 (operands, mode)
- rtx *operands;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- int regs = 0;
- rtx op0 = operands[0];
- rtx op1 = operands[1];
- rtx op2 = operands[2];
- rtx op4 = operands[4];
- rtx op5 = operands[5];
-
- if (GET_CODE (op1) == SUBREG)
- op1 = SUBREG_REG (op1);
- if (GET_CODE (op2) == SUBREG)
- op2 = SUBREG_REG (op2);
- if (GET_CODE (op4) == SUBREG)
- op4 = SUBREG_REG (op4);
- if (GET_CODE (op5) == SUBREG)
- op5 = SUBREG_REG (op5);
-
- /* The patterns should only allow ext_low_reg_operand() or
- par_ind_operand() operands. Thus of the 4 input operands, only 2
- should be REGs and the other 2 should be MEMs. */
-
- if (GET_CODE (op1) == REG)
- regs++;
- if (GET_CODE (op2) == REG)
- regs++;
- if (GET_CODE (op4) == REG)
- regs++;
- if (GET_CODE (op5) == REG)
- regs++;
-
- /* The new C30/C40 silicon dies allow 3 regs of the 4 input operands.
- Perhaps we should count the MEMs as well? */
- if (regs != 2)
- return 0;
-
- /* This test prevents the multipack pass from using this pattern if
- op0 is used as an index or base register in op4 or op5, since
- this combination will require reloading. */
- if (GET_CODE (op0) == REG
- && ((GET_CODE (op4) == MEM && reg_mentioned_p (op0, XEXP (op4, 0)))
- || (GET_CODE (op5) == MEM && reg_mentioned_p (op0, XEXP (op5, 0)))))
- return 0;
-
- return 1;
-}
-
-
-/* Validate combination of src operands. Note that the operands have
- been screened by the src_operand predicate. We just have to check
- that the combination of operands is valid. If FORCE is set, ensure
- that the destination regno is valid if we have a 2 operand insn. */
-
-static int
-c4x_valid_operands (code, operands, mode, force)
- enum rtx_code code;
- rtx *operands;
- enum machine_mode mode;
- int force;
-{
- rtx op1;
- rtx op2;
- enum rtx_code code1;
- enum rtx_code code2;
-
- if (code == COMPARE)
- {
- op1 = operands[0];
- op2 = operands[1];
- }
- else
- {
- op1 = operands[1];
- op2 = operands[2];
- }
-
- if (GET_CODE (op1) == SUBREG)
- op1 = SUBREG_REG (op1);
- if (GET_CODE (op2) == SUBREG)
- op2 = SUBREG_REG (op2);
-
- code1 = GET_CODE (op1);
- code2 = GET_CODE (op2);
-
- if (code1 == REG && code2 == REG)
- return 1;
-
- if (code1 == MEM && code2 == MEM)
- {
- if (c4x_S_indirect (op1, mode) && c4x_S_indirect (op2, mode))
- return 1;
- return c4x_R_indirect (op1, mode) && c4x_R_indirect (op2, mode);
- }
-
- if (code1 == code2)
- return 0;
-
- if (code1 == REG)
- {
- switch (code2)
- {
- case CONST_INT:
- if (c4x_J_constant (op2) && c4x_R_indirect (op1))
- return 1;
- break;
-
- case CONST_DOUBLE:
- if (! c4x_H_constant (op2))
- return 0;
- break;
-
- /* Any valid memory operand screened by src_operand is OK. */
- case MEM:
-
- /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
- into a stack slot memory address comprising a PLUS and a
- constant. */
- case ADDRESSOF:
- break;
-
- default:
- fatal ("c4x_valid_operands: Internal error");
- break;
- }
-
- /* Check that we have a valid destination register for a two operand
- instruction. */
- return ! force || code == COMPARE || REGNO (op1) == REGNO (operands[0]);
- }
-
- /* We assume MINUS is commutative since the subtract patterns
- also support the reverse subtract instructions. Since op1
- is not a register, and op2 is a register, op1 can only
- be a restricted memory operand for a shift instruction. */
- if (code == ASHIFTRT || code == LSHIFTRT
- || code == ASHIFT || code == COMPARE)
- return code2 == REG
- && (c4x_S_indirect (op1) || c4x_R_indirect (op1));
-
- switch (code1)
- {
- case CONST_INT:
- if (c4x_J_constant (op1) && c4x_R_indirect (op2))
- return 1;
- break;
-
- case CONST_DOUBLE:
- if (! c4x_H_constant (op1))
- return 0;
- break;
-
- /* Any valid memory operand screened by src_operand is OK. */
- case MEM:
-
- /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
- into a stack slot memory address comprising a PLUS and a
- constant. */
- case ADDRESSOF:
- break;
-
- default:
- fatal ("c4x_valid_operands: Internal error");
- break;
- }
-
- /* Check that we have a valid destination register for a two operand
- instruction. */
- return ! force || REGNO (op1) == REGNO (operands[0]);
-}
-
-
-int valid_operands (code, operands, mode)
- enum rtx_code code;
- rtx *operands;
- enum machine_mode mode;
-{
-
- /* If we are not optimizing then we have to let anything go and let
- reload fix things up. instantiate_decl in function.c can produce
- invalid insns by changing the offset of a memory operand from a
- valid one into an invalid one, when the second operand is also a
- memory operand. The alternative is not to allow two memory
- operands for an insn when not optimizing. The problem only rarely
- occurs, for example with the C-torture program DFcmp.c */
-
- return ! optimize || c4x_valid_operands (code, operands, mode, 0);
-}
-
-
-int
-legitimize_operands (code, operands, mode)
- enum rtx_code code;
- rtx *operands;
- enum machine_mode mode;
-{
- /* Compare only has 2 operands. */
- if (code == COMPARE)
- {
- /* During RTL generation, force constants into pseudos so that
- they can get hoisted out of loops. This will tie up an extra
- register but can save an extra cycle. Only do this if loop
- optimisation enabled. (We cannot pull this trick for add and
- sub instructions since the flow pass won't find
- autoincrements etc.) This allows us to generate compare
- instructions like CMPI R0, *AR0++ where R0 = 42, say, instead
- of LDI *AR0++, R0; CMPI 42, R0.
-
- Note that expand_binops will try to load an expensive constant
- into a register if it is used within a loop. Unfortunately,
- the cost mechanism doesn't allow us to look at the other
- operand to decide whether the constant is expensive. */
-
- if (! reload_in_progress
- && TARGET_HOIST
- && optimize > 0
- && ((GET_CODE (operands[1]) == CONST_INT
- && ! c4x_J_constant (operands[1])
- && INTVAL (operands[1]) != 0)
- || GET_CODE (operands[1]) == CONST_DOUBLE))
- operands[1] = force_reg (mode, operands[1]);
-
- if (! reload_in_progress
- && ! c4x_valid_operands (code, operands, mode, 0))
- operands[0] = force_reg (mode, operands[0]);
- return 1;
- }
-
- /* We cannot do this for ADDI/SUBI insns since we will
- defeat the flow pass from finding autoincrement addressing
- opportunities. */
- if (! reload_in_progress
- && ! ((code == PLUS || code == MINUS) && mode == Pmode)
- && (TARGET_HOIST && optimize > 1
- && ((GET_CODE (operands[2]) == CONST_INT
- && ! c4x_J_constant (operands[2])
- && INTVAL (operands[2]) != 0)
- || GET_CODE (operands[2]) == CONST_DOUBLE)))
- operands[2] = force_reg (mode, operands[2]);
-
- /* We can get better code on a C30 if we force constant shift counts
- into a register. This way they can get hoisted out of loops,
- tying up a register, but saving an instruction. The downside is
- that they may get allocated to an address or index register, and
- thus we will get a pipeline conflict if there is a nearby
- indirect address using an address register.
-
- Note that expand_binops will not try to load an expensive constant
- into a register if it is used within a loop for a shift insn. */
-
- if (! reload_in_progress
- && ! c4x_valid_operands (code, operands, mode, TARGET_FORCE))
- {
- /* If the operand combination is invalid, we force operand1 into a
- register, preventing reload from having doing to do this at a
- later stage. */
- operands[1] = force_reg (mode, operands[1]);
- if (TARGET_FORCE)
- {
- emit_move_insn (operands[0], operands[1]);
- operands[1] = copy_rtx (operands[0]);
- }
- else
- {
- /* Just in case... */
- if (! c4x_valid_operands (code, operands, mode, 0))
- operands[2] = force_reg (mode, operands[2]);
- }
- }
-
- /* Right shifts require a negative shift count, but GCC expects
- a positive count, so we emit a NEG. */
- if ((code == ASHIFTRT || code == LSHIFTRT)
- && (GET_CODE (operands[2]) != CONST_INT))
- operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2]));
-
- return 1;
-}
-
-
-/* The following predicates are used for instruction scheduling. */
-
-int
-group1_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_GROUP1_REG (REGNO (op));
-}
-
-
-int
-group1_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- if (GET_CODE (op) == MEM)
- {
- op = XEXP (op, 0);
- if (GET_CODE (op) == PLUS)
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (((GET_CODE (op0) == REG) && IS_GROUP1_REGNO (op0))
- || ((GET_CODE (op1) == REG) && IS_GROUP1_REGNO (op1)))
- return 1;
- }
- else if ((REG_P (op)) && IS_GROUP1_REGNO (op))
- return 1;
- }
-
- return 0;
-}
-
-
-/* Return true if any one of the address registers. */
-
-int
-arx_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_ADDR_REGNO (op);
-}
-
-
-static int
-c4x_arn_reg_operand (op, mode, regno)
- rtx op;
- enum machine_mode mode;
- int regno;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && (REGNO (op) == regno);
-}
-
-
-static int
-c4x_arn_mem_operand (op, mode, regno)
- rtx op;
- enum machine_mode mode;
- int regno;
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- if (GET_CODE (op) == MEM)
- {
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case PRE_DEC:
- case POST_DEC:
- case PRE_INC:
- case POST_INC:
- op = XEXP (op, 0);
-
- case REG:
- if (REG_P (op) && (REGNO (op) == regno))
- return 1;
- break;
-
- case PRE_MODIFY:
- case POST_MODIFY:
- if (REG_P (XEXP (op, 0)) && (REGNO (XEXP (op, 0)) == regno))
- return 1;
- if (REG_P (XEXP (XEXP (op, 1), 1))
- && (REGNO (XEXP (XEXP (op, 1), 1)) == regno))
- return 1;
- break;
-
- case PLUS:
- {
- rtx op0 = XEXP (op, 0);
- rtx op1 = XEXP (op, 1);
-
- if (((GET_CODE (op0) == REG) && (REGNO (op0) == regno))
- || ((GET_CODE (op1) == REG) && (REGNO (op1) == regno)))
- return 1;
- }
- break;
- default:
- break;
- }
- }
- return 0;
-}
-
-
-int
-ar0_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR0_REGNO);
-}
-
-
-int
-ar0_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR0_REGNO);
-}
-
-
-int
-ar1_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR1_REGNO);
-}
-
-
-int
-ar1_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR1_REGNO);
-}
-
-
-int
-ar2_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR2_REGNO);
-}
-
-
-int
-ar2_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR2_REGNO);
-}
-
-
-int
-ar3_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR3_REGNO);
-}
-
-
-int
-ar3_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR3_REGNO);
-}
-
-
-int
-ar4_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR4_REGNO);
-}
-
-
-int
-ar4_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR4_REGNO);
-}
-
-
-int
-ar5_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR5_REGNO);
-}
-
-
-int
-ar5_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR5_REGNO);
-}
-
-
-int
-ar6_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR6_REGNO);
-}
-
-
-int
-ar6_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR6_REGNO);
-}
-
-
-int
-ar7_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, AR7_REGNO);
-}
-
-
-int
-ar7_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, AR7_REGNO);
-}
-
-
-int
-ir0_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, IR0_REGNO);
-}
-
-
-int
-ir0_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, IR0_REGNO);
-}
-
-
-int
-ir1_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_reg_operand (op, mode, IR1_REGNO);
-}
-
-
-int
-ir1_mem_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return c4x_arn_mem_operand (op, mode, IR1_REGNO);
-}
-
-
-/* We allow autoincrement addressing. */
-
-rtx
-c4x_operand_subword (op, i, validate_address, mode)
- rtx op;
- int i;
- int validate_address;
- enum machine_mode mode;
-{
- if (mode != HImode && mode != HFmode)
- fatal_insn ("c4x_operand_subword: invalid mode", op);
-
- if (mode == HFmode && REG_P (op))
- fatal_insn ("c4x_operand_subword: invalid operand", op);
-
- if (GET_CODE (op) == MEM)
- {
- enum rtx_code code = GET_CODE (XEXP (op, 0));
- enum machine_mode mode = GET_MODE (XEXP (op, 0));
-
- switch (code)
- {
- case POST_INC:
- case PRE_INC:
- if (mode == HImode)
- mode = QImode;
- else if (mode == HFmode)
- mode = QFmode;
- return gen_rtx_MEM (mode, XEXP (op, 0));
-
- case POST_DEC:
- case PRE_DEC:
- case PRE_MODIFY:
- case POST_MODIFY:
- /* We could handle these with some difficulty.
- e.g., *p-- => *(p-=2); *(p+1). */
- fatal_insn ("c4x_operand_subword: invalid autoincrement", op);
-
- default:
- break;
- }
- }
-
- return operand_subword (op, i, validate_address, mode);
-}
-
-/* Handle machine specific pragmas for compatibility with existing
- compilers for the C3x/C4x.
-
- pragma attribute
- ----------------------------------------------------------
- CODE_SECTION(symbol,"section") section("section")
- DATA_SECTION(symbol,"section") section("section")
- FUNC_CANNOT_INLINE(function)
- FUNC_EXT_CALLED(function)
- FUNC_IS_PURE(function) const
- FUNC_IS_SYSTEM(function)
- FUNC_NEVER_RETURNS(function) noreturn
- FUNC_NO_GLOBAL_ASG(function)
- FUNC_NO_IND_ASG(function)
- INTERRUPT(function) interrupt
-
- */
-
-int
-c4x_handle_pragma (p_getc, p_ungetc, pname)
- int (* p_getc) PROTO ((void));
- void (* p_ungetc) PROTO ((int)) ATTRIBUTE_UNUSED;
- char *pname;
-{
- int i;
- int c;
- int namesize;
- char *name;
- tree func;
- tree sect = NULL_TREE;
- tree new;
-
- c = p_getc ();
- while (c == ' ' || c == '\t') c = p_getc ();
- if (c != '(')
- return 0;
-
- c = p_getc ();
- while (c == ' ' || c == '\t') c = p_getc ();
- if (! (isalpha(c) || c == '_' || c == '$' || c == '@'))
- return 0;
-
- i = 0;
- namesize = 16;
- name = xmalloc (namesize);
- while (isalnum (c) || c == '_' || c == '$' || c == '@')
- {
- if (i >= namesize-1)
- {
- namesize += 16;
- name = xrealloc (name, namesize);
- }
- name[i++] = c;
- c = p_getc ();
- }
- name[i] = 0;
- func = get_identifier (name);
- free (name);
-
- if (strcmp (pname, "CODE_SECTION") == 0
- || strcmp (pname, "DATA_SECTION") == 0)
- {
- while (c == ' ' || c == '\t') c = p_getc ();
- if (c != ',')
- return 0;
-
- c = p_getc ();
- while (c == ' ' || c == '\t') c = p_getc ();
- if (c != '"')
- return 0;
-
- i = 0;
- namesize = 16;
- name = xmalloc (namesize);
- c = p_getc ();
- while (c != '"' && c != '\n' && c != '\r' && c != EOF)
- {
- if (i >= namesize-1)
- {
- namesize += 16;
- name = xrealloc (name, namesize);
- }
- name[i++] = c;
- c = p_getc ();
- }
- name[i] = 0;
- sect = build_string (i, name);
- free (name);
- sect = build_tree_list (NULL_TREE, sect);
-
- if (c != '"')
- return 0;
- c = p_getc ();
- }
- while (c == ' ' || c == '\t') c = p_getc ();
- if (c != ')')
- return 0;
-
- new = build_tree_list (func, sect);
- if (strcmp (pname, "CODE_SECTION") == 0)
- code_tree = chainon (code_tree, new);
-
- else if (strcmp (pname, "DATA_SECTION") == 0)
- data_tree = chainon (data_tree, new);
-
- else if (strcmp (pname, "FUNC_CANNOT_INLINE") == 0)
- ; /* ignore */
-
- else if (strcmp (pname, "FUNC_EXT_CALLED") == 0)
- ; /* ignore */
-
- else if (strcmp (pname, "FUNC_IS_PURE") == 0)
- pure_tree = chainon (pure_tree, new);
-
- else if (strcmp (pname, "FUNC_IS_SYSTEM") == 0)
- ; /* ignore */
-
- else if (strcmp (pname, "FUNC_NEVER_RETURNS") == 0)
- noreturn_tree = chainon (noreturn_tree, new);
-
- else if (strcmp (pname, "FUNC_NO_GLOBAL_ASG") == 0)
- ; /* ignore */
-
- else if (strcmp (pname, "FUNC_NO_IND_ASG") == 0)
- ; /* ignore */
-
- else if (strcmp (pname, "INTERRUPT") == 0)
- interrupt_tree = chainon (interrupt_tree, new);
-
- else
- return 0;
-
- return 1;
-}
-
-
-static void
-c4x_check_attribute(attrib, list, decl, attributes)
- char *attrib;
- tree list, decl, *attributes;
-{
- while (list != NULL_TREE
- && IDENTIFIER_POINTER (TREE_PURPOSE (list))
- != IDENTIFIER_POINTER (DECL_NAME (decl)))
- list = TREE_CHAIN(list);
- if (list)
- *attributes = chainon (*attributes,
- build_tree_list (get_identifier (attrib),
- TREE_VALUE(list)));
-}
-
-
-void
-c4x_set_default_attributes(decl, attributes)
- tree decl, *attributes;
-{
- switch (TREE_CODE (decl))
- {
- case FUNCTION_DECL:
- c4x_check_attribute ("section", code_tree, decl, attributes);
- c4x_check_attribute ("const", pure_tree, decl, attributes);
- c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes);
- c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes);
- break;
-
- case VAR_DECL:
- c4x_check_attribute ("section", data_tree, decl, attributes);
- break;
-
- default:
- break;
- }
-}
-
-
-/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
- specific attribute for TYPE. The attributes in ATTRIBUTES have
- previously been assigned to TYPE. */
-
-int
-c4x_valid_type_attribute_p (type, attributes, identifier, args)
- tree type;
- tree attributes ATTRIBUTE_UNUSED;
- tree identifier;
- tree args ATTRIBUTE_UNUSED;
-{
- if (TREE_CODE (type) != FUNCTION_TYPE)
- return 0;
-
- if (is_attribute_p ("interrupt", identifier))
- return 1;
-
- if (is_attribute_p ("assembler", identifier))
- return 1;
-
- if (is_attribute_p ("leaf_pretend", identifier))
- return 1;
-
- return 0;
-}
-
-
-/* !!! FIXME to emit RPTS correctly. */
-int
-c4x_rptb_rpts_p (insn, op)
- rtx insn, op;
-{
- /* The next insn should be our label marking where the
- repeat block starts. */
- insn = NEXT_INSN (insn);
- if (GET_CODE (insn) != CODE_LABEL)
- {
- /* Some insns may have been shifted between the RPTB insn
- and the top label... They were probably destined to
- be moved out of the loop. For now, let's leave them
- where they are and print a warning. We should
- probably move these insns before the repeat block insn. */
- if (TARGET_DEBUG)
- fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n",
- insn);
- return 0;
- }
-
- /* Skip any notes. */
- insn = next_nonnote_insn (insn);
-
- /* This should be our first insn in the loop. */
- if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
- return 0;
-
- /* Skip any notes. */
- insn = next_nonnote_insn (insn);
-
- if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
- return 0;
-
- if (recog_memoized (insn) != CODE_FOR_rptb_end)
- return 0;
-
- if (TARGET_RPTS)
- return 1;
-
- return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op));
-}
-
-
-/* Adjust the cost of a scheduling dependency. Return the new cost of
- a dependency LINK or INSN on DEP_INSN. COST is the current cost.
- A set of an address register followed by a use occurs a 2 cycle
- stall (reduced to a single cycle on the c40 using LDA), while
- a read of an address register followed by a use occurs a single cycle. */
-#define SET_USE_COST 3
-#define SETLDA_USE_COST 2
-#define READ_USE_COST 2
-
-int
-c4x_adjust_cost (insn, link, dep_insn, cost)
- rtx insn;
- rtx link;
- rtx dep_insn;
- int cost;
-{
- /* Don't worry about this until we know what registers have been
- assigned. */
- if (! reload_completed)
- return 0;
-
- /* How do we handle dependencies where a read followed by another
- read causes a pipeline stall? For example, a read of ar0 followed
- by the use of ar0 for a memory reference. It looks like we
- need to extend the scheduler to handle this case. */
-
- /* Reload sometimes generates a CLOBBER of a stack slot, e.g.,
- (clobber (mem:QI (plus:QI (reg:QI 11 ar3) (const_int 261)))),
- so only deal with insns we know about. */
- if (recog_memoized (dep_insn) < 0)
- return 0;
-
- if (REG_NOTE_KIND (link) == 0)
- {
- int max = 0;
-
- /* Data dependency; DEP_INSN writes a register that INSN reads some
- cycles later. */
-
- if (TARGET_C3X)
- {
- if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_readarx (dep_insn) && get_attr_usegroup1 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
- }
- else
- {
- /* This could be significantly optimized. We should look
- to see if dep_insn sets ar0-ar7 or ir0-ir1 and if
- insn uses ar0-ar7. We then test if the same register
- is used. The tricky bit is that some operands will
- use several registers... */
-
- if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar0 (dep_insn) && get_attr_usear0 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar1 (dep_insn) && get_attr_usear1 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar1 (dep_insn) && get_attr_usear1 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar1 (dep_insn) && get_attr_usear1 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar2 (dep_insn) && get_attr_usear2 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar2 (dep_insn) && get_attr_usear2 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar2 (dep_insn) && get_attr_usear2 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar3 (dep_insn) && get_attr_usear3 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar3 (dep_insn) && get_attr_usear3 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar3 (dep_insn) && get_attr_usear3 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar4 (dep_insn) && get_attr_usear4 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar4 (dep_insn) && get_attr_usear4 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar4 (dep_insn) && get_attr_usear4 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar5 (dep_insn) && get_attr_usear5 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar5 (dep_insn) && get_attr_usear5 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar5 (dep_insn) && get_attr_usear5 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar6 (dep_insn) && get_attr_usear6 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar6 (dep_insn) && get_attr_usear6 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar6 (dep_insn) && get_attr_usear6 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setar7 (dep_insn) && get_attr_usear7 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ar7 (dep_insn) && get_attr_usear7 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- if (get_attr_readar7 (dep_insn) && get_attr_usear7 (insn))
- max = READ_USE_COST > max ? READ_USE_COST : max;
-
- if (get_attr_setir0 (dep_insn) && get_attr_useir0 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ir0 (dep_insn) && get_attr_useir0 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
-
- if (get_attr_setir1 (dep_insn) && get_attr_useir1 (insn))
- max = SET_USE_COST > max ? SET_USE_COST : max;
- if (get_attr_setlda_ir1 (dep_insn) && get_attr_useir1 (insn))
- max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
- }
-
- if (max)
- cost = max;
-
- /* For other data dependencies, the default cost specified in the
- md is correct. */
- return cost;
- }
- else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
- {
- /* Anti dependency; DEP_INSN reads a register that INSN writes some
- cycles later. */
-
- /* For c4x anti dependencies, the cost is 0. */
- return 0;
- }
- else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
- {
- /* Output dependency; DEP_INSN writes a register that INSN writes some
- cycles later. */
-
- /* For c4x output dependencies, the cost is 0. */
- return 0;
- }
- else
- abort ();
-}
diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h
deleted file mode 100755
index 2a0a7c0..0000000
--- a/gcc/config/c4x/c4x.h
+++ /dev/null
@@ -1,2671 +0,0 @@
-/* Definitions of target machine for GNU compiler. TMS320C[34]x
- Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
-
- Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
- and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* Set the following so that some of the macros expand to function
- calls to simplify debugging. */
-#define C4X_DEBUG 1
-
-/* RUN-TIME TARGET SPECIFICATION */
-
-#define C4x 1
-
-/* Name of the c4x assembler */
-
-#define ASM_PROG "c4x-as"
-
-/* Name of the c4x linker */
-
-#define LD_PROG "c4x-ld"
-
-/* Define assembler options */
-
-#define ASM_SPEC "\
-%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=40:%{!mcpu=44:\
-%{!m30:%{!m40:-m40}}}}}}} \
-%{mcpu=30:-m30} \
-%{mcpu=31:-m31} \
-%{mcpu=32:-m32} \
-%{mcpu=40:-m40} \
-%{mcpu=44:-m44} \
-%{m30:-m30} \
-%{m31:-m31} \
-%{m32:-m32} \
-%{m40:-m40} \
-%{m44:-m44} \
-%{mmemparm:-p} %{mregparm:-r} \
-%{!mmemparm:%{!mregparm:-r}} \
-%{mbig:-b} %{msmall:-s} \
-%{!msmall:%{!mbig:-b}}"
-
-/* Define linker options */
-
-#define LINK_SPEC "\
-%{m30:--architecture c3x} \
-%{m31:--architecture c3x} \
-%{m32:--architecture c3x} \
-%{mcpu=30:--architecture c3x} \
-%{mcpu=31:--architecture c3x} \
-%{mcpu=32:--architecture c3x}"
-
-/* Define C preprocessor options. */
-
-#define CPP_SPEC "\
-%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=40:%{!mcpu=44:\
- %{!m40:%{!m44:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 }}}}}}}}}} \
-%{mcpu=30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \
-%{m30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \
-%{mcpu=31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \
-%{m31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \
-%{mcpu=32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \
-%{m32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \
-%{mcpu=40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \
-%{m40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \
-%{mcpu=44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \
-%{m44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \
-%{mmemparm:-U_REGPARM }%{mregparm:-D_REGPARM } \
-%{!mmemparm:%{!mregparm:-D_REGPARM }} \
-%{msmall:-U_BIGMODEL } %{mbig:-D_BIGMODEL } \
-%{!msmall:%{!mbig:-D_BIGMODEL }} \
-%{finline-functions:-D_INLINE }"
-
-/* Specify the startup file to link with. */
-
-#define STARTFILE_SPEC "\
-%{!mmemparm:%{m30:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{m30:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{m31:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{m31:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{m32:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{m32:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{mcpu=30:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{mcpu=30:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{mcpu=31:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{mcpu=31:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{mcpu=32:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \
-%{mmemparm:%{mcpu=32:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \
-%{!mmemparm:%{m40:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \
-%{mmemparm:%{m40:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \
-%{!mmemparm:%{m44:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \
-%{mmemparm:%{m44:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \
-%{!mmemparm:%{mcpu=40:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \
-%{mmemparm:%{mcpu=40:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \
-%{!mmemparm:%{mcpu=44:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \
-%{mmemparm:%{mcpu=44:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \
-%{!mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \
- %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{msmall:crt0_4sr%O%s}}}}}}}}}}}} \
-%{mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \
- %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{msmall:crt0_4sm%O%s}}}}}}}}}}}} \
-%{!mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \
- %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{!msmall:crt0_4br%O%s}}}}}}}}}}}} \
-%{mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \
- %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{!msmall:crt0_4bm%O%s}}}}}}}}}}}}"
-
-/* Specify the end file to link with */
-
-#define ENDFILE_SPEC ""
-
-/* Target compilation option flags */
-
-#define SMALL_MEMORY_FLAG 0x0000001 /* small memory model */
-#define MPYI_FLAG 0x0000002 /* use 24-bit MPYI for C3x */
-#define FAST_FIX_FLAG 0x0000004 /* fast fixing of floats */
-#define RPTS_FLAG 0x0000008 /* allow use of RPTS */
-#define C3X_FLAG 0x0000010 /* emit C3x code */
-#define TI_FLAG 0x0000020 /* be compatible with TI assembler */
-#define PARANOID_FLAG 0x0000040 /* be paranoid about DP reg. in ISRs */
-#define MEMPARM_FLAG 0x0000080 /* pass arguments on stack */
-#define DEVEL_FLAG 0x0000100 /* enable features under development */
-#define RPTB_FLAG 0x0000200 /* enable repeat block */
-#define BK_FLAG 0x0000400 /* use BK as general register */
-#define DB_FLAG 0x0000800 /* use decrement and branch for C3x */
-#define DEBUG_FLAG 0x0001000 /* enable debugging of GCC */
-#define HOIST_FLAG 0x0002000 /* force constants into registers */
-#define LOOP_UNSIGNED_FLAG 0x0004000 /* allow unsigned loop counters */
-#define FORCE_FLAG 0x0008000 /* force op0 and op1 to be same */
-#define PRESERVE_FLOAT_FLAG 0x0010000 /* save all 40 bits for floats */
-#define PARALLEL_PACK_FLAG 0x0020000 /* allow parallel insn packing */
-#define PARALLEL_MPY_FLAG 0x0040000 /* allow MPY||ADD, MPY||SUB insns */
-#define ALIASES_FLAG 0x0080000 /* assume mem refs possibly aliased */
-
-#define C30_FLAG 0x0100000 /* emit C30 code */
-#define C31_FLAG 0x0200000 /* emit C31 code */
-#define C32_FLAG 0x0400000 /* emit C32 code */
-#define C40_FLAG 0x1000000 /* emit C40 code */
-#define C44_FLAG 0x2000000 /* emit C44 code */
-
-/* Run-time compilation parameters selecting different hardware subsets.
-
- Macro to define tables used to set the flags.
- This is a list in braces of pairs in braces,
- each pair being { "NAME", VALUE }
- where VALUE is the bits to set or minus the bits to clear.
- An empty string NAME is used to identify the default VALUE. */
-
-#define TARGET_SWITCHES \
-{ { "small", SMALL_MEMORY_FLAG }, \
- { "big", -SMALL_MEMORY_FLAG }, \
- { "mpyi", MPYI_FLAG}, \
- { "no-mpyi", -MPYI_FLAG}, \
- { "fast-fix", FAST_FIX_FLAG}, \
- { "no-fast-fix", -FAST_FIX_FLAG}, \
- { "rpts", RPTS_FLAG}, \
- { "no-rpts", -RPTS_FLAG}, \
- { "rptb", RPTB_FLAG}, \
- { "no-rptb", -RPTB_FLAG}, \
- { "30", C30_FLAG}, \
- { "31", C31_FLAG}, \
- { "32", C32_FLAG}, \
- { "40", C40_FLAG}, \
- { "44", C44_FLAG}, \
- { "ti", TI_FLAG}, \
- { "no-ti", -TI_FLAG}, \
- { "paranoid", PARANOID_FLAG}, \
- { "no-paranoid", -PARANOID_FLAG}, \
- { "isr-dp-reload", PARANOID_FLAG}, \
- { "no-isr-dp-reload", -PARANOID_FLAG}, \
- { "memparm", MEMPARM_FLAG}, \
- { "regparm", -MEMPARM_FLAG}, \
- { "devel", DEVEL_FLAG}, \
- { "no-devel", -DEVEL_FLAG}, \
- { "bk", BK_FLAG}, \
- { "no-bk", -BK_FLAG}, \
- { "db", DB_FLAG}, \
- { "no-db", -DB_FLAG}, \
- { "debug", DEBUG_FLAG}, \
- { "no-debug", -DEBUG_FLAG}, \
- { "hoist", HOIST_FLAG}, \
- { "no-hoist", -HOIST_FLAG}, \
- { "no-force", -FORCE_FLAG}, \
- { "force", FORCE_FLAG}, \
- { "loop-unsigned", LOOP_UNSIGNED_FLAG}, \
- { "no-loop-unsigned", -LOOP_UNSIGNED_FLAG}, \
- { "preserve-float", PRESERVE_FLOAT_FLAG}, \
- { "no-preserve-float", -PRESERVE_FLOAT_FLAG}, \
- { "parallel-insns", PARALLEL_PACK_FLAG}, \
- { "no-parallel-mpy", -PARALLEL_MPY_FLAG}, \
- { "parallel-mpy", PARALLEL_MPY_FLAG}, \
- { "no-parallel-insns", -PARALLEL_PACK_FLAG}, \
- { "aliases", ALIASES_FLAG}, \
- { "no-aliases", -ALIASES_FLAG}, \
- { "", TARGET_DEFAULT} }
-
-/* Default target switches */
-
-/* Play safe, not the fastest code. */
-#define TARGET_DEFAULT ALIASES_FLAG | PARALLEL_PACK_FLAG \
- | PARALLEL_MPY_FLAG | RPTB_FLAG
-
-/* Caveats:
- Max iteration count for RPTB/RPTS is 2^31 + 1.
- Max iteration count for DB is 2^31 + 1 for C40, but 2^23 + 1 for C30.
- RPTS blocks interrupts. */
-
-
-extern int target_flags;
-
-#define TARGET_INLINE 1 /* Inline MPYI */
-#define TARGET_PARALLEL 1 /* Enable parallel insns in MD */
-#define TARGET_SMALL_REG_CLASS 0
-
-#define TARGET_SMALL (target_flags & SMALL_MEMORY_FLAG)
-#define TARGET_MPYI (!TARGET_C3X || (target_flags & MPYI_FLAG))
-#define TARGET_FAST_FIX (target_flags & FAST_FIX_FLAG)
-#define TARGET_RPTS (target_flags & RPTS_FLAG)
-#define TARGET_TI (target_flags & TI_FLAG)
-#define TARGET_PARANOID (target_flags & PARANOID_FLAG)
-#define TARGET_MEMPARM (target_flags & MEMPARM_FLAG)
-#define TARGET_DEVEL (target_flags & DEVEL_FLAG)
-#define TARGET_RPTB (target_flags & RPTB_FLAG \
- && optimize >= 2)
-#define TARGET_BK (target_flags & BK_FLAG)
-#define TARGET_DB (! TARGET_C3X || (target_flags & DB_FLAG))
-#define TARGET_DEBUG (target_flags & DEBUG_FLAG)
-#define TARGET_HOIST (target_flags & HOIST_FLAG)
-#define TARGET_LOOP_UNSIGNED (target_flags & LOOP_UNSIGNED_FLAG)
-#define TARGET_FORCE (target_flags & FORCE_FLAG)
-#define TARGET_PRESERVE_FLOAT (target_flags & PRESERVE_FLOAT_FLAG)
-#define TARGET_PARALLEL_PACK (TARGET_RPTB \
- && (target_flags & PARALLEL_PACK_FLAG) \
- && optimize >= 2)
-#define TARGET_PARALLEL_MPY (TARGET_PARALLEL_PACK \
- && (target_flags & PARALLEL_MPY_FLAG))
-#define TARGET_ALIASES (target_flags & ALIASES_FLAG)
-
-#define TARGET_C3X (target_flags & C3X_FLAG)
-#define TARGET_C30 (target_flags & C30_FLAG)
-#define TARGET_C31 (target_flags & C31_FLAG)
-#define TARGET_C32 (target_flags & C32_FLAG)
-#define TARGET_C40 (target_flags & C40_FLAG)
-#define TARGET_C44 (target_flags & C44_FLAG)
-
-/* -mrpts allows the use of the RPTS instruction irregardless.
- -mrpts=max-cycles will use RPTS if the number of cycles is constant
- and less than max-cycles. */
-
-#define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles)
-
-/* -mcpu=XX with XX = target DSP version number */
-
-/* This macro is similar to `TARGET_SWITCHES' but defines names of
- command options that have values. Its definition is an
- initializer with a subgrouping for each command option.
-
- Each subgrouping contains a string constant, that defines the
- fixed part of the option name, and the address of a variable.
- The variable, type `char *', is set to the variable part of the
- given option if the fixed part matches. The actual option name
- is made by appending `-m' to the specified name.
-
- Here is an example which defines `-mshort-data-NUMBER'. If the
- given option is `-mshort-data-512', the variable `m88k_short_data'
- will be set to the string `"512"'.
-
- extern char *m88k_short_data;
- #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
-
-extern char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
-
-#define TARGET_OPTIONS \
-{ {"rpts=", &c4x_rpts_cycles_string},\
- {"cpu=", &c4x_cpu_version_string} }
-
-/* Sometimes certain combinations of command options do not make sense
- on a particular target machine. You can define a macro
- `OVERRIDE_OPTIONS' to take account of this. This macro, if
- defined, is executed once just after all the command options have
- been parsed. */
-
-extern void c4x_override_options ();
-#define OVERRIDE_OPTIONS c4x_override_options ()
-
-/* Define this to change the optimizations performed by default. */
-extern void c4x_optimization_options ();
-#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) c4x_optimization_options(LEVEL,SIZE)
-
-/* Run Time Target Specification */
-
-#define TARGET_VERSION fprintf (stderr, " (TMS320C[34]x, TI syntax)" );
-
-/* Storage Layout */
-
-#define BITS_BIG_ENDIAN 0
-#define BYTES_BIG_ENDIAN 0
-#define WORDS_BIG_ENDIAN 0
-
-/* Technically, we are little endian, but we put the floats out as
- whole longs and this makes GCC put them out in the right order. */
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-/* Note the ANSI C standard requires sizeof(char) = 1. On the C[34]x
- all integral and floating point data types are stored in memory as
- 32-bits (floating point types can be stored as 40-bits in the
- extended precision registers), so sizeof(char) = sizeof(short) =
- sizeof(int) = sizeof(long) = sizeof(float) = sizeof(double) = 1. */
-
-#define BITS_PER_UNIT 32
-#define BITS_PER_WORD 32
-#define UNITS_PER_WORD 1
-#define POINTER_SIZE 32
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-#define EMPTY_FIELD_BOUNDARY 32
-#define STRICT_ALIGNMENT 0
-#define TARGET_FLOAT_FORMAT C4X_FLOAT_FORMAT
-#define MAX_FIXED_MODE_SIZE 64 /* HImode */
-
-/* Use the internal floating point stuff in the compiler and not the
- host floating point stuff. */
-
-#define REAL_ARITHMETIC
-
-/* Define register numbers */
-
-/* Extended-precision registers */
-
-#define R0_REGNO 0
-#define R1_REGNO 1
-#define R2_REGNO 2
-#define R3_REGNO 3
-#define R4_REGNO 4
-#define R5_REGNO 5
-#define R6_REGNO 6
-#define R7_REGNO 7
-
-/* Auxiliary (address) registers */
-
-#define AR0_REGNO 8
-#define AR1_REGNO 9
-#define AR2_REGNO 10
-#define AR3_REGNO 11
-#define AR4_REGNO 12
-#define AR5_REGNO 13
-#define AR6_REGNO 14
-#define AR7_REGNO 15
-
-/* Data page register */
-
-#define DP_REGNO 16
-
-/* Index registers */
-
-#define IR0_REGNO 17
-#define IR1_REGNO 18
-
-/* Block size register */
-
-#define BK_REGNO 19
-
-/* Stack pointer */
-
-#define SP_REGNO 20
-
-/* Status register */
-
-#define ST_REGNO 21
-
-/* Misc. interrupt registers */
-
-#define DIE_REGNO 22 /* C4x only */
-#define IE_REGNO 22 /* C3x only */
-#define IIE_REGNO 23 /* C4x only */
-#define IF_REGNO 23 /* C3x only */
-#define IIF_REGNO 24 /* C4x only */
-#define IOF_REGNO 24 /* C3x only */
-
-/* Repeat block registers */
-
-#define RS_REGNO 25
-#define RE_REGNO 26
-#define RC_REGNO 27
-
-/* Additional extended-precision registers */
-
-#define R8_REGNO 28 /* C4x only */
-#define R9_REGNO 29 /* C4x only */
-#define R10_REGNO 30 /* C4x only */
-#define R11_REGNO 31 /* C4x only */
-
-#define FIRST_PSEUDO_REGISTER 32
-
-/* Extended precision registers (low set) */
-
-#define IS_R0R1_REG(r) ((((r) >= R0_REGNO) && ((r) <= R1_REGNO)))
-#define IS_R2R3_REG(r) ((((r) >= R2_REGNO) && ((r) <= R3_REGNO)))
-#define IS_EXT_LOW_REG(r) ((((r) >= R0_REGNO) && ((r) <= R7_REGNO)))
-
-/* Extended precision registers (high set) */
-
-#define IS_EXT_HIGH_REG(r) (! TARGET_C3X \
- && ((r) >= R8_REGNO) && ((r) <= R11_REGNO))
-/* Address registers */
-
-#define IS_AUX_REG(r) (((r) >= AR0_REGNO) && ((r) <= AR7_REGNO))
-#define IS_ADDR_REG(r) IS_AUX_REG(r)
-#define IS_DP_REG(r) ((r) == DP_REGNO)
-#define IS_INDEX_REG(r) (((r) == IR0_REGNO) || ((r) == IR1_REGNO))
-#define IS_SP_REG(r) ((r) == SP_REGNO)
-#define IS_BK_REG(r) (TARGET_BK && (r) == BK_REGNO)
-
-/* Misc registers */
-
-#define IS_ST_REG(r) ((r) == ST_REGNO)
-#define IS_RC_REG(r) ((r) == RC_REGNO)
-#define IS_REPEAT_REG(r) (((r) >= RS_REGNO) && ((r) <= RC_REGNO))
-
-/* Composite register sets */
-
-#define IS_ADDR_OR_INDEX_REG(r) (IS_ADDR_REG(r) || IS_INDEX_REG(r))
-#define IS_EXT_REG(r) (IS_EXT_LOW_REG(r) || IS_EXT_HIGH_REG(r))
-#define IS_STD_REG(r) (IS_ADDR_OR_INDEX_REG(r) || IS_REPEAT_REG(r) \
- || IS_SP_REG(r) || IS_BK_REG(r))
-#define IS_INT_REG(r) (IS_EXT_REG(r) || IS_STD_REG(r))
-#define IS_GROUP1_REG(r) (IS_ADDR_OR_INDEX_REG(r) || IS_BK_REG(r))
-
-
-#define IS_PSEUDO_REG(r) ((r) >= FIRST_PSEUDO_REGISTER)
-#define IS_R0R1_OR_PSEUDO_REG(r) (IS_R0R1_REG(r) || IS_PSEUDO_REG(r))
-#define IS_R2R3_OR_PSEUDO_REG(r) (IS_R2R3_REG(r) || IS_PSEUDO_REG(r))
-#define IS_EXT_OR_PSEUDO_REG(r) (IS_EXT_REG(r) || IS_PSEUDO_REG(r))
-#define IS_STD_OR_PSEUDO_REG(r) (IS_STD_REG(r) || IS_PSEUDO_REG(r))
-#define IS_INT_OR_PSEUDO_REG(r) (IS_INT_REG(r) || IS_PSEUDO_REG(r))
-#define IS_ADDR_OR_PSEUDO_REG(r) (IS_ADDR_REG(r) || IS_PSEUDO_REG(r))
-#define IS_INDEX_OR_PSEUDO_REG(r) (IS_INDEX_REG(r) || IS_PSEUDO_REG(r))
-#define IS_EXT_LOW_OR_PSEUDO_REG(r) (IS_EXT_LOW_REG(r) || IS_PSEUDO_REG(r))
-#define IS_DP_OR_PSEUDO_REG(r) (IS_DP_REG(r) || IS_PSEUDO_REG(r))
-#define IS_SP_OR_PSEUDO_REG(r) (IS_SP_REG(r) || IS_PSEUDO_REG(r))
-#define IS_ST_OR_PSEUDO_REG(r) (IS_ST_REG(r) || IS_PSEUDO_REG(r))
-#define IS_RC_OR_PSEUDO_REG(r) (IS_RC_REG(r) || IS_PSEUDO_REG(r))
-
-#define IS_PSEUDO_REGNO(op) (IS_PSEUDO_REG(REGNO(op)))
-#define IS_ADDR_REGNO(op) (IS_ADDR_REG(REGNO(op)))
-#define IS_INDEX_REGNO(op) (IS_INDEX_REG(REGNO(op)))
-#define IS_GROUP1_REGNO(r) (IS_GROUP1_REG(REGNO(op)))
-
-#define IS_R0R1_OR_PSEUDO_REGNO(op) (IS_R0R1_OR_PSEUDO_REG(REGNO(op)))
-#define IS_R2R3_OR_PSEUDO_REGNO(op) (IS_R2R3_OR_PSEUDO_REG(REGNO(op)))
-#define IS_EXT_OR_PSEUDO_REGNO(op) (IS_EXT_OR_PSEUDO_REG(REGNO(op)))
-#define IS_STD_OR_PSEUDO_REGNO(op) (IS_STD_OR_PSEUDO_REG(REGNO(op)))
-#define IS_EXT_LOW_OR_PSEUDO_REGNO(op) (IS_EXT_LOW_OR_PSEUDO_REG(REGNO(op)))
-#define IS_INT_OR_PSEUDO_REGNO(op) (IS_INT_OR_PSEUDO_REG(REGNO(op)))
-
-#define IS_ADDR_OR_PSEUDO_REGNO(op) (IS_ADDR_OR_PSEUDO_REG(REGNO(op)))
-#define IS_INDEX_OR_PSEUDO_REGNO(op) (IS_INDEX_OR_PSEUDO_REG(REGNO(op)))
-#define IS_DP_OR_PSEUDO_REGNO(op) (IS_DP_OR_PSEUDO_REG(REGNO(op)))
-#define IS_SP_OR_PSEUDO_REGNO(op) (IS_SP_OR_PSEUDO_REG(REGNO(op)))
-#define IS_ST_OR_PSEUDO_REGNO(op) (IS_ST_OR_PSEUDO_REG(REGNO(op)))
-#define IS_RC_OR_PSEUDO_REGNO(op) (IS_RC_OR_PSEUDO_REG(REGNO(op)))
-
-/* 1 for registers that have pervasive standard uses
- and are not available for the register allocator. */
-
-#define FIXED_REGISTERS \
-{ \
-/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7 */ \
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11 */ \
- 1, 0, 0, 0, 1, 1, 1, 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.
-
- Note that the extended precision registers are only saved in some
- modes. The macro HARD_REGNO_CALL_CLOBBERED specifies which modes
- get clobbered for a given regno. */
-
-#define CALL_USED_REGISTERS \
-{ \
-/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7 */ \
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, \
-/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11 */ \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 \
-}
-
-/* Macro to conditionally modify fixed_regs/call_used_regs. */
-
-#define CONDITIONAL_REGISTER_USAGE \
- { \
- if (! TARGET_BK) \
- { \
- fixed_regs[BK_REGNO] = 1; \
- call_used_regs[BK_REGNO] = 1; \
- c4x_regclass_map[BK_REGNO] = NO_REGS; \
- } \
- if (TARGET_C3X) \
- { \
- int i; \
- \
- reg_names[DIE_REGNO] = "ie"; /* clobber die */ \
- reg_names[IF_REGNO] = "if"; /* clobber iie */ \
- reg_names[IOF_REGNO] = "iof"; /* clobber iif */ \
- \
- for (i = R8_REGNO; i <= R11_REGNO; i++) \
- { \
- fixed_regs[i] = call_used_regs[i] = 1; \
- c4x_regclass_map[i] = NO_REGS; \
- } \
- } \
- if (TARGET_PRESERVE_FLOAT) \
- { \
- c4x_caller_save_map[R6_REGNO] = HFmode; \
- c4x_caller_save_map[R7_REGNO] = HFmode; \
- } \
- }
-
-/* Order of Allocation of Registers */
-
-/* List the order in which to allocate registers. Each register must be
- listed once, even those in FIXED_REGISTERS.
-
- First allocate registers that don't need preservation across calls,
- except index and address registers. Then allocate data registers
- that require preservation across calls (even though this invokes an
- extra overhead of having to save/restore these registers). Next
- allocate the address and index registers, since using these
- registers for arithmetic can cause pipeline stalls. Finally
- allocated the fixed registers which won't be allocated anyhow. */
-
-#define REG_ALLOC_ORDER \
-{R0_REGNO, R1_REGNO, R2_REGNO, R3_REGNO, \
- R9_REGNO, R10_REGNO, R11_REGNO, \
- RS_REGNO, RE_REGNO, RC_REGNO, BK_REGNO, \
- R4_REGNO, R5_REGNO, R6_REGNO, R7_REGNO, R8_REGNO, \
- AR0_REGNO, AR1_REGNO, AR2_REGNO, AR3_REGNO, \
- AR4_REGNO, AR5_REGNO, AR6_REGNO, AR7_REGNO, \
- IR0_REGNO, IR1_REGNO, \
- SP_REGNO, DP_REGNO, ST_REGNO, IE_REGNO, IF_REGNO, IOF_REGNO}
-
-
-/* Determine which register classes are very likely used by spill registers.
- local-alloc.c won't allocate pseudos that have these classes as their
- preferred class unless they are "preferred or nothing". */
-
-#define CLASS_LIKELY_SPILLED_P(CLASS) \
- ((CLASS) == INDEX_REGS)
-
-/* CCmode is wrongly defined in machmode.def It should have a size
- of UNITS_PER_WORD. */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \
-((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
-
-/* A C expression that is nonzero if the hard register REGNO is preserved
- across a call in mode MODE. This does not have to include the call used
- registers. */
-
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
- ((((REGNO) == R6_REGNO || (REGNO) == R7_REGNO) && ! ((MODE) == QFmode)) \
- || (((REGNO) == R4_REGNO || (REGNO) == R5_REGNO || (REGNO == R8_REGNO)) \
- && ! ((MODE) == QImode || (MODE) == HImode || (MODE) == Pmode)))
-
-/* Specify the modes required to caller save a given hard regno. */
-
-#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) (c4x_caller_save_map[REGNO])
-
-int c4x_hard_regno_mode_ok ();
-#define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE)
-
-
-/* A C expression that is nonzero if it is desirable to choose
- register allocation so as to avoid move instructions between a
- value of mode MODE1 and a value of mode MODE2.
-
- 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) 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. */
-
-enum reg_class
- {
- NO_REGS,
- R0R1_REGS, /* 't' */
- R2R3_REGS, /* 'u' */
- EXT_LOW_REGS, /* 'q' */
- EXT_REGS, /* 'f' */
- ADDR_REGS, /* 'a' */
- INDEX_REGS, /* 'x' */
- BK_REG, /* 'k' */
- SP_REG, /* 'b' */
- RC_REG, /* 'v' */
- INT_REGS, /* 'c' */
- GENERAL_REGS, /* 'r' */
- DP_REG, /* 'z' */
- ST_REG, /* 'y' */
- ALL_REGS,
- LIM_REG_CLASSES
- };
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "R0R1_REGS", \
- "R2R3_REGS", \
- "EXT_LOW_REGS", \
- "EXT_REGS", \
- "ADDR_REGS", \
- "INDEX_REGS", \
- "BK_REG", \
- "SP_REG", \
- "RC_REG", \
- "INT_REGS", \
- "GENERAL_REGS", \
- "DP_REG", \
- "ST_REG", \
- "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. RC is not included in GENERAL_REGS
- since the register allocator will often choose a general register
- in preference to RC for the decrement_and_branch_on_count pattern. */
-
-#define REG_CLASS_CONTENTS \
-{ \
- {0x00000000}, /* No registers */ \
- {0x00000003}, /* 't' R0-R1 */ \
- {0x0000000c}, /* 'u' R2-R3 */ \
- {0x000000ff}, /* 'q' R0-R7 */ \
- {0xf00000ff}, /* 'f' R0-R11 */ \
- {0x0000ff00}, /* 'a' AR0-AR7 */ \
- {0x00060000}, /* 'x' IR0-IR1 */ \
- {0x00080000}, /* 'k' BK */ \
- {0x00100000}, /* 'b' SP */ \
- {0x08000000}, /* 'v' RC */ \
- {0x0e1eff00}, /* 'c' AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */ \
- {0xfe1effff}, /* 'r' R0-R11, AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */\
- {0x00010000}, /* 'z' DP */ \
- {0x00200000}, /* 'y' ST */ \
- {0xffffffff}, /* All registers */ \
-}
-
-/* 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) (c4x_regclass_map[REGNO])
-
-/* When SMALL_REGISTER_CLASSES is defined, the lifetime of registers
- explicitly used in the rtl is kept as short as possible.
-
- We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY
- is defined since the MPY|ADD insns require the classes R0R1_REGS and
- R2R3_REGS which are used by the function return registers (R0,R1) and
- the register arguments (R2,R3), respectively. I'm reluctant to define
- this macro since it stomps on many potential optimisations. Ideally
- it should have a register class argument so that not all the register
- classes gets penalised for the sake of a naughty few... For long
- double arithmetic we need two additional registers that we can use as
- spill registers. */
-
-#define SMALL_REGISTER_CLASSES (TARGET_SMALL_REG_CLASS && TARGET_PARALLEL_MPY)
-
-#define BASE_REG_CLASS ADDR_REGS
-#define INDEX_REG_CLASS INDEX_REGS
-
-/*
- Register constraints for the C4x
-
- a - address reg (ar0-ar7)
- b - stack reg (sp)
- c - other gp int-only reg
- d - data/int reg (equiv. to f)
- f - data/float reg
- h - data/long double reg (equiv. to f)
- k - block count (bk)
- q - r0-r7
- t - r0-r1
- u - r2-r3
- v - repeat count (rc)
- x - index register (ir0-ir1)
- y - status register (st)
- z - dp reg (dp)
-
- Memory/constant constraints for the C4x
-
- G - short float 16-bit
- I - signed 16-bit constant (sign extended)
- J - signed 8-bit constant (sign extended) (C4x only)
- K - signed 5-bit constant (sign extended) (C4x only for stik)
- L - unsigned 16-bit constant
- M - unsigned 8-bit constant (C4x only)
- N - ones complement of unsigned 16-bit constant
- Q - indirect arx + 9-bit signed displacement
- (a *-arx(n) or *+arx(n) is used to account for the sign bit)
- R - indirect arx + 5-bit unsigned displacement (C4x only)
- S - indirect arx + 0, 1, or irn displacement
- T - direct symbol ref
- > - indirect with autoincrement
- < - indirect with autodecrement
- } - indirect with post-modify
- { - indirect with pre-modify
- */
-
-#define REG_CLASS_FROM_LETTER(CC) \
- ( ((CC) == 'a') ? ADDR_REGS \
- : ((CC) == 'b') ? SP_REG \
- : ((CC) == 'c') ? INT_REGS \
- : ((CC) == 'd') ? EXT_REGS \
- : ((CC) == 'f') ? EXT_REGS \
- : ((CC) == 'h') ? EXT_REGS \
- : ((CC) == 'k') ? BK_REG \
- : ((CC) == 'q') ? EXT_LOW_REGS \
- : ((CC) == 't') ? R0R1_REGS \
- : ((CC) == 'u') ? R2R3_REGS \
- : ((CC) == 'v') ? RC_REG \
- : ((CC) == 'x') ? INDEX_REGS \
- : ((CC) == 'y') ? ST_REG \
- : ((CC) == 'z') ? DP_REG \
- : NO_REGS )
-
-/* These assume that REGNO is a hard or pseudo reg number.
- They give nonzero only if REGNO is a hard reg of the suitable class
- or a pseudo reg currently allocated to a suitable hard reg.
- Since they use reg_renumber, they are safe only once reg_renumber
- has been allocated, which happens in local-alloc.c. */
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- (IS_ADDR_REG(REGNO) || IS_ADDR_REG((unsigned)reg_renumber[REGNO]))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- (IS_INDEX_REG(REGNO) || IS_INDEX_REG((unsigned)reg_renumber[REGNO]))
-
-extern enum reg_class c4x_preferred_reload_class ();
-#define PREFERRED_RELOAD_CLASS(X, CLASS) c4x_preferred_reload_class(X, CLASS)
-
-extern enum reg_class c4x_limit_reload_class ();
-#define LIMIT_RELOAD_CLASS(X, CLASS) c4x_limit_reload_class(X, CLASS)
-
-extern enum reg_class c4x_secondary_memory_needed ();
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
-c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
-
-#define CLASS_MAX_NREGS(CLASS, MODE) \
-(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \
-((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
-#define IS_INT5_CONST(VAL) (((VAL) <= 15) && ((VAL) >= -16)) /* 'K' */
-
-#define IS_UINT5_CONST(VAL) (((VAL) <= 31) && ((VAL) >= 0)) /* 'R' */
-
-#define IS_INT8_CONST(VAL) (((VAL) <= 127) && ((VAL) >= -128)) /* 'J' */
-
-#define IS_UINT8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= 0)) /* 'M' */
-
-#define IS_INT16_CONST(VAL) (((VAL) <= 32767) && ((VAL) >= -32768)) /* 'I' */
-
-#define IS_UINT16_CONST(VAL) (((VAL) <= 65535) && ((VAL) >= 0)) /* 'L' */
-
-#define IS_NOT_UINT16_CONST(VAL) IS_UINT16_CONST(~(VAL)) /* 'N' */
-
-#define IS_HIGH_CONST(VAL) (! TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O' */
-
-
-#define IS_DISP1_CONST(VAL) (((VAL) <= 1) && ((VAL) >= -1)) /* 'S' */
-
-#define IS_DISP8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= -255)) /* 'Q' */
-
-#define IS_DISP1_OFF_CONST(VAL) (IS_DISP1_CONST (VAL) \
- && IS_DISP1_CONST (VAL + 1))
-
-#define IS_DISP8_OFF_CONST(VAL) (IS_DISP8_CONST (VAL) \
- && IS_DISP8_CONST (VAL + 1))
-
-#define CONST_OK_FOR_LETTER_P(VAL, C) \
- ( ((C) == 'I') ? (IS_INT16_CONST (VAL)) \
- : ((C) == 'J') ? (! TARGET_C3X && IS_INT8_CONST (VAL)) \
- : ((C) == 'K') ? (! TARGET_C3X && IS_INT5_CONST (VAL)) \
- : ((C) == 'L') ? (IS_UINT16_CONST (VAL)) \
- : ((C) == 'M') ? (! TARGET_C3X && IS_UINT8_CONST (VAL)) \
- : ((C) == 'N') ? (IS_NOT_UINT16_CONST (VAL)) \
- : ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \
- : 0 )
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL, C) \
- ( ((C) == 'G') ? (fp_zero_operand (VAL)) \
- : ((C) == 'H') ? (c4x_H_constant (VAL)) \
- : 0 )
-
-#define EXTRA_CONSTRAINT(VAL, C) \
- ( ((C) == 'Q') ? (c4x_Q_constraint (VAL)) \
- : ((C) == 'R') ? (c4x_R_constraint (VAL)) \
- : ((C) == 'S') ? (c4x_S_constraint (VAL)) \
- : ((C) == 'T') ? (c4x_T_constraint (VAL)) \
- : 0 )
-
-#define SMALL_CONST(VAL, insn) \
- ( ((insn == NULL_RTX) || (get_attr_data (insn) == DATA_INT16)) \
- ? IS_INT16_CONST (VAL) \
- : ( (get_attr_data (insn) == DATA_NOT_UINT16) \
- ? IS_NOT_UINT16_CONST (VAL) \
- : ( (get_attr_data (insn) == DATA_HIGH_16) \
- ? IS_HIGH_CONST (VAL) \
- : IS_UINT16_CONST (VAL) \
- ) \
- ) \
- )
-
-/*
- I. Routine calling with arguments in registers
- ----------------------------------------------
-
- The TI C3x compiler has a rather unusual register passing algorithm.
- Data is passed in the following registers (in order):
-
- AR2, R2, R3, RC, RS, RE
-
- However, the first and second floating point values are always in R2
- and R3 (and all other floats are on the stack). Structs are always
- passed on the stack. If the last argument is an ellipsis, the
- previous argument is passed on the stack so that its address can be
- taken for the stdargs macros.
-
- Because of this, we have to pre-scan the list of arguments to figure
- out what goes where in the list.
-
- II. Routine calling with arguments on stack
- -------------------------------------------
-
- Let the subroutine declared as "foo(arg0, arg1, arg2);" have local
- variables loc0, loc1, and loc2. After the function prologue has
- been executed, the stack frame will look like:
-
- [stack grows towards increasing addresses]
- I-------------I
- 5 I saved reg1 I <= SP points here
- I-------------I
- 4 I saved reg0 I
- I-------------I
- 3 I loc2 I
- I-------------I
- 2 I loc1 I
- I-------------I
- 1 I loc0 I
- I-------------I
- 0 I old FP I <= FP (AR3) points here
- I-------------I
- -1 I return PC I
- I-------------I
- -2 I arg0 I
- I-------------I
- -3 I arg1 I
- I-------------I
- -4 I arg2 I
- I-------------I
-
- All local variables (locn) are accessible by means of +FP(n+1)
- addressing, where n is the local variable number.
-
- All stack arguments (argn) are accessible by means of -FP(n-2).
-
- The stack pointer (SP) points to the last register saved in the
- prologue (regn).
-
- Note that a push instruction performs a preincrement of the stack
- pointer. (STACK_PUSH_CODE == PRE_INC)
-
- III. Registers used in function calling convention
- --------------------------------------------------
-
- Preserved across calls: R4...R5 (only by PUSH, i.e. lower 32 bits)
- R6...R7 (only by PUSHF, i.e. upper 32 bits)
- AR3...AR7
-
- (Because of this model, we only assign FP values in R6, R7 and
- only assign integer values in R4, R5.)
-
- These registers are saved at each function entry and restored at
- the exit. Also it is expected any of these not affected by any
- call to user-defined (not service) functions.
-
- Not preserved across calls: R0...R3
- R4...R5 (upper 8 bits)
- R6...R7 (lower 8 bits)
- AR0...AR2, IR0, IR1, BK, ST, RS, RE, RC
-
- These registers are used arbitrary in a function without being preserved.
- It is also expected that any of these can be clobbered by any call.
-
- Not used by GCC (except for in user "asm" statements):
- IE (DIE), IF (IIE), IOF (IIF)
-
- These registers are never used by GCC for any data, but can be used
- with "asm" statements. */
-
-#define C4X_ARG0 -2
-#define C4X_LOC0 1
-
-/* Basic Stack Layout */
-
-/* The stack grows upward, stack frame grows upward, and args grow
- downward. */
-
-#define STARTING_FRAME_OFFSET C4X_LOC0
-#define FIRST_PARM_OFFSET(FNDECL) (C4X_ARG0 + 1)
-#define ARGS_GROW_DOWNWARD
-#define STACK_POINTER_OFFSET 1
-
-/* Define this if pushing a word on the stack
- makes the stack pointer a smaller address. */
-
-/* #define STACK_GROWS_DOWNWARD */
-/* Like the dsp16xx, i370, i960, and we32k ports */
-
-/* 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 */
-
-
-/* Registers That Address the Stack Frame */
-
-#define STACK_POINTER_REGNUM SP_REGNO /* SP */
-#define FRAME_POINTER_REGNUM AR3_REGNO /* AR3 */
-#define ARG_POINTER_REGNUM AR3_REGNO /* AR3 */
-#define STATIC_CHAIN_REGNUM AR0_REGNO /* AR0 */
-
-/* Eliminating Frame Pointer and Arg Pointer */
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \
-{ \
- int regno; \
- int offset = 0; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += TARGET_PRESERVE_FLOAT \
- && ((regno == R6_REGNO) || (regno == R7_REGNO)) \
- ? 2 : 1; \
- (DEPTH) = -(offset + get_frame_size ()); \
-}
-
-/* This is a hack... We need to specify a register. */
-#define ELIMINABLE_REGS \
- {{ FRAME_POINTER_REGNUM, FRAME_POINTER_REGNUM }}
-
-#define CAN_ELIMINATE(FROM, TO) \
- (! (((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- || ((FROM) == FRAME_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)))
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ \
- int regno; \
- int offset = 0; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += TARGET_PRESERVE_FLOAT \
- && ((regno == R6_REGNO) || (regno == R7_REGNO)) \
- ? 2 : 1; \
- (OFFSET) = -(offset + get_frame_size ()); \
-}
-
-
-/* Passing Function Arguments on the Stack */
-
-#if 0
-#define PUSH_ROUNDING(BYTES) (BYTES)
-#endif
-#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
-
-/* The following structure is used by calls.c, function.c, c4x.c */
-
-typedef struct c4x_args
-{
- int floats;
- int ints;
- int maxfloats;
- int maxints;
- int init;
- int var;
- int prototype;
- int args;
-}
-CUMULATIVE_ARGS;
-
-extern void c4x_init_cumulative_args();
-
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
- (c4x_init_cumulative_args (&CUM, FNTYPE, LIBNAME))
-
-extern void c4x_function_arg_advance();
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (c4x_function_arg_advance (&CUM, MODE, TYPE, NAMED))
-
-extern struct rtx_def *c4x_function_arg();
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- (c4x_function_arg(&CUM, MODE, TYPE, NAMED))
-
-/* Define the profitability of saving registers around calls.
- NOTE: For now we turn this off because caller-save assumes
- that a register with a QFmode quantity can be saved/restored
- using QImode. */
-
-/* #define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 */
-
-/* Never pass data by reference. */
-
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-
-/* 1 if N is a possible register number for function argument passing. */
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ( ( ((REGNO) == AR2_REGNO) /* AR2 */ \
- || ((REGNO) == R2_REGNO) /* R2 */ \
- || ((REGNO) == R3_REGNO) /* R3 */ \
- || ((REGNO) == RC_REGNO) /* RC */ \
- || ((REGNO) == RS_REGNO) /* RS */ \
- || ((REGNO) == RE_REGNO)) /* RE */ \
- ? 1 \
- : 0)
-
-/* How Scalar Function Values Are Returned */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx(REG, TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0 */
-
-#define LIBCALL_VALUE(MODE) \
- gen_rtx(REG, MODE, R0_REGNO) /* Return in R0 */
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == R0_REGNO)
-
-/* How Large Values Are Returned */
-
-#define DEFAULT_PCC_STRUCT_RETURN 0
-#define STRUCT_VALUE_REGNUM AR0_REGNO /* AR0 */
-
-
-/* Function Entry and Exit */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) c4x_function_prologue(FILE, SIZE)
-#define FUNCTION_EPILOGUE(FILE, SIZE) c4x_function_epilogue(FILE, SIZE)
-
-
-/* Generating Code for Profiling */
-
-/* Note that the generated assembly uses the ^ operator to load the 16
- MSBs of the address. This is not supported by the TI assembler. */
-
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- if (! TARGET_C3X) \
- { \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tldhi\t^LP%d,ar2\n", (LABELNO)); \
- fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \
- fprintf (FILE, "\tcall\tmcount\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tldiu\t^LP%d,ar2\n", (LABELNO)); \
- fprintf (FILE, "\tlsh\t16,ar2\n"); \
- fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \
- fprintf (FILE, "\tcall\tmcount\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- }
-
-/* There are three profiling modes for basic blocks available.
- The modes are selected at compile time by using the options
- -a or -ax of the gnu compiler.
- The variable `profile_block_flag' will be set according to the
- selected option.
-
- profile_block_flag == 0, no option used:
-
- No profiling done.
-
- profile_block_flag == 1, -a option used.
-
- Count frequency of execution of every basic block.
-
- profile_block_flag == 2, -ax option used.
-
- Generate code to allow several different profiling modes at run time.
- Available modes are:
- Produce a trace of all basic blocks.
- Count frequency of jump instructions executed.
- In every mode it is possible to start profiling upon entering
- certain functions and to disable profiling of some other functions.
-
- The result of basic-block profiling will be written to a file `bb.out'.
- If the -ax option is used parameters for the profiling will be read
- from file `bb.in'.
-
-*/
-
-#define FUNCTION_BLOCK_PROFILER(FILE, BLOCKNO) \
- if (profile_block_flag == 2) \
- { \
- if (! TARGET_C3X) \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tr2\n"); \
- fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \
- if (BLOCKNO > 32767) \
- { \
- fprintf (FILE, "\tldhi\t%d,r2\n", (BLOCKNO) >> 16); \
- fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \
- } \
- else \
- { \
- fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \
- } \
- fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \
- fprintf (FILE, "\tpop\tr2\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tr2\n"); \
- fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \
- fprintf (FILE, "\tlsh\t16,ar2\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \
- if (BLOCKNO > 32767) \
- { \
- fprintf (FILE, "\tldi\t%d,r2\n", (BLOCKNO) >> 16); \
- fprintf (FILE, "\tlsh\t16,r2\n"); \
- fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \
- } \
- else \
- { \
- fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \
- } \
- fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \
- fprintf (FILE, "\tpop\tr2\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- } \
- else \
- { \
- if (! TARGET_C3X) \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \
- fprintf (FILE, "\tcmpi\t0,*ar2\n"); \
- fprintf (FILE, "\tbne\t$+2\n"); \
- fprintf (FILE, "\tcall\t___bb_init_func\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tr2\n"); \
- fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \
- fprintf (FILE, "\tlsh\t16,ar2\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \
- fprintf (FILE, "\tldi\t*ar2,r2\n"); \
- fprintf (FILE, "\tbne\t$+2\n"); \
- fprintf (FILE, "\tcall\t___bb_init_func\n"); \
- fprintf (FILE, "\tpop\tr2\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- }
-
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
- if (profile_block_flag == 2) \
- { \
- if (! TARGET_C3X) \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tar0\n"); \
- fprintf (FILE, "\tldhi\t^___bb,ar2\n"); \
- fprintf (FILE, "\tor\t#___bb,ar2\n"); \
- if (BLOCKNO > 32767) \
- { \
- fprintf (FILE, "\tldhi\t%d,ar0\n", (BLOCKNO) >> 16);\
- fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \
- } \
- else \
- { \
- fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \
- } \
- fprintf (FILE, "\tsti\tar0,*ar2\n"); \
- fprintf (FILE, "\tldhi\t^LPBX0,ar0\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \
- fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \
- fprintf (FILE, "\tcall\t___bb_trace_func\n"); \
- fprintf (FILE, "\tpop\tar0\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tar0\n"); \
- fprintf (FILE, "\tldiu\t^___bb,ar2\n"); \
- fprintf (FILE, "\tlsh\t16,ar2\n"); \
- fprintf (FILE, "\tor\t#___bb,ar2\n"); \
- if (BLOCKNO > 32767) \
- { \
- fprintf (FILE, "\tldi\t%d,ar0\n", (BLOCKNO) >> 16); \
- fprintf (FILE, "\tlsh\t16,ar0\n"); \
- fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \
- } \
- else \
- { \
- fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \
- } \
- fprintf (FILE, "\tsti\tar0,*ar2\n"); \
- fprintf (FILE, "\tldiu\t^LPBX0,ar0\n"); \
- fprintf (FILE, "\tlsh\t16,ar0\n"); \
- fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \
- fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \
- fprintf (FILE, "\tcall\t___bb_trace_func\n"); \
- fprintf (FILE, "\tpop\tar0\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- } \
- } \
- else \
- { \
- if (! TARGET_C3X) \
- { \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tar0\n"); \
- fprintf (FILE, "\tldhi\t^LPBX2+%d,ar2\n", (BLOCKNO)); \
- fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \
- fprintf (FILE, "\taddi3\t1,*ar2,ar0\n"); \
- fprintf (FILE, "\tsti\tar0,*ar2\n"); \
- fprintf (FILE, "\tpop\tar0\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tpush\tar0\n"); \
- fprintf (FILE, "\tldiu\t^LPBX2+%d,ar2\n", (BLOCKNO)); \
- fprintf (FILE, "\tlsh\t16,ar2\n"); \
- fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \
- fprintf (FILE, "\tldiu\t*ar2,ar0\n"); \
- fprintf (FILE, "\taddi\t1,ar0\n"); \
- fprintf (FILE, "\tsti\tar0,*ar2\n"); \
- fprintf (FILE, "\tpop\tar0\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- } \
- }
-
-#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
- { \
- fprintf (FILE, "\tpush\tst\n"); \
- fprintf (FILE, "\tpush\tar2\n"); \
- fprintf (FILE, "\tcall\t___bb_trace_ret\n"); \
- fprintf (FILE, "\tpop\tar2\n"); \
- fprintf (FILE, "\tpop\tst\n"); \
- }
-
-#define MACHINE_STATE_SAVE(ID) \
- asm(" push r0"); \
- asm(" pushf r0"); \
- asm(" push r1"); \
- asm(" pushf r1"); \
- asm(" push r2"); \
- asm(" pushf r2"); \
- asm(" push r3"); \
- asm(" pushf r3"); \
- asm(" push ar0"); \
- asm(" push ar1"); \
- asm(" .if .BIGMODEL"); \
- asm(" push dp"); \
- asm(" .endif"); \
- asm(" push ir0"); \
- asm(" push ir1"); \
- asm(" push bk"); \
- asm(" push rs"); \
- asm(" push re"); \
- asm(" push rc"); \
- asm(" .if .tms320C40"); \
- asm(" push r9"); \
- asm(" pushf r9"); \
- asm(" push r10"); \
- asm(" pushf r10"); \
- asm(" push r11"); \
- asm(" pushf r11"); \
- asm(" .endif");
-
-#define MACHINE_STATE_RESTORE(ID) \
- asm(" .if .tms320C40"); \
- asm(" popf r11"); \
- asm(" pop r11"); \
- asm(" popf r10"); \
- asm(" pop r10"); \
- asm(" popf r9"); \
- asm(" pop r9"); \
- asm(" .endif"); \
- asm(" pop rc"); \
- asm(" pop re"); \
- asm(" pop rs"); \
- asm(" pop bk"); \
- asm(" pop ir1"); \
- asm(" pop ir0"); \
- asm(" .if .BIGMODEL"); \
- asm(" pop dp"); \
- asm(" .endif"); \
- asm(" pop ar1"); \
- asm(" pop ar0"); \
- asm(" popf r3"); \
- asm(" pop r3"); \
- asm(" popf r2"); \
- asm(" pop r2"); \
- asm(" popf r1"); \
- asm(" pop r1"); \
- asm(" popf r0"); \
- asm(" pop r0"); \
-
-/* Implicit Calls to Library Routines */
-
-#define MULQI3_LIBCALL "__mulqi3"
-#define DIVQI3_LIBCALL "__divqi3"
-#define UDIVQI3_LIBCALL "__udivqi3"
-#define MODQI3_LIBCALL "__modqi3"
-#define UMODQI3_LIBCALL "__umodqi3"
-
-#define DIVQF3_LIBCALL "__divqf3"
-
-#define MULHF3_LIBCALL "__mulhf3"
-#define DIVHF3_LIBCALL "__divhf3"
-
-#define MULHI3_LIBCALL "__mulhi3"
-#define SMULHI3_LIBCALL "__smulhi3_high"
-#define UMULHI3_LIBCALL "__umulhi3_high"
-#define DIVHI3_LIBCALL "__divhi3"
-#define UDIVHI3_LIBCALL "__udivhi3"
-#define MODHI3_LIBCALL "__modhi3"
-#define UMODHI3_LIBCALL "__umodhi3"
-
-#define FLOATHIQF2_LIBCALL "__floathiqf2"
-#define FLOATUNSHIQF2_LIBCALL "__ufloathiqf2"
-#define FIX_TRUNCQFHI2_LIBCALL "__fix_truncqfhi2"
-#define FIXUNS_TRUNCQFHI2_LIBCALL "__ufix_truncqfhi2"
-
-#define FLOATHIHF2_LIBCALL "__floathihf2"
-#define FLOATUNSHIHF2_LIBCALL "__ufloathihf2"
-#define FIX_TRUNCHFHI2_LIBCALL "__fix_trunchfhi2"
-#define FIXUNS_TRUNCHFHI2_LIBCALL "__ufix_trunchfhi2"
-
-#define FFS_LIBCALL "__ffs"
-
-#define TARGET_MEM_FUNCTIONS
-
-/* Add any extra modes needed to represent the condition code.
-
- On the C4x, we have a "no-overflow" mode which is used when an ADD,
- SUB, NEG, or MPY insn is used to set the condition code. This is
- to prevent the combiner from optimising away a following CMP of the
- result with zero when a signed conditional branch or load insn
- follows.
-
- The problem is a subtle one and deals with the manner in which the
- negative condition (N) flag is used on the C4x. This flag does not
- reflect the status of the actual result but of the ideal result had
- no overflow occured (when considering signed operands).
-
- For example, 0x7fffffff + 1 => 0x80000000 Z=0 V=1 N=0 C=0. Here
- the flags reflect the untruncated result, not the actual result.
- While the actual result is less than zero, the N flag is not set
- since the ideal result of the addition without truncation would
- have been positive.
-
- Note that the while the N flag is handled differently to most other
- architectures, the use of it is self consistent and is not the
- cause of the problem.
-
- Logical operations set the N flag to the MSB of the result so if
- the result is negative, N is 1. However, integer and floating
- point operations set the N flag to be the MSB of the result
- exclusive ored with the overflow (V) flag. Thus if an overflow
- occurs and the result does not have the MSB set (i.e., the result
- looks like a positive number), the N flag is set. Conversely, if
- an overflow occurs and the MSB of the result is set, N is set to 0.
- Thus the N flag represents the sign of the result if it could have
- been stored without overflow but does not represent the apparent
- sign of the result. Note that most architectures set the N flag to
- be the MSB of the result.
-
- The C4x approach to setting the N flag simplifies signed
- conditional branches and loads which only have to test the state of
- the N flag, whereas most architectures have to look at both the N
- and V flags. The disadvantage is that there is no flag giving the
- status of the sign bit of the operation. However, there are no
- conditional load or branch instructions that make use of this
- feature (e.g., BMI---branch minus) instruction. Note that BN and
- BLT are identical in the C4x.
-
- To handle the problem where the N flag is set differently whenever
- there is an overflow we use a different CC mode, CC_NOOVmode which
- says that the CC reflects the comparison of the result against zero
- if no overflow occured.
-
- For example,
-
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "")
- (minus:QI (match_dup 1)
- (match_dup 2)))]
-
- Note that there is no problem for insns that don't return a result
- like CMP, since the CC reflects the effect of operation.
-
- An example of a potential problem is when GCC
- converts (LTU (MINUS (0x80000000) (0x7fffffff) (0x80000000)))
- to (LEU (MINUS (0x80000000) (0x7fffffff) (0x7fffffff)))
- to (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000)))
-
- Now (MINUS (0x80000000) (0x7fffffff)) returns 0x00000001 but the
- C4x sets the N flag since the result without overflow would have
- been 0xffffffff when treating the operands as signed integers.
- Thus (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) sets the N
- flag but (GE (0x00000001)) does not set the N flag.
-
- The upshot is that we can not use signed branch and conditional
- load instructions after an add, subtract, neg, abs or multiply.
- We must emit a compare insn to check the result against 0. */
-
-#define EXTRA_CC_MODES CC_NOOVmode
-
-/* Define the names for the modes specified above. */
-
-#define EXTRA_CC_NAMES "CC_NOOV"
-
-/* CC_NOOVmode should be used when the first operand is a PLUS, MINUS, NEG
- or MULT.
- CCmode should be used when no special processing is needed. */
-#define SELECT_CC_MODE(OP,X,Y) \
- ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
- || GET_CODE (X) == NEG || GET_CODE (X) == MULT \
- || GET_MODE (X) == ABS \
- || GET_CODE (Y) == PLUS || GET_CODE (Y) == MINUS \
- || GET_CODE (Y) == NEG || GET_CODE (Y) == MULT \
- || GET_MODE (Y) == ABS) \
- ? CC_NOOVmode : CCmode)
-
-extern struct rtx_def *c4x_gen_compare_reg ();
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-#define HAVE_PRE_INCREMENT 1
-#define HAVE_POST_DECREMENT 1
-#define HAVE_PRE_DECREMENT 1
-#define HAVE_PRE_MODIFY_REG 1
-#define HAVE_POST_MODIFY_REG 1
-#define HAVE_PRE_MODIFY_DISP 1
-#define HAVE_POST_MODIFY_DISP 1
-
-#define HAVE_MULTIPLE_PACK 2
-
-/* What about LABEL_REF? */
-#define CONSTANT_ADDRESS_P(X) (GET_CODE (X) == SYMBOL_REF)
-
-#define MAX_REGS_PER_ADDRESS 2
-
-/* 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. */
-
-extern int c4x_check_legit_addr ();
-
-#ifndef REG_OK_STRICT
-
-/* Nonzero if X is a hard or pseudo reg that can be used as an base. */
-
-#define REG_OK_FOR_BASE_P(X) IS_ADDR_OR_PSEUDO_REG(REGNO(X))
-
-/* Nonzero if X is a hard or pseudo reg that can be used as an index. */
-
-#define REG_OK_FOR_INDEX_P(X) IS_INDEX_OR_PSEUDO_REG(REGNO(X))
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (c4x_check_legit_addr (MODE, X, 0)) \
- goto ADDR; \
-}
-
-#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))
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (c4x_check_legit_addr (MODE, X, 1)) \
- goto ADDR; \
-}
-
-#endif
-
-extern struct rtx_def *c4x_legitimize_address ();
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-{ \
- rtx new; \
- new = c4x_legitimize_address (X, MODE); \
- if (new != NULL_RTX) \
- { \
- (X) = new; \
- goto WIN; \
- } \
-}
-
-
-/* No mode-dependent addresses on the C4x are autoincrements. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
- if (GET_CODE (ADDR) == PRE_DEC \
- || GET_CODE (ADDR) == POST_DEC \
- || GET_CODE (ADDR) == PRE_INC \
- || GET_CODE (ADDR) == POST_INC \
- || GET_CODE (ADDR) == POST_MODIFY \
- || GET_CODE (ADDR) == PRE_MODIFY) \
- goto LABEL
-
-
-/* Nonzero if the constant value X is a legitimate general operand.
- It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
-
- The C4x can only load 16-bit immediate values, so we only allow
- a restricted subset of CONST_INT and CONST_DOUBLE and reject
- LABEL_REF, SYMBOL_REF, CONST, and HIGH codes. */
-
-#define LEGITIMATE_CONSTANT_P(X) \
- ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \
- || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)))
-
-
-#define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X))
-
-/* Descripting Relative Cost of Operations */
-
-/* Provide the costs of a rtl expression. This is in the body of a
- switch on CODE.
-
- Note that we return, rather than break so that rtx_cost doesn't
- include CONST_COSTS otherwise expand_mult will think that it is
- cheaper to synthesise a multiply rather than to use a multiply
- instruction. I think this is because the algorithm synth_mult
- doesn't take into account the loading of the operands, whereas the
- calculation of mult_cost does.
-*/
-
-
-#define RTX_COSTS(RTX, CODE, OUTER_CODE) \
- case MULT: \
- return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \
- || TARGET_MPYI ? 1 : 14); \
- case DIV: case UDIV: case MOD: case UMOD: \
- return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \
- ? 15 : 50);
-
-/* Compute the cost of computing a constant rtl expression RTX
- whose rtx-code is CODE. The body of this macro is a portion
- of a switch statement. If the code is computed here,
- return it with a return statement. Otherwise, break from the switch.
-
- An insn is assumed to cost 4 units.
- COSTS_N_INSNS (N) is defined as (N) * 4 - 2.
-
- Some small integers are effectively free for the C40. We should
- also consider if we are using the small memory model. With
- the big memory model we require an extra insn for a constant
- loaded from memory. */
-
-#define SHIFT_CODE_P(C) ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT)
-
-#define LOGICAL_CODE_P(C) ((C) == NOT || (C) == AND \
- || (C) == IOR || (C) == XOR)
-
-#define NON_COMMUTATIVE_CODE_P ((C) == MINUS || (C) == COMPARE)
-
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
- case CONST_INT: \
- if (c4x_J_constant (RTX)) \
- return 0; \
- if (TARGET_C3X && SHIFT_CODE_P (OUTER_CODE)) \
- return 3; \
- if (LOGICAL_CODE_P (OUTER_CODE) \
- ? c4x_L_constant (RTX) : c4x_I_constant (RTX)) \
- return 2; \
- case CONST: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return 4; \
- case CONST_DOUBLE: \
- if (c4x_H_constant (RTX)) \
- return 2; \
- if (GET_MODE (RTX) == QFmode) \
- return 4; \
- else \
- return 8;
-
-/* 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. We handle the most common address without
- a call to c4x_address_cost. */
-
-extern int c4x_address_cost ();
-
-#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : c4x_address_cost (ADDR))
-
-#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
-if (REG_P (OP1) && ! REG_P (OP0)) \
-{ \
- rtx tmp = OP0; OP0 = OP1 ; OP1 = tmp; \
- CODE = swap_condition (CODE); \
-}
-
-#define EXT_CLASS_P(CLASS) (reg_class_subset_p (CLASS, EXT_REGS))
-#define ADDR_CLASS_P(CLASS) (reg_class_subset_p (CLASS, ADDR_REGS))
-#define INDEX_CLASS_P(CLASS) (reg_class_subset_p (CLASS, INDEX_REGS))
-#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \
- || INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG)
-
-/* Compute extra cost of moving data between one register class
- and another. */
-
-#define REGISTER_MOVE_COST(FROM, TO) 2
-
-/* Memory move cost is same as fast register move. Maybe this should
- be bumped up? */
-
-#define MEMORY_MOVE_COST(M,C,I) 4
-
-/* Branches are kind of expensive (even with delayed branching) so
- make their cost higher. */
-
-#define BRANCH_COST 8
-
-/* Adjust the cost of dependencies. */
-
-#define ADJUST_COST(INSN,LINK,DEP,COST) \
- (COST) = c4x_adjust_cost (INSN, LINK, DEP, COST)
-
-#define WORD_REGISTER_OPERATIONS
-
-/* Dividing the Output into Sections */
-
-#define TEXT_SECTION_ASM_OP "\t.text"
-
-#define DATA_SECTION_ASM_OP "\t.data"
-
-#define USE_CONST_SECTION 1
-
-#define CONST_SECTION_ASM_OP "\t.sect\t\".const\""
-
-/* Do not use .init section so __main will be called on startup. This will
- call __do_global_ctors and prepare for __do_global_dtors on exit. */
-
-#if 0
-#define INIT_SECTION_ASM_OP "\t.sect\t\".init\""
-#endif
-
-#define FINI_SECTION_ASM_OP "\t.sect\t\".fini\""
-
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side. */
-
-/* Define a few machine-specific details of the implementation of
- constructors.
-
- The __CTORS_LIST__ goes in the .ctors section. Define CTOR_LIST_BEGIN
- and CTOR_LIST_END to contribute to the .ctors section an instruction to
- push a word containing 0 (or some equivalent of that).
-
- Define ASM_OUTPUT_CONSTRUCTOR to push the address of the constructor. */
-
-#define CTORS_SECTION_ASM_OP "\t.sect\t\".ctors\""
-#define DTORS_SECTION_ASM_OP "\t.sect\t\".dtors\""
-
-/* Constructor list on stack is in reverse order. Go to the end of the
- list and go backwards to call constructors in the right order. */
-
-#define DO_GLOBAL_CTORS_BODY \
-do { \
- extern func_ptr __CTOR_LIST__[]; \
- func_ptr *p, *beg = __CTOR_LIST__ + 1; \
- for (p = beg; *p ; p++) ; \
- while (p != beg) \
- (*--p) (); \
-} while (0)
-
-/* The TI tooling uses atexit. */
-#define HAVE_ATEXIT
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
- INIT_SECTION_FUNCTION \
- FINI_SECTION_FUNCTION \
- CTORS_SECTION_FUNCTION \
- DTORS_SECTION_FUNCTION
-
-#define INIT_SECTION_FUNCTION \
-void \
-init_section () \
-{ \
- if (in_section != in_init) \
- { \
- fprintf (asm_out_file, ";\t.init\n"); \
- in_section = in_init; \
- } \
-}
-
-#define FINI_SECTION_FUNCTION \
-void \
-fini_section () \
-{ \
- if (in_section != in_fini) \
- { \
- fprintf (asm_out_file, "\t%s\n", FINI_SECTION_ASM_OP); \
- in_section = in_fini; \
- } \
-}
-
-#define READONLY_DATA_SECTION() const_section ()
-
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- extern void text_section(); \
- if (! USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
-#define ASM_STABS_OP "\t.stabs"
-
-/* The ctors and dtors sections are not normally put into use
- by EXTRA_SECTIONS and EXTRA_SECTION_FUNCTIONS as defined in svr3.h,
- but it can't hurt to define these macros for whatever systems use them. */
-
-#define CTORS_SECTION_FUNCTION \
-void \
-ctors_section () \
-{ \
- if (in_section != in_ctors) \
- { \
- fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
- in_section = in_ctors; \
- } \
-}
-
-#define DTORS_SECTION_FUNCTION \
-void \
-dtors_section () \
-{ \
- if (in_section != in_dtors) \
- { \
- fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
- in_section = in_dtors; \
- } \
-}
-
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
- fprintf (FILE, "\t.sect\t\"%s\"\n", NAME);
-
-/* This is machine-dependent because it needs to push something
- on the stack. */
-
-/* A C statement (sans semicolon) to output an element in the table of
- global constructors. */
-#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
- do { \
- ctors_section (); \
- fprintf (FILE, "\t.word\t "); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
-/* A C statement (sans semicolon) to output an element in the table of
- global destructors. */
-#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
- do { \
- dtors_section (); \
- fprintf (FILE, "\t.word\t "); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations. */
-
-#define SELECT_SECTION(DECL, RELOC) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if ((0 && RELOC) /* should be (flag_pic && RELOC) */ \
- || ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
- || ! DECL_INITIAL (DECL) \
- || (DECL_INITIAL (DECL) != error_mark_node \
- && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \
- data_section (); \
- else \
- const_section (); \
- } \
- else \
- const_section (); \
-}
-
-/* A C statement or statements to switch to the appropriate
- section for output of RTX in mode MODE. RTX is some kind
- of constant in RTL. The argument MODE is redundant except
- in the case of a `const_int' rtx. Currently, these always
- go into the const section. */
-
-#define SELECT_RTX_SECTION(MODE, RTX) const_section()
-
-
-/* Overall Framework of an Assembler File */
-
-#define ASM_FILE_START(FILE) \
-{ \
- int dspversion = 0; \
- if (TARGET_C30) dspversion = 30; \
- if (TARGET_C31) dspversion = 31; \
- if (TARGET_C32) dspversion = 32; \
- if (TARGET_C40) dspversion = 40; \
- if (TARGET_C44) dspversion = 44; \
- fprintf (FILE, "\t.version\t%d\n", dspversion); \
- fprintf (FILE, "\t.file\t"); \
- if (TARGET_TI) \
- { \
- char *p; \
- char *after_dir = main_input_filename; \
- for (p = main_input_filename; *p; p++) \
- if (*p == '/') \
- after_dir = p + 1; \
- output_quoted_string (FILE, after_dir); \
- } \
- else \
- output_quoted_string (FILE, main_input_filename); \
- fprintf (FILE, "\n"); \
-}
-
-#define ASM_FILE_END(FILE) fprintf (FILE, "\t.end\n")
-
-/* We need to have a data section we can identify so that we can set
- the DP register back to a data pointer in the small memory model.
- This is only required for ISRs if we are paranoid that someone
- may have quietly changed this register on the sly. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
- if (! TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \
- fputs ("\t.data\ndata_sec:\n", FILE);
-
-#define ASM_COMMENT_START ";"
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF ""
-
-/* Output float/double constants QFmode. */
-
-#define ASM_OUTPUT_BYTE_FLOAT(FILE, VALUE) \
-{ long l; \
- char str[30]; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \
- if (sizeof (int) == sizeof (long)) \
- fprintf (FILE, "\t.word\t0%08xh\t; %s\n", l, str);\
- else \
- fprintf (FILE, "\t.word\t0%08lxh\t; %s\n", l, str);\
-}
-
-/* Output long double constants HFmode.
- The first word contains the exponent and first part of the mantissa
- in the same manner as QFmode. The second word contains the full
- mantissa. We should ensure that the two words are allocated within
- the same page for the large memory model since we only output a single
- LDP instruction. FIXME. The simplest solution probably is to output
- a LDP for each load. */
-
-#define ASM_OUTPUT_SHORT_FLOAT(FILE, VALUE) \
-{ long l[2]; \
- char str[30]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \
- l[1] = (l[0] << 8) | ((l[1] >> 24) & 0xff); \
- if (sizeof (int) == sizeof (long)) \
- fprintf (FILE, "\t.word\t0%08xh\t; %s\n\t.word\t0%08xh\n", \
- l[0], str, l[1]); \
- else \
- fprintf (FILE, "\t.word\t0%08lxh\t; %s\n\t.word\t0%08lxh\n", \
- l[0], str, l[1]); \
-}
-
-#define ASM_OUTPUT_CHAR(FILE, VALUE) \
-{ fprintf (FILE, "\t.word\t"); \
- output_addr_const (FILE, VALUE); \
- if (GET_CODE (VALUE) != SYMBOL_REF) \
- fprintf (FILE, " ; 0%08xh\n", INTVAL (VALUE)); \
- else \
- fputc ('\n', FILE); \
-}
-
-#define ASM_OUTPUT_BYTE(FILE, VALUE) \
- fprintf (FILE, "\t.word\t0%xh\n", (VALUE))
-
-extern void c4x_output_ascii ();
-#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) c4x_output_ascii (FILE, PTR, LEN)
-
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-
-/* Output and Generation of Labels */
-
-#define NO_DOT_IN_LABEL /* Only required for TI format */
-
-#define ASM_OUTPUT_LABEL(FILE, NAME) \
-{ assemble_name (FILE, NAME); fputs (":\n", FILE); }
-
-#define ASM_GLOBALIZE_LABEL(FILE, NAME) \
-{ \
- fprintf (FILE, "\t.global\t"); \
- assemble_name (FILE, NAME); \
- fputs ("\n", FILE); \
-}
-
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
-{ \
- fprintf (FILE, "\t.ref\t"); \
- assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
-}
-
-/* A C statement to output on FILE an assembler pseudo-op to
- declare a library function named external.
- (Only needed to keep asm30 happy for ___divqf3 etc.) */
-
-#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
-{ \
- fprintf (FILE, "\t.ref\t"); \
- assemble_name (FILE, XSTR (FUN, 0)); \
- fprintf (FILE, "\n"); \
-}
-
-/* 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) \
-asm_fprintf (FILE, "%s%d:\n", PREFIX, NUM)
-
-/* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
-#define ASM_GENERATE_INTERNAL_LABEL(BUFFER, PREFIX, NUM) \
- sprintf (BUFFER, "*%s%d", PREFIX, NUM)
-
-/* 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)))
-
-
-/* Output of Dispatch Tables */
-
-/* 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\tL%d\n", VALUE);
-
-/* This is how to output an element of a case-vector that is relative. */
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- fprintf (FILE, "\t.long\tL%d-L%d\n", VALUE, REL);
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-#define INT_TYPE_SIZE 32
-#define LONG_LONG_TYPE_SIZE 64
-#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 32
-#define LONG_DOUBLE_TYPE_SIZE 64 /* actually only 40 */
-
-/* Allow #sccs in preprocessor. */
-
-#define SCCS_DIRECTIVE
-
-/* Output #ident as a .ident. */
-
-#define ASM_OUTPUT_IDENT(FILE, NAME) \
- fprintf (FILE, "\t.ident \"%s\"\n", NAME);
-
-#define CPP_PREDEFINES ""
-
-/* This says how to output an assembler line
- to define a local common symbol. */
-
-#undef ASM_OUTPUT_LOCAL
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
-( fputs ("\t.bss\t", FILE), \
- assemble_name (FILE, (NAME)), \
- fprintf (FILE, ",%u\n", (ROUNDED)))
-
-/* Output of Uninitialized Variables */
-
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
-( fputs ("\t.globl\t", FILE), \
- assemble_name (FILE, (NAME)), \
- fputs ("\n\t.bss\t", FILE), \
- assemble_name (FILE, (NAME)), \
- fprintf (FILE, ",%u\n", (ROUNDED)))
-
-/* Macros Controlling Initialization Routines */
-
-#define OBJECT_FORMAT_COFF
-#define REAL_NM_FILE_NAME "c4x-nm"
-
-/* Output of Assembler Instructions */
-
-/* Register names when used for integer modes. */
-
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \
- "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \
- "iif", "rs", "re", "rc", "r8", "r9", "r10", "r11" \
-}
-
-/* Alternate register names when used for floating point modes. */
-
-#define FLOAT_REGISTER_NAMES \
-{ \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \
- "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \
- "iif", "rs", "re", "rc", "f8", "f9", "f10", "f11" \
-}
-
-
-extern void c4x_print_operand ();
-#define PRINT_OPERAND(FILE, X, CODE) c4x_print_operand(FILE, X, CODE)
-
-/* Determine which codes are valid without a following integer. These must
- not be alphabetic. */
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#')
-
-extern void c4x_print_operand_address ();
-#define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X)
-
-/* Define this macro if you want to implement any pragmas. If defined, it
- should be a C expression to be executed when #pragma is seen. The
- argument STREAM is the stdio input stream from which the source
- text can be read. CH is the first character after the #pragma. The
- result of the expression is the terminating character found
- (newline or EOF). */
-extern int c4x_handle_pragma ();
-#define HANDLE_PRAGMA(GETC, UNGETC, NAME) \
- c4x_handle_pragma (GETC, UNGETC, NAME)
-
-extern void c4x_set_default_attributes ();
-#define SET_DEFAULT_DECL_ATTRIBUTES(DECL, ATTRIBUTES) \
- c4x_set_default_attributes (DECL, &ATTRIBUTES)
-
-extern int c4x_valid_type_attribute_p ();
-#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
- (c4x_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
-
-/* Assembler Commands for Alignment */
-
-#define ASM_OUTPUT_SKIP(FILE, SIZE) \
-{ int c = SIZE; \
- for (; c > 0; --c) \
- fprintf (FILE,"\t.word\t0\n"); \
-}
-
-#define ASM_NO_SKIP_IN_TEXT 1
-
-/* I'm not sure about this one. FIXME. */
-
-#define ASM_OUTPUT_ALIGN(FILE, LOG) \
- if ((LOG) != 0) \
- fprintf (FILE, "\t.align\t%d\n", (1 << (LOG)))
-
-
-/* Macros for SDB and DWARF Output (use .sdef instead of .def
- to avoid conflict with TI's use of .def) */
-
-#define SDB_DELIM "\n"
-#define SDB_DEBUGGING_INFO
-
-#define PUT_SDB_DEF(A) \
-do { fprintf (asm_out_file, "\t.sdef\t"); \
- ASM_OUTPUT_LABELREF (asm_out_file, A); \
- fprintf (asm_out_file, SDB_DELIM); } while (0)
-
-#define PUT_SDB_PLAIN_DEF(A) \
- fprintf (asm_out_file,"\t.sdef\t.%s%s", A, SDB_DELIM)
-
-#define PUT_SDB_BLOCK_START(LINE) \
- fprintf (asm_out_file, \
- "\t.sdef\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
-
-#define PUT_SDB_BLOCK_END(LINE) \
- fprintf (asm_out_file, \
- "\t.sdef\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
-
-#define PUT_SDB_FUNCTION_START(LINE) \
- fprintf (asm_out_file, \
- "\t.sdef\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
-
-#define PUT_SDB_FUNCTION_END(LINE) \
- fprintf (asm_out_file, \
- "\t.sdef\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
-
-#define PUT_SDB_EPILOGUE_END(NAME) \
-do { fprintf (asm_out_file, "\t.sdef\t"); \
- ASM_OUTPUT_LABELREF (asm_out_file, NAME); \
- fprintf (asm_out_file, \
- "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
-
-
-/* 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
-
-/* This is the kind of divide that is easiest to do in the general case. */
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-
-#define DEFAULT_SIGNED_CHAR 1
-
-/* A function address in a call instruction is a byte address (for
- indexing purposes) so give the MEM rtx a byte's mode. */
-
-#define FUNCTION_MODE QImode
-
-#define SLOW_BYTE_ACCESS 0
-
-/* 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 QImode
-
-/* On the C4x we can write the following code. We have to clear the cache
- every time we execute it because the data in the stack could change.
-
- laj $+4
- addi3 4,r11,ar0
- lda *ar0,ar1
- lda *+ar0(1),ar0
- bud ar1
- nop
- nop
- or 1000h,st
- .word FNADDR
- .word CXT
-
- On the c3x this is a bit more difficult. We have to write self
- modifying code here. So we have to clear the cache every time
- we execute it because the data in the stack could change.
-
- ldiu TOP_OF_FUNCTION,ar1
- lsh 16,ar1
- or BOTTOM_OF_FUNCTION,ar1
- ldiu TOP_OF_STATIC,ar0
- bud ar1
- lsh 16,ar0
- or BOTTOM_OF_STATIC,ar0
- or 1000h,st
-
- */
-
-#define TRAMPOLINE_SIZE (TARGET_C3X ? 8 : 10)
-
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- if (TARGET_C3X) \
- { \
- asm_fprintf (FILE, "\tldiu\t0,ar1\n"); \
- asm_fprintf (FILE, "\tlsh\t16,ar1\n"); \
- asm_fprintf (FILE, "\tor\t0,ar1\n"); \
- asm_fprintf (FILE, "\tldiu\t0,ar0\n"); \
- asm_fprintf (FILE, "\tbud\tar1\n"); \
- asm_fprintf (FILE, "\tlsh\t16,ar0\n"); \
- asm_fprintf (FILE, "\tor\t0,ar0\n"); \
- asm_fprintf (FILE, "\tor\t1000h,st\n"); \
- } \
- else \
- { \
- asm_fprintf (FILE, "\tlaj\t$+4\n"); \
- asm_fprintf (FILE, "\taddi3\t4,r11,ar0\n"); \
- asm_fprintf (FILE, "\tlda\t*ar0,ar1\n"); \
- asm_fprintf (FILE, "\tlda\t*+ar0(1),ar0\n"); \
- asm_fprintf (FILE, "\tbud\tar1\n"); \
- asm_fprintf (FILE, "\tnop\n"); \
- asm_fprintf (FILE, "\tnop\n"); \
- asm_fprintf (FILE, "\tor\t1000h,st\n"); \
- asm_fprintf (FILE, "\t.word\t0\n"); \
- asm_fprintf (FILE, "\t.word\t0\n"); \
- } \
-}
-
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- if (TARGET_C3X) \
- { \
- rtx tmp1, tmp2; \
- tmp1 = expand_shift (RSHIFT_EXPR, QImode, FNADDR, \
- size_int (16), 0, 1); \
- tmp2 = expand_shift (LSHIFT_EXPR, QImode, \
- gen_rtx (CONST_INT, VOIDmode, 0x5069), \
- size_int (16), 0, 1); \
- emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (tramp, 0)), tmp1); \
- tmp1 = expand_and (FNADDR, gen_rtx (CONST_INT, VOIDmode, \
- 0xffff), 0); \
- tmp2 = expand_shift (LSHIFT_EXPR, QImode, \
- gen_rtx (CONST_INT, VOIDmode, 0x1069), \
- size_int (16), 0, 1); \
- emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (tramp, 2)), tmp1); \
- tmp1 = expand_shift (RSHIFT_EXPR, QImode, CXT, \
- size_int (16), 0, 1); \
- tmp2 = expand_shift (LSHIFT_EXPR, QImode, \
- gen_rtx (CONST_INT, VOIDmode, 0x5068), \
- size_int (16), 0, 1); \
- emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (tramp, 3)), tmp1); \
- tmp1 = expand_and (CXT, gen_rtx (CONST_INT, VOIDmode, \
- 0xffff), 0); \
- tmp2 = expand_shift (LSHIFT_EXPR, QImode, \
- gen_rtx (CONST_INT, VOIDmode, 0x1068), \
- size_int (16), 0, 1); \
- emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (tramp, 6)), tmp1); \
- } \
- else \
- { \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (TRAMP, 8)), FNADDR); \
- emit_move_insn (gen_rtx (MEM, QImode, \
- plus_constant (TRAMP, 9)), CXT); \
- } \
-}
-
-/* Specify the machine mode that this machine uses for the index in
- the tablejump instruction. */
-
-#define CASE_VECTOR_MODE Pmode
-
-/* Max number of (32-bit) bytes we can move from memory to memory
- in one reasonably fast instruction. */
-
-#define MOVE_MAX 1
-
-/* MOVE_RATIO is the number of move instructions that is better than a
- block move. */
-
-#define MOVE_RATIO 2 /* Default value */
-
-#define BSS_SECTION_ASM_OP ".bss"
-
-#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
- asm_fprintf (FILE, "\tpush\t%s\n", reg_names[REGNO])
-
-/* This is how to output an insn to pop a register from the stack.
- It need not be very fast code. */
-
-#define ASM_OUTPUT_REG_POP(FILE, REGNO) \
- asm_fprintf (FILE, "\tpop\t%s\n", reg_names[REGNO])
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* We need to use direct addressing for large constants and addresses
- that cannot fit within an instruction. We must check for these
- after after the final jump optimisation pass, since this may
- introduce a local_move insn for a SYMBOL_REF. This pass
- must come before delayed branch slot filling since it can generate
- additional instructions. */
-
-#define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS)
-
-#define MACHINE_DEPENDENT_COMBINE(INSNS) c4x_combine_parallel(INSNS)
-
-#define DBR_OUTPUT_SEQEND(FILE) \
-if (final_sequence != NULL_RTX) \
-{ \
- int count; \
- int laj = GET_CODE (XEXP (XEXP (final_sequence, 0), 0)) == CALL_INSN; \
- \
- count = dbr_sequence_length(); \
- while (count < (laj ? 2 : 3)) \
- { \
- fputs("\tnop\n", FILE); \
- count++; \
- } \
- if (laj) \
- fputs("\tpush\tr11\n", FILE); \
-}
-
-#define NO_FUNCTION_CSE
-
-/* We don't want a leading tab. */
-
-#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING)
-
-/* Define the codes that are matched by predicates in c4x.c. */
-
-#define PREDICATE_CODES \
- {"fp_zero_operand", {CONST_DOUBLE}}, \
- {"const_operand", {CONST_INT, CONST_DOUBLE}}, \
- {"stik_const_operand", {CONST_INT}}, \
- {"not_const_operand", {CONST_INT}}, \
- {"reg_operand", {REG, SUBREG}}, \
- {"reg_or_const_operand", {REG, SUBREG, CONST_INT, CONST_DOUBLE}},\
- {"r0r1_reg_operand", {REG, SUBREG}}, \
- {"r2r3_reg_operand", {REG, SUBREG}}, \
- {"ext_low_reg_operand", {REG, SUBREG}}, \
- {"ext_reg_operand", {REG, SUBREG}}, \
- {"std_reg_operand", {REG, SUBREG}}, \
- {"addr_reg_operand", {REG, SUBREG}}, \
- {"index_reg_operand", {REG, SUBREG}}, \
- {"dp_reg_operand", {REG}}, \
- {"sp_reg_operand", {REG}}, \
- {"st_reg_operand", {REG}}, \
- {"rc_reg_operand", {REG}}, \
- {"call_operand", {REG, SYMBOL_REF}}, \
- {"src_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"src_hi_operand", {SUBREG, REG, MEM, CONST_DOUBLE}}, \
- {"lsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"tsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
- {"par_ind_operand", {MEM}}, \
- {"parallel_operand", {SUBREG, REG, MEM}}, \
- {"mem_operand", {MEM}}, \
-
-
-/* Variables in c4x.c */
-
-extern enum reg_class c4x_regclass_map[];/* smallest class containing REGNO */
-extern enum machine_mode c4x_caller_save_map[];
-
-extern struct rtx_def *c4x_compare_op0; /* operand 0 for comparisons */
-extern struct rtx_def *c4x_compare_op1; /* operand 1 for comparisons */
-
-extern int c4x_rpts_cycles; /* max cycles for RPTS */
-extern int c4x_cpu_version; /* cpu version C30/31/32/40/44 */
-
-/* Functions in c4x.c */
-
-extern void c4x_function_prologue ();
-
-extern void c4x_function_epilogue ();
-
-extern struct rtx_def *c4x_operand_subword ();
-
-extern struct rtx_def *c4x_adj_offsettable_operand ();
-
-extern char *c4x_output_cbranch ();
-
-extern int c4x_null_epilogue_p ();
-
-extern int c4x_autoinc_operand ();
-
-extern int c4x_label_conflict ();
-
-extern int c4x_address_conflict ();
-
-extern int c4x_adjust_cost ();
-
-extern void c4x_process_after_reload ();
-
-extern void c4x_combine_parallel ();
-
-extern int c4x_rptb_nop_p ();
-
-extern int c4x_rptb_rpts_p ();
-
-extern int fp_zero_operand ();
-
-extern int const_operand ();
-
-extern int stik_const_operand ();
-
-extern int not_const_operand ();
-
-extern int parallel_operand ();
-
-extern int reg_or_const_operand ();
-
-extern int reg_operand ();
-
-extern int reg_imm_operand ();
-
-extern int r0r1_reg_operand ();
-
-extern int r2r3_reg_operand ();
-
-extern int ext_low_reg_operand ();
-
-extern int ext_reg_operand ();
-
-extern int std_reg_operand ();
-
-extern int src_operand ();
-
-extern int src_hi_operand ();
-
-extern int lsrc_operand ();
-
-extern int tsrc_operand ();
-
-extern int addr_reg_operand ();
-
-extern int index_reg_operand ();
-
-extern int dp_reg_operand ();
-
-extern int sp_reg_operand ();
-
-extern int rc_reg_operand ();
-
-extern int st_reg_operand ();
-
-extern int ar0_reg_operand ();
-
-extern int ar0_mem_operand ();
-
-extern int ar1_reg_operand ();
-
-extern int ar1_mem_operand ();
-
-extern int ar2_reg_operand ();
-
-extern int ar2_mem_operand ();
-
-extern int ar3_reg_operand ();
-
-extern int ar3_mem_operand ();
-
-extern int ar4_reg_operand ();
-
-extern int ar4_mem_operand ();
-
-extern int ar5_reg_operand ();
-
-extern int ar5_mem_operand ();
-
-extern int ar6_reg_operand ();
-
-extern int ar6_mem_operand ();
-
-extern int ar7_reg_operand ();
-
-extern int ar7_mem_operand ();
-
-extern int ir0_reg_operand ();
-
-extern int ir0_mem_operand ();
-
-extern int ir1_reg_operand ();
-
-extern int ir1_mem_operand ();
-
-extern int group1_reg_operand ();
-
-extern int group1_mem_operand ();
-
-extern int arx_reg_operand ();
-
-extern int call_operand ();
-
-extern int par_ind_operand ();
-
-extern int not_rc_reg ();
-
-extern int not_modify_reg ();
-
-extern int c4x_H_constant ();
-
-extern int c4x_I_constant ();
-
-extern int c4x_J_constant ();
-
-extern int c4x_L_constant ();
-
-extern int c4x_Q_constraint ();
-
-extern int c4x_R_constraint ();
-
-extern int c4x_S_constraint ();
-
-extern int c4x_T_constraint ();
-
-extern void c4x_emit_libcall ();
-
-extern void c4x_emit_libcall3 ();
-
-extern void c4x_emit_libcall_mulhi ();
-
-extern int legitimize_operands ();
-
-extern int valid_operands ();
-
-extern int valid_parallel_load_store ();
-
-extern int valid_parallel_operands_4 ();
-
-extern int valid_parallel_operands_5 ();
-
-extern int valid_parallel_operands_6 ();
diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md
deleted file mode 100755
index 1e3d343..0000000
--- a/gcc/config/c4x/c4x.md
+++ /dev/null
@@ -1,6877 +0,0 @@
-;; Machine description for the TMS320C[34]x for GNU C compiler
-;; Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
-
-;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
-;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl)
-
-;; 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.
-
-;
-; TODO :
-; Set up addressing macros to handle direct memory references properly.
-; Try using PQImode again for addresses since C30 only uses
-; 24-bit addresses. Ideally GCC would emit different insns
-; for QImode and Pmode, whether Pmode was QImode or PQImode.
-; For addresses we wouldn't have to have a clobber of the CC
-; associated with each insn and we could use MPYI in address
-; calculations without having to synthesise a proper 32 bit multiply.
-
-; Additional C30/C40 instructions not coded:
-; CALLcond, IACK, IDLE, LDE, LDFI, LDII, LDM, NORM, RETIcond
-; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI, TRAPcond
-
-; Additional C40 instructions not coded:
-; LDEP, LDPE, LWRct, FRIEEE, TOIEEE, LAJcond, LATcond, RETIcondD
-
-;
-; C4x MODES
-;
-; QImode char, short, int, long (32-bits)
-; HImode long long (64-bits)
-; QFmode float, double (32-bits)
-; HFmode long double (40-bits)
-; CCmode
-; CC_NOOVmode
-
-;
-; C4x PREDICATES:
-;
-; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE
-; memory_operand memory [m]
-; immediate_operand immediate constant [IKN]
-; register_operand register [rf]
-; general_operand register, memory, constant [rfmI]
-
-; addr_reg_operand AR0-AR7, pseudo reg [a]
-; sp_reg_operand SP [b]
-; std_reg_operand AR0-AR7, IR0-IR1, RC, RS, RE, SP, pseudo [c]
-; ext_reg_operand R0-R11, pseudo reg [f]
-; ext_low_reg_operand R0-R7, pseudo reg [q]
-; index_reg_operand IR0-IR1, pseudo reg [x]
-; st_reg_operand ST [y]
-; dp_reg_operand DP [z]
-; stik_const_operand 5-bit const [K]
-; src_operand general operand [rfmHI]
-; par_ind_operand indirect S mode (ARx + 0, 1, IRx) [S<>]
-; parallel_operand par_ind_operand or ext_low_reg_operand
-
-; ADDI src2, src1, dst three operand op
-; ADDI src, dst two operand op
-
-; Note that the predicates are only used when selecting a pattern
-; to determine if an operand is valid.
-
-; The constraints then select which of the possible valid operands
-; is present (and guide register selection). The actual assembly
-; instruction is then selected on the basis of the constraints.
-
-; The extra constraint (valid_operands) is used to determine if
-; the combination of operands is legitimate for the pattern.
-
-;
-; C4x CONSTRAINTS:
-;
-; a address reg AR0-AR7
-; b stack pointer SP
-; c other int reg AR0-AR7, IR0-IR1, RC, RS, RE
-; d fp reg R0-R11 (sets CC when dst)
-; e
-; f fp reg R0-R11 (sets CC when dst)
-; g general reg, memory, constant
-; h fp reg (HFmode) R0-R11 (sets CC when dst)
-; i immediate int constant
-; j
-; k block count BK
-; l
-; m memory
-; n immediate int constant with known numeric value
-; o offsettable memory
-; p memory address
-; q low fp reg R0-R7 (sets CC when dst)
-; r general reg R0-R11, AR0-AR7, IR0-IR1, RC, RS, RE
-; s immediate int constant (value not explicit)
-; t R0-R1
-; u R2-R3
-; v repeat count reg RC
-; w
-; x index reg IR0-IR1
-; y status (CC) reg ST
-; z data pointer DP
-
-; G fp zero
-; H fp 16-bit constant
-; I signed 16-bit
-; J signed 8-bit (C4x only)
-; K signed 5-bit (C4x only)
-; L unsigned 16-bit
-; M unsigned 8-bit (C4x only)
-; N ones complement of unsigned 16-bit
-; O 16 bit high constant
-; Q ARx + 9-bit signed disp
-; R ARx + 5-bit unsigned disp (C4x only)
-; S ARx + 0, 1, IRx disp
-; T symbol ref (direct)
-; V non offsettable memory
-; X any operand
-; < memory operand with autodecrement addressing
-; > memory operand with autoincrement addressing
-; { memory operand with pre-modify addressing
-; } memory operand with post-modify addressing
-
-; Note that the d, f, and h constraints are equivalent.
-; The m constraint is equivalent to QT<>{}
-
-; Note that the constraints are used to select the operands
-; for a chosen pattern. The constraint that requires the fewest
-; instructions to load an operand is chosen.
-
-; Note that the 'r' constraint is mostly only used for src integer register
-; operands, while 'c' and 'd' constraints are generally only used for dst
-; integer register operands (the 'r' constraint is the union of the 'c' and
-; 'd' constraints). When a register satisfying the 'd' constraint
-; is used as a dst operand, the CC gets clobbered (except for LDIcond)---but
-; not for 'c'.
-
-; The 'f' constraint is only for float register operands---when
-; a register satisying the 'f' constraint is used as a dst operand,
-; the CC gets clobbered (except for LDFcond).
-
-; The ! in front of the 'b' constaint says to GCC to disparage the
-; use of this constraint. The 'b' constraint applies only to the SP.
-
-; Note that we deal with the condition code CC like some of the RISC
-; architectures (arm, sh, sparc) where it is stored in a general register,
-; in this case the hard register ST (21). Unlike these other architectures
-; that do not set the CC with many instructions, the C[34]x architectures
-; sets the CC for many instructions when the destination register is
-; an extended precision register. While it would have been easier
-; to use the generic cc0 register to store the CC, as with most of
-; the other ported architectures, this constrains the setting and testing
-; of the CC to be consecutive insns. Thus we would reduce the benefit
-; of scheduling instructions to avoid pipeline conflicts and filling of
-; delayed branch slots.
-
-; Since the C[34]x has many instructions that set the CC, we pay the
-; price of having to explicity define which insns clobber the CC
-; (rather than using the macro NOTICE_UPDATE_CC).
-
-; Note that many patterns say that the CC is clobbered when in fact
-; that it may not be (depending on the destination register).
-; We have to cover ourselves if an extended precision register
-; is allocated to the destination register.
-; Unfortunately, it is not easy to tell GCC that the clobbering of CC
-; is register dependent. If we could tolerate the ST register being
-; copied about, then we could store the CC in a pseudo register and
-; use constructs such as (clobber (match_scratch:CC N "&y,X")) to
-; indicate that the 'y' class (ST register) is clobbered for the
-; first combination of operands, but not with the second.
-; I tried this approach for a while but reload got unhappy since I
-; didn't allow it to move the CC around.
-
-; Note that fundamental operations, such as moves, must not clobber the
-; CC. Thus movqi choses a move instruction that doesn't clobber the CC.
-; If GCC wants to combine a move with a compare, it is smart enough to
-; chose the move instruction that sets the CC.
-
-; Unfortunately, the C[34]x instruction set does not have arithmetic or
-; logical operations that never touch the CC. We thus have to assume
-; that the CC may be clobbered at all times. If we define patterns
-; such as addqi without the clobber of CC, then GCC will be forced
-; to use registers such as the auxiliary registers which can cause
-; horrible pipeline conflicts. The tradeoff is that GCC can't now
-; sneak in an add instruction between setting and testing of the CC.
-
-; Most of the C[34]x instructions require operands of the following formats,
-; where imm represents an immediate constant, dir a direct memory reference,
-; ind an indirect memory reference, and reg a register:
-
-; src2 (op2) src1 (op1) dst (op0)
-; imm dir ind reg | imm dir ind reg | reg Notes
-;---------------------+----------------------+------
-; ILH T Q<> r | - - - 0 | r 2 operand
-; - - S<> r | - - S<> r | r
-; J - R - | - - R r | r C4x
-
-; Arithmetic operations use the I, J constraints for immediate constants,
-; while logical operations use the L, J constraints. Floating point
-; operations use the H constraint for immediate constants.
-
-; With most instructions the src2 and src1 operands are commutative
-; (except for SUB, SUBR, ANDN). The assembler considers
-; ADDI 10, R0, R1 and ADDI R0, 10, R1 to be equivalent.
-; We thus match src2 and src1 with the src_operand predicate and
-; use valid_operands as the extra constraint to reject invalid
-; operand combinations. For example, ADDI @foo, @bar, R0.
-
-; Note that we use the ? modifier so that reload doesn't preferentially
-; try the alternative where three registers are acceptable as
-; operands (whenever an operand requires reloading). Instead it will try
-; the 2 operand form which will produce better code since it won't require
-; a new spill register.
-
-; Note that the floating point representation of 0.0 on the C4x
-; is 0x80000000 (-2147483648). This value produces an warning
-; message on 32-bit machines about the decimal constant being so large
-; that it is unsigned.
-
-; With two operand instructions patterns having two sets,
-; the compare set must come first to keep the combiner happy.
-; While the combiner seems to cope most of the time with the
-; compare set coming second, it's best to have it first.
-
-;
-; C4x CONSTANT attributes
-;
-(define_attr "cpu" "c4x,c3x"
- (const
- (cond [(symbol_ref "TARGET_C3X") (const_string "c3x")]
- (const_string "c4x"))))
-
-;
-; C4x INSN ATTRIBUTES:
-;
-; lda load address, non-clobber CC
-; store memory store, non-clobber CC
-; load_load parallel memory loads, non-clobber CC
-; load_store parallel memory load and store, non-clobber CC
-; store_load parallel memory store and load, non-clobber CC
-; store_store parallel memory stores, non-clobber CC
-; unary two operand arithmetic, non-clobber CC
-; unarycc two operand arithmetic, clobber CC
-; binary three operand arithmetic, non-clobber CC
-; binarycc three operand arithmetic, clobber CC
-; compare compare, clobber CC
-; call function call
-; rets return from subroutine
-; jump unconditional branch
-; jmpc conditional branch
-; db decrement and branch (unconditional)
-; dbc decrement and branch (conditional)
-; ldp load DP
-; push stack push
-; pop stack pop
-; repeat block repeat
-; repeat_top block repeat top
-; laj link and jump
-; multi multiple instruction
-; misc nop (default)
-
-; The only real instructions that affect things are the ones that modify
-; address registers and ones that call or jump. Note that the number
-; of operands refers to the RTL insn pattern, not the number of explicit
-; operands in the machine instruction.
-;
-(define_attr "type" "lda,store,unary,unarycc,binary,binarycc,compare,call,rets,jump,jmpc,db,dbc,misc,ldp,repeat,repeat_top,laj,load_load,load_store,store_load,store_store,push,pop,multi"
- (const_string "misc"))
-
-
-; Some instructions operate on unsigned data constants, some on signed data
-; constants, or the ones complement of unsigned constants.
-; This differentiates them. Default to signed. This attribute
-; is used by the macro SMALL_CONST () (defined in c4x.h) to determine
-; whether an immediate integer constant will fit within the instruction,
-; or will have to be loaded using direct addressing from memory.
-; Note that logical operations assume unsigned integers whereas
-; arithmetic operations assume signed integers. Note that the C4x
-; small immediate constant (J) used as src2 in three operand instructions
-; is always signed. not_uint16 refers to a number that fits into 16-bits
-; when one's complemented.
-;
-(define_attr "data" "int16,uint16,high_16,not_uint16" (const_string "int16"))
-
-(define_asm_attributes
- [(set_attr "type" "multi")])
-
-;
-; C4x DELAY SLOTS
-;
-; Define delay slot scheduling for branch and call instructions.
-; The C[34]x has three delay slots. Note that none of the three instructions
-; that follow a delayed branch can be a Bcond, BcondD, BR, BRD, DBcond,
-; DBcondD, CALL, CALLcond, TRAPcond, RETIcond, RETScond, RPTB, RPTS, or IDLE.
-;
-; Annulled branches are a bit difficult because the next instructions
-; are preprocessed.
-; The table below shows what phase of the c4x is executed.
-; BccA[TF] label
-; op1 fetch, decode and read executed
-; op2 fetch and decode executed
-; op3 fetch executed
-; This means that we can allow any instruction in the last delay slot
-; and only instructions which modify registers in the first two.
-; lda can not be executed in the first delay slot
-; and ldpk can not be executed in the first two delay slots.
-
-(define_attr "onlyreg" "false,true"
- (cond [(eq_attr "type" "unary,unarycc")
- (if_then_else (and (match_operand 0 "reg_imm_operand" "")
- (match_operand 1 "reg_imm_operand" ""))
- (const_string "true") (const_string "false"))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (and (match_operand 0 "reg_imm_operand" "")
- (and (match_operand 1 "reg_imm_operand" "")
- (match_operand 2 "reg_imm_operand" "")))
- (const_string "true") (const_string "false"))]
- (const_string "false")))
-
-(define_attr "onlyreg_nomod" "false,true"
- (cond [(eq_attr "type" "unary,unarycc,compare,lda,store")
- (if_then_else (and (match_operand 0 "not_modify_reg" "")
- (match_operand 1 "not_modify_reg" ""))
- (const_string "true") (const_string "false"))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (and (match_operand 0 "not_modify_reg" "")
- (and (match_operand 1 "not_modify_reg" "")
- (match_operand 2 "not_modify_reg" "")))
- (const_string "true") (const_string "false"))]
- (const_string "false")))
-
-(define_attr "not_repeat_reg" "false,true"
- (cond [(eq_attr "type" "unary,unarycc,compare,lda,store")
- (if_then_else (and (match_operand 0 "not_rc_reg" "")
- (match_operand 1 "not_rc_reg" ""))
- (const_string "true") (const_string "false"))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (and (match_operand 0 "not_rc_reg" "")
- (and (match_operand 1 "not_rc_reg" "")
- (match_operand 2 "not_rc_reg" "")))
- (const_string "true") (const_string "false"))]
- (const_string "false")))
-
-(define_attr "in_annul_slot_1" "false,true"
- (if_then_else (and (and (eq_attr "cpu" "c4x")
- (eq_attr "type" "!jump,call,rets,jmpc,compare,db,dbc,repeat,repeat_top,laj,push,pop,lda,ldp,multi"))
- (eq_attr "onlyreg" "true"))
- (const_string "true")
- (const_string "false")))
-
-(define_attr "in_annul_slot_2" "false,true"
- (if_then_else (and (and (eq_attr "cpu" "c4x")
- (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi"))
- (eq_attr "onlyreg_nomod" "true"))
- (const_string "true")
- (const_string "false")))
-
-(define_attr "in_annul_slot_3" "false,true"
- (if_then_else (and (eq_attr "cpu" "c4x")
- (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,db,dbc,repeat,repeat_top,laj,push,pop,multi"))
- (const_string "true")
- (const_string "false")))
-
-(define_attr "in_delay_slot" "false,true"
- (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi")
- (const_string "true")
- (const_string "false")))
-
-(define_attr "in_repeat_slot" "false,true"
- (if_then_else (and (eq_attr "cpu" "c4x")
- (and (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi")
- (eq_attr "not_repeat_reg" "true")))
- (const_string "true")
- (const_string "false")))
-
-(define_attr "in_dbc_slot" "false,true"
- (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,compare,db,dbc,repeat,repeat_top,laj,multi")
- (const_string "true")
- (const_string "false")))
-
-(define_delay (eq_attr "type" "jmpc")
- [(eq_attr "in_delay_slot" "true")
- (eq_attr "in_annul_slot_1" "true")
- (eq_attr "in_annul_slot_1" "true")
-
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_annul_slot_2" "true")
- (eq_attr "in_annul_slot_2" "true")
-
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_annul_slot_3" "true")
- (eq_attr "in_annul_slot_3" "true") ])
-
-
-(define_delay (eq_attr "type" "repeat_top")
- [(eq_attr "in_repeat_slot" "true") (nil) (nil)
- (eq_attr "in_repeat_slot" "true") (nil) (nil)
- (eq_attr "in_repeat_slot" "true") (nil) (nil)])
-
-(define_delay (eq_attr "type" "jump,db")
- [(eq_attr "in_delay_slot" "true") (nil) (nil)
- (eq_attr "in_delay_slot" "true") (nil) (nil)
- (eq_attr "in_delay_slot" "true") (nil) (nil)])
-
-
-; Decrement and branch conditional instructions cannot modify the
-; condition codes for the cycles in the delay slots.
-;
-(define_delay (eq_attr "type" "dbc")
- [(eq_attr "in_dbc_slot" "true") (nil) (nil)
- (eq_attr "in_dbc_slot" "true") (nil) (nil)
- (eq_attr "in_dbc_slot" "true") (nil) (nil)])
-
-; The LAJ instruction has three delay slots but the last slot is
-; used for pushing the return address. Thus we can only use two slots.
-;
-(define_delay (eq_attr "type" "laj")
- [(eq_attr "in_delay_slot" "true") (nil) (nil)
- (eq_attr "in_delay_slot" "true") (nil) (nil)])
-
-;
-; C4x UNSPEC NUMBERS
-;
-; 1 BU/BUD
-; 2 RPTS
-; 3 LSH
-; 4 cmphi
-; 5 RCPF
-; 6 RND
-; 7 repeat block filler
-; 8 loadhf_int
-; 9 storehf_int
-; 10 RSQRF
-
-
-;
-; C4x FUNCTIONAL UNITS
-;
-; Define functional units for instruction scheduling to minimise
-; pipeline conflicts.
-;
-; With the C3x, an external memory write (with no wait states) takes
-; two cycles and an external memory read (with no wait states) takes
-; one cycle. However, an external read following an external write
-; takes two cycles. With internal memory, reads and writes take
-; half a cycle.
-;
-; When a C4x address register is loaded it will not be available for
-; an extra machine cycle. Calculating with a C4x address register
-; makes it unavailable for 2 machine cycles. To notify GCC of these
-; pipeline delays, each of the auxiliary and index registers are declared
-; as separate functional units.
-;
-; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
-; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
-;
-; MULTIPLICITY 1 (C4x has no independent identical function units)
-; SIMULTANEITY 0 (C4x is pipelined)
-; READY_DELAY 1 (Results usually ready after every cyle)
-; ISSUE_DELAY 1 (Can issue insns every cycle)
-
-; Just some dummy definitions. The real work is done in c4x_adjust_cost.
-; These are needed so the min/max READY_DELAY is known.
-
-(define_function_unit "dummy" 1 0 (const_int 0) 1 1)
-(define_function_unit "dummy" 1 0 (const_int 0) 2 1)
-(define_function_unit "dummy" 1 0 (const_int 0) 3 1)
-
-;(define_function_unit "ar0" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar0" "1")
-; (eq_attr "usear0" "1")))
-; 3 1 )
-
-;(define_function_unit "ar0" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar0" "1")
-; (eq_attr "usear0" "1")))
-; 2 1 )
-
-;(define_function_unit "ar0" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear0" "1")
-; (eq_attr "readar0" "1")))
-; 2 1 )
-
-; The attribute setar0 is set to 1 for insns where ar0 is a dst operand.
-; Note that the attributes unarycc and binarycc do not apply
-; if ar0 is a dst operand (only loading an ext. prec. reg. sets CC)
-(define_attr "setar0" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar0" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-; The attribute usear0 is set to 1 for insns where ar0 is used
-; for addressing, as a src operand, or as a dst operand.
-(define_attr "usear0" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar0_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar0_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar0_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-; The attribute readar0 is set to 1 for insns where ar0 is a src operand.
-(define_attr "readar0" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar1" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar1" "1")
-; (eq_attr "usear1" "1")))
-; 3 1 )
-
-;(define_function_unit "ar1" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar1" "1")
-; (eq_attr "usear1" "1")))
-; 2 1 )
-
-;(define_function_unit "ar1" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear1" "1")
-; (eq_attr "readar1" "1")))
-; 2 1 )
-
-(define_attr "setar1" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar1" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear1" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar1" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar2" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar2" "1")
-; (eq_attr "usear2" "1")))
-; 3 1 )
-
-;(define_function_unit "ar2" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar2" "1")
-; (eq_attr "usear2" "1")))
-; 2 1 )
-
-;(define_function_unit "ar2" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear2" "1")
-; (eq_attr "readar2" "1")))
-; 2 1 )
-
-(define_attr "setar2" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar2" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear2" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar2_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar2_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar2_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar2" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar2_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar3" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar3" "1")
-; (eq_attr "usear3" "1")))
-; 3 1 )
-
-;(define_function_unit "ar3" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar3" "1")
-; (eq_attr "usear3" "1")))
-; 2 1 )
-
-;(define_function_unit "ar3" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear3" "1")
-; (eq_attr "readar3" "1")))
-; 2 1 )
-
-(define_attr "setar3" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar3" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear3" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar3_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar3_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar3_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar3" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar3_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar4" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar4" "1")
-; (eq_attr "usear4" "1")))
-; 3 1 )
-
-;(define_function_unit "ar4" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar4" "1")
-; (eq_attr "usear4" "1")))
-; 2 1 )
-
-;(define_function_unit "ar4" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear4" "1")
-; (eq_attr "readar4" "1")))
-; 2 1 )
-
-(define_attr "setar4" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar4" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear4" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar4_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar4_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar4_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar4" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar4_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar5" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar5" "1")
-; (eq_attr "usear5" "1")))
-; 3 1 )
-
-;(define_function_unit "ar5" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar5" "1")
-; (eq_attr "usear5" "1")))
-; 2 1 )
-
-;(define_function_unit "ar5" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear5" "1")
-; (eq_attr "readar5" "1")))
-; 2 1 )
-
-(define_attr "setar5" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar5" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear5" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar5_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar5_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar5_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar5" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar5_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar6" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar6" "1")
-; (eq_attr "usear6" "1")))
-; 3 1 )
-
-;(define_function_unit "ar6" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar6" "1")
-; (eq_attr "usear6" "1")))
-; 2 1 )
-
-;(define_function_unit "ar6" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear6" "1")
-; (eq_attr "readar6" "1")))
-; 2 1 )
-
-(define_attr "setar6" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar6" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear6" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar6_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar6_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar6_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar6" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar6_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ar7" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setar7" "1")
-; (eq_attr "usear7" "1")))
-; 3 1 )
-
-;(define_function_unit "ar7" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ar7" "1")
-; (eq_attr "usear7" "1")))
-; 2 1 )
-
-;(define_function_unit "ar7" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "usear7" "1")
-; (eq_attr "readar7" "1")))
-; 2 1 )
-
-(define_attr "setar7" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ar7" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usear7" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ar7_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar7_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar7_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "db,dbc")
- (if_then_else (match_operand 0 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readar7" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ar7_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ir0" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setir0" "1")
-; (eq_attr "useir0" "1")))
-; 3 1 )
-
-;(define_function_unit "ir0" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ir0" "1")
-; (eq_attr "useir0" "1")))
-; 2 1 )
-
-(define_attr "setir0" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ir0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ir0" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ir0_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "useir0" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ir0_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ir0_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ir0_mem_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-;(define_function_unit "ir1" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setir1" "1")
-; (eq_attr "useir1" "1")))
-; 3 1 )
-
-;(define_function_unit "ir1" 1 0
-; (and (eq_attr "cpu" "c4x")
-; (and (eq_attr "setlda_ir1" "1")
-; (eq_attr "useir1" "1")))
-; 2 1 )
-
-(define_attr "setir1" ""
- (cond [(eq_attr "type" "unary,binary")
- (if_then_else (match_operand 0 "ir1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "setlda_ir1" ""
- (cond [(eq_attr "type" "lda")
- (if_then_else (match_operand 0 "ir1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "useir1" ""
- (cond [(eq_attr "type" "compare,store")
- (if_then_else (match_operand 0 "ir1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "ir1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "ir1_mem_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-; With the C3x, things are simpler, but slower, i.e. more pipeline conflicts :(
-; There are three functional groups:
-; (1) AR0-AR7, IR0-IR1, BK
-; (2) DP
-; (3) SP
-;
-; When a register in one of these functional groups is loaded,
-; the contents of that or any other register in its group
-; will not be available to the next instruction for 2 machine cycles.
-; Similarly, when a register in one of the functional groups is read
-; excepting (IR0-IR1, BK, DP) the contents of that or any other register
-; in its group will not be available to the next instruction for
-; 1 machine cycle.
-;
-; Let's ignore functional groups 2 and 3 for now, since they are not
-; so important.
-
-;(define_function_unit "group1" 1 0
-; (and (eq_attr "cpu" "c3x")
-; (and (eq_attr "setgroup1" "1")
-; (eq_attr "usegroup1" "1")))
-; 3 1)
-
-;(define_function_unit "group1" 1 0
-; (and (eq_attr "cpu" "c3x")
-; (and (eq_attr "usegroup1" "1")
-; (eq_attr "readarx" "1")))
-; 2 1)
-
-(define_attr "setgroup1" ""
- (cond [(eq_attr "type" "lda,unary,binary")
- (if_then_else (match_operand 0 "group1_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "usegroup1" ""
- (cond [(eq_attr "type" "compare,store,store_store,store_load")
- (if_then_else (match_operand 0 "group1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc,load_load,load_store")
- (if_then_else (match_operand 1 "group1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "store_store,load_store")
- (if_then_else (match_operand 2 "group1_mem_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "load_load,store_load")
- (if_then_else (match_operand 3 "group1_mem_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-(define_attr "readarx" ""
- (cond [(eq_attr "type" "compare")
- (if_then_else (match_operand 0 "arx_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")
- (if_then_else (match_operand 1 "arx_reg_operand" "")
- (const_int 1) (const_int 0))
- (eq_attr "type" "binary,binarycc")
- (if_then_else (match_operand 2 "arx_reg_operand" "")
- (const_int 1) (const_int 0))]
- (const_int 0)))
-
-
-;
-; C4x INSN PATTERNS:
-;
-; Note that the movMM and addP patterns can be called during reload
-; so we need to take special care with theses patterns since
-; we cannot blindly clobber CC or generate new pseudo registers.
-
-;
-; TWO OPERAND INTEGER INSTRUCTIONS
-;
-
-;
-; LDP/LDPK
-;
-(define_insn "set_ldp"
- [(set (match_operand:QI 0 "dp_reg_operand" "=z")
- (high:QI (match_operand:QI 1 "" "")))]
- "! TARGET_SMALL"
- "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"
- [(set_attr "type" "ldp")])
-
-
-; Used when moving a constant label reference to an external
-; location, this will make sure the original label is still
-; used so the optimizer will not optimize it away.
-;
-(define_insn "set_ldp_use"
- [(parallel [(set (match_operand:QI 0 "dp_reg_operand" "=z")
- (high:QI (match_operand:QI 1 "" "")))
- (use (match_operand 2 "" ""))])]
- "! TARGET_SMALL"
- "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"
- [(set_attr "type" "ldp")])
-
-(define_insn "set_high_use"
- [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c")
- (high:QI (match_operand:QI 1 "" "")))
- (use (match_operand 2 "" ""))])]
- "! TARGET_C3X && ! TARGET_SMALL"
- "ldhi\\t^%H1,%0"
- [(set_attr "type" "unary")])
-
-(define_insn "set_ior_lo_use"
- [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c")
- (ior:QI (match_dup 0)
- (and:QI (match_operand:QI 1 "" "")
- (const_int 65535))))
- (use (match_operand 2 "" ""))])]
- "! TARGET_C3X && ! TARGET_SMALL"
- "or\\t#%H1,%0"
- [(set_attr "type" "unary")])
-
-;
-; LDIU/LDA/STI/STIK
-;
-; The following moves will not set the condition codes register.
-;
-
-; This must come before the general case
-(define_insn "*movqi_stik"
- [(set (match_operand:QI 0 "memory_operand" "=m")
- (match_operand:QI 1 "stik_const_operand" "K"))]
- "! TARGET_C3X"
- "stik\\t%1,%0"
- [(set_attr "type" "store")])
-
-; We must provide an alternative to store to memory in case we have to
-; spill a register.
-(define_insn "movqi_noclobber"
- [(set (match_operand:QI 0 "src_operand" "=d,*c,m,r")
- (match_operand:QI 1 "src_hi_operand" "rmI,rmI,r,O"))]
- "reg_operand (operands[0], QImode)
- || reg_operand (operands[1], QImode)"
- "*
- if (which_alternative == 2)
- return \"sti\\t%1,%0\";
-
- if (! TARGET_C3X && which_alternative == 3)
- {
- operands[1] = GEN_INT ((INTVAL (operands[1]) >> 16) & 0xffff);
- return \"ldhi\\t%1,%0\";
- }
-
- /* The lda instruction cannot use the same register as source
- and destination. */
- if (! TARGET_C3X && which_alternative == 1
- && ( IS_ADDR_REG (REGNO (operands[0]))
- || IS_INDEX_REG (REGNO (operands[0]))
- || IS_SP_REG (REGNO (operands[0])))
- && (REGNO (operands[0]) != REGNO (operands[1])))
- return \"lda\\t%1,%0\";
- return \"ldiu\\t%1,%0\";
- "
- [(set_attr "type" "unary,lda,store,unary")
- (set_attr "data" "int16,int16,int16,high_16")])
-
-;
-; LDI
-;
-
-; We shouldn't need these peepholes, but the combiner seems to miss them...
-(define_peephole
- [(set (match_operand:QI 0 "ext_reg_operand" "=d")
- (match_operand:QI 1 "src_operand" "g"))
- (set (reg:CC 21)
- (compare:CC (match_dup 0) (const_int 0)))]
- ""
- "@
- ldi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-(define_insn "*movqi_set"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QI 1 "src_operand" "g")
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d")
- (match_dup 1))]
- ""
- "@
- ldi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-; This pattern probably gets in the way and requires a scratch register
-; when a simple compare with zero will suffice.
-;(define_insn "*movqi_test"
-; [(set (reg:CC 21)
-; (compare:CC (match_operand:QI 1 "src_operand" "g")
-; (const_int 0)))
-; (clobber (match_scratch:QI 0 "=d"))]
-; ""
-; "@
-; ldi\\t%1,%0"
-; [(set_attr "type" "unarycc")
-; (set_attr "data" "int16")])
-
-; If one of the operands is not a register, then we should
-; emit two insns, using a scratch register. This will produce
-; better code in loops if the source operand is invariant, since
-; the source reload can be optimised out. During reload we cannot
-; use change_address or force_reg which will allocate new pseudo regs.
-
-; Unlike most other insns, the move insns can't be split with
-; different predicates, because register spilling and other parts of
-; the compiler, have memoized the insn number already.
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "src_operand" "")
- (match_operand:QI 1 "src_operand" ""))]
- ""
- "
- /* We shouldn't have to do this, since reload is supposed to
- be able to do this if we have a memory constraint. */
- if (CONSTANT_P (operands[1])
- && ! const_operand (operands[1], QImode))
- {
- operands[1] = force_const_mem (QImode, operands[1]);
- if (! memory_address_p (QImode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], QImode,
- XEXP (operands[1], 0));
- }
-
- if (! reload_in_progress
- && ! reg_operand (operands[0], QImode)
- && ! reg_operand (operands[1], QImode)
- && ! (stik_const_operand (operands[1], QImode)
- && ! push_operand (operands[0], QImode)))
- operands[1] = force_reg (QImode, operands[1]);")
-
-(define_insn "*movqi_update"
- [(set (match_operand:QI 0 "reg_operand" "=r")
- (mem:QI (plus:QI (match_operand:QI 1 "addr_reg_operand" "a")
- (match_operand:QI 2 "index_reg_operand" "x"))))
- (set (match_dup 1)
- (plus:QI (match_dup 1) (match_dup 2)))]
- ""
- "ldiu\\t*%1++(%2),%0"
- [(set_attr "type" "unary")
- (set_attr "data" "int16")])
-
-(define_insn "movqi_parallel"
- [(set (match_operand:QI 0 "parallel_operand" "=q,S<>,q,S<>")
- (match_operand:QI 1 "parallel_operand" "S<>,q,S<>,q"))
- (set (match_operand:QI 2 "parallel_operand" "=q,S<>,S<>,q")
- (match_operand:QI 3 "parallel_operand" "S<>,q,q,S<>"))]
- "valid_parallel_load_store (operands, QImode)"
- "@
- ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2
- sti1\\t%1,%0\\n||\\tsti2\\t%3,%2
- ldi\\t%1,%0\\n||\\tsti\\t%3,%2
- ldi\\t%3,%2\\n||\\tsti\\t%1,%0"
- [(set_attr "type" "load_load,store_store,load_store,store_load")])
-
-;
-; PUSH/POP
-;
-(define_insn "*pushqi"
- [(set (mem:QI (pre_inc:QI (reg:QI 20)))
- (match_operand:QI 0 "reg_operand" "r"))]
- ""
- "push\\t%0"
- [(set_attr "type" "push")])
-
-(define_insn "*popqi"
- [(set (match_operand:QI 0 "reg_operand" "=r")
- (mem:QI (post_dec:QI (reg:QI 20))))
- (clobber (reg:CC 21))]
- ""
- "pop\\t%0"
- [(set_attr "type" "pop")])
-
-;
-; ABSI
-;
-(define_expand "absqi2"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (abs:QI (match_operand:QI 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "")
-
-(define_insn "*absqi2_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (abs:QI (match_operand:QI 1 "src_operand" "g,g")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "absi\\t%1,%0"
- [(set_attr "type" "unarycc,unary")
- (set_attr "data" "int16,int16")])
-
-(define_insn "*absqi2_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d"))]
- ""
- "absi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-(define_insn "*absqi2_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d")
- (abs:QI (match_dup 1)))]
- ""
- "absi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-;
-; NEGI
-;
-(define_expand "negqi2"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (neg:QI (match_operand:QI 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
-""
-"")
-
-(define_insn "*negqi2_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (neg:QI (match_operand:QI 1 "src_operand" "g,g")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "negi\\t%1,%0"
- [(set_attr "type" "unarycc,unary")
- (set_attr "data" "int16,int16")])
-
-(define_insn "*negqi2_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d"))]
- ""
- "negi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-(define_insn "*negqi2_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d")
- (neg:QI (match_dup 1)))]
- ""
- "negi\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-(define_insn "*negbqi2_clobber"
- [(set (match_operand:QI 0 "ext_reg_operand" "=d")
- (neg:QI (match_operand:QI 1 "src_operand" "g")))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))]
- ""
- "negb\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "int16")])
-
-;
-; NOT
-;
-(define_expand "one_cmplqi2"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (not:QI (match_operand:QI 1 "lsrc_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "")
-
-(define_insn "*one_cmplqi2_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (not:QI (match_operand:QI 1 "lsrc_operand" "g,g")))
- (clobber (reg:CC 21))]
- ""
- "not\\t%1,%0"
- [(set_attr "type" "unarycc,unary")
- (set_attr "data" "uint16,uint16")])
-
-(define_insn "*one_cmplqi2_test"
- [(set (reg:CC 21)
- (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d"))]
- ""
- "not\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "uint16")])
-
-(define_insn "*one_cmplqi2_set"
- [(set (reg:CC 21)
- (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d")
- (not:QI (match_dup 1)))]
- ""
- "not\\t%1,%0"
- [(set_attr "type" "unarycc")
- (set_attr "data" "uint16")])
-
-(define_insn "*one_cmplqi2_const_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (match_operand:QI 1 "not_const_operand" "N,N"))
- (clobber (reg:CC 21))]
- ""
- "@
- not\\t%N1,%0
- not\\t%N1,%0"
- [(set_attr "type" "unarycc,unary")
- (set_attr "data" "not_uint16,not_uint16")])
-
-; movqi can use this for loading an integer that can't normally
-; fit into a 16-bit signed integer. The drawback is that it cannot
-; go into R0-R11 since that will clobber the CC and movqi shouldn't
-; do that. This can cause additional reloading but in most cases
-; this will cause only an additional register move. With the large
-; memory model we require an extra instruction to load DP anyway,
-; if we're loading the constant from memory. The big advantage of
-; allowing constants that satisfy not_const_operand in movqi, is that
-; it allows andn to be generated more often.
-; However, there is a problem if GCC has decided that it wants
-; to use R0-R11, since we won't have a matching pattern...
-; In interim, we prevent immed_const allowing `N' constants.
-(define_insn "*one_cmplqi2_const_noclobber"
- [(set (match_operand:QI 0 "std_reg_operand" "=c")
- (match_operand:QI 1 "not_const_operand" "N"))]
- ""
- "not\\t%N1,%0"
- [(set_attr "type" "unary")
- (set_attr "data" "not_uint16")])
-
-;
-; ROL
-;
-(define_expand "rotlqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (rotate:QI (match_operand:QI 1 "reg_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (INTVAL (operands[2]) > 4)
- FAIL; /* Open code as two shifts and an or */
- if (INTVAL (operands[2]) > 1)
- {
- int i;
- rtx tmp;
-
- /* If we have 4 or fewer shifts, then it is probably faster
- to emit separate ROL instructions. A C3x requires
- at least 4 instructions (a C4x requires at least 3), to
- perform a rotation by shifts. */
-
- tmp = operands[1];
- for (i = 0; i < INTVAL (operands[2]) - 1; i++)
- {
- tmp = gen_reg_rtx (QImode);
- emit_insn (gen_rotl_1_clobber (tmp, operands[1]));
- operands[1] = tmp;
- }
- emit_insn (gen_rotl_1_clobber (operands[0], tmp));
- DONE;
- }")
-
-(define_insn "rotl_1_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (rotate:QI (match_operand:QI 1 "reg_operand" "0,0")
- (const_int 1)))
- (clobber (reg:CC 21))]
- ""
- "rol\\t%0"
- [(set_attr "type" "unarycc,unary")])
-; Default to int16 data attr.
-
-;
-; ROR
-;
-(define_expand "rotrqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (rotatert:QI (match_operand:QI 1 "reg_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (INTVAL (operands[2]) > 4)
- FAIL; /* Open code as two shifts and an or */
- if (INTVAL (operands[2]) > 1)
- {
- int i;
- rtx tmp;
-
- /* If we have 4 or fewer shifts, then it is probably faster
- to emit separate ROL instructions. A C3x requires
- at least 4 instructions (a C4x requires at least 3), to
- perform a rotation by shifts. */
-
- tmp = operands[1];
- for (i = 0; i < INTVAL (operands[2]) - 1; i++)
- {
- tmp = gen_reg_rtx (QImode);
- emit_insn (gen_rotr_1_clobber (tmp, operands[1]));
- operands[1] = tmp;
- }
- emit_insn (gen_rotr_1_clobber (operands[0], tmp));
- DONE;
- }")
-
-(define_insn "rotr_1_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (rotatert:QI (match_operand:QI 1 "reg_operand" "0,0")
- (const_int 1)))
- (clobber (reg:CC 21))]
- ""
- "ror\\t%0"
- [(set_attr "type" "unarycc,unary")])
-; Default to int16 data attr.
-
-
-;
-; THREE OPERAND INTEGER INSTRUCTIONS
-;
-
-;
-; ADDI
-;
-; This is used by reload when it calls gen_add2_insn for address arithmetic
-; so we must emit the pattern that doesn't clobber CC.
-;
-(define_expand "addqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (plus:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (PLUS, operands, QImode);
- if (reload_in_progress
- || (! IS_PSEUDO_REGNO (operands[0])
- && ! IS_EXT_REG (REGNO (operands[0]))))
- {
- emit_insn (gen_addqi3_noclobber (operands[0], operands[1], operands[2]));
- DONE;
- }")
-
-(define_insn "*addqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-(define_insn "*addqi3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-; gcc does this in combine.c we just reverse it here
-(define_insn "*cmp_neg"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (neg: QI (match_operand:QI 2 "src_operand" "JR,rS<>,g"))))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g")))
- (clobber (reg:CC_NOOV 21))])
- (set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_dup 0) (const_int 0)))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_insn "*addqi3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (plus:QI (match_dup 1) (match_dup 2)))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-; This pattern is required primarily for manipulating the stack pointer
-; where GCC doesn't expect CC to be clobbered or for calculating
-; addresses during reload.
-(define_insn "addqi3_noclobber"
- [(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c")
- (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g")))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binary,binary,binary")])
-; Default to int16 data attr.
-
-
-; This pattern is required during reload when eliminate_regs_in_insn
-; effectively converts a move insn into an add insn when the src
-; operand is the frame pointer plus a constant. Without this
-; pattern, gen_addqi3 can be called with a register for operand0
-; that can clobber CC.
-; For example, we may have (set (mem (reg ar0)) (reg 99))
-; with (set (reg 99) (plus (reg ar3) (const_int 8)))
-; Now since ar3, the frame pointer, is unchanging within the function,
-; (plus (reg ar3) (const_int 8)) is considered a constant.
-; eliminate_regs_in_insn substitutes this constant to give
-; (set (mem (reg ar0)) (plus (reg ar3) (const_int 8))).
-; This is an invalid C4x insn but if we don't provide a pattern
-; for it, it will be considered to be a move insn for reloading.
-; The nasty bit is that a GENERAL_REGS class register, say r0,
-; may be allocated to reload the PLUS and thus gen_reload will
-; emit an add insn that may clobber CC.
-(define_insn "*addqi3_noclobber_reload"
- [(set (match_operand:QI 0 "general_operand" "=c,?c,c")
- (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g")))]
- "reload_in_progress"
- "@
- addi3\\t%2,%1,%0
- addi3\\t%2,%1,%0
- addi\\t%2,%0"
- [(set_attr "type" "binary,binary,binary")])
-; Default to int16 data attr.
-
-
-(define_insn "*addqi3_carry_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (PLUS, operands, QImode)"
- "@
- addc3\\t%2,%1,%0
- addc3\\t%2,%1,%0
- addc\\t%2,%0
- addc3\\t%2,%1,%0
- addc3\\t%2,%1,%0
- addc\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-
-;
-; SUBI/SUBRI
-;
-(define_expand "subqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (minus:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MINUS, operands, QImode);")
-
-(define_insn "*subqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subi3\\t%2,%1,%0
- subi3\\t%2,%1,%0
- subi\\t%2,%0
- subri\\t%1,%0
- subi3\\t%2,%1,%0
- subi3\\t%2,%1,%0
- subi\\t%2,%0
- subri\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")])
-; Default to int16 data attr.
-
-(define_insn "*subqi3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d,d"))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subi3\\t%2,%1,%0
- subi3\\t%2,%1,%0
- subi\\t%2,%0
- subri\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")))
- (clobber (reg:CC_NOOV 21))])
- (set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_dup 0) (const_int 0)))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subi3\\t%2,%1,%0
- subi3\\t%2,%1,%0
- subi\\t%2,%0
- subri\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-(define_insn "*subqi3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (minus:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subi3\\t%2,%1,%0
- subi3\\t%2,%1,%0
- subi\\t%2,%0
- subri\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-(define_insn "*subqi3_carry_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0")))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subb3\\t%2,%1,%0
- subb3\\t%2,%1,%0
- subb\\t%2,%0
- subrb\\t%1,%0
- subb3\\t%2,%1,%0
- subb3\\t%2,%1,%0
- subb\\t%2,%0
- subrb\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")])
-; Default to int16 data attr.
-
-(define_insn "*subqi3_carry_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (minus:QI (match_dup 1)
- (match_dup 2)))
- (use (reg:CC_NOOV 21))]
- "valid_operands (MINUS, operands, QImode)"
- "@
- subb3\\t%2,%1,%0
- subb3\\t%2,%1,%0
- subb\\t%2,%0
- subrb\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-;
-; MPYI
-;
-(define_expand "mulqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (mult:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "if (TARGET_MPYI || (GET_CODE (operands[2]) == CONST_INT
- && exact_log2 (INTVAL (operands[2])) >= 0))
- legitimize_operands (MULT, operands, QImode);
- else
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- /* Let GCC try to synthesise the multiplication using shifts
- and adds. In most cases this will be more profitable than
- using the C3x MPYI. */
- FAIL;
- }
- if (operands[1] == operands[2])
- {
- /* Do the squaring operation in-line. */
- emit_insn (gen_sqrqi2_inline (operands[0], operands[1]));
- DONE;
- }
- if (TARGET_INLINE)
- {
- emit_insn (gen_mulqi3_inline (operands[0], operands[1],
- operands[2]));
- DONE;
- }
- c4x_emit_libcall3 (MULQI3_LIBCALL, MULT, QImode, operands);
- DONE;
- }
- ")
-
-(define_insn "*mulqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MULT, operands, QImode)"
- "*
- if (which_alternative == 2 || which_alternative == 5)
- {
- if (TARGET_C3X
- && GET_CODE (operands[2]) == CONST_INT
- && exact_log2 (INTVAL (operands[2])) >= 0)
- return \"ash\\t%L2,%0\";
- else
- return \"mpyi\\t%2,%0\";
- }
- else
- return \"mpyi3\\t%2,%1,%0\";"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-(define_insn "*mulqi3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (MULT, operands, QImode)"
- "*
- if (which_alternative == 2)
- {
- if (TARGET_C3X
- && GET_CODE (operands[2]) == CONST_INT
- && exact_log2 (INTVAL (operands[2])) >= 0)
- return \"ash\\t%L2,%0\";
- else
- return \"mpyi\\t%2,%0\";
- }
- else
- return \"mpyi3\\t%2,%1,%0\";"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-(define_insn "*mulqi3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (mult:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (MULT, operands, QImode)"
- "*
- if (which_alternative == 2)
- {
- if (TARGET_C3X
- && GET_CODE (operands[2]) == CONST_INT
- && exact_log2 (INTVAL (operands[2])) >= 0)
- return \"ash\\t%L2,%0\";
- else
- return \"mpyi\\t%2,%0\";
- }
- else
- return \"mpyi3\\t%2,%1,%0\";"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-; The C3x multiply instruction assumes 24-bit signed integer operands
-; and the 48-bit result is truncated to 32-bits.
-(define_insn "*mulqi3_24_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (mult:QI
- (sign_extend:QI
- (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (const_int 16777215)))
- (sign_extend:QI
- (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))]
- "TARGET_C3X && valid_operands (MULT, operands, QImode)"
- "@
- mpyi3\\t%2,%1,%0
- mpyi3\\t%2,%1,%0
- mpyi\\t%2,%0
- mpyi3\\t%2,%1,%0
- mpyi3\\t%2,%1,%0
- mpyi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-
-; Fast square function for C3x where TARGET_MPYI not asserted
-(define_expand "sqrqi2_inline"
- [(set (match_dup 7) (match_operand:QI 1 "src_operand" ""))
- (parallel [(set (match_dup 3)
- (lshiftrt:QI (match_dup 7) (const_int 16)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 2)
- (and:QI (match_dup 7) (const_int 65535)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 4)
- (mult:QI (sign_extend:QI (and:QI (match_dup 2)
- (const_int 16777215)))
- (sign_extend:QI (and:QI (match_dup 2)
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 5)
- (mult:QI (sign_extend:QI (and:QI (match_dup 2)
- (const_int 16777215)))
- (sign_extend:QI (and:QI (match_dup 3)
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 6)
- (ashift:QI (match_dup 5) (const_int 17)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_operand:QI 0 "reg_operand" "")
- (plus:QI (match_dup 4) (match_dup 6)))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "
- operands[2] = gen_reg_rtx (QImode); /* a = val & 0xffff */
- operands[3] = gen_reg_rtx (QImode); /* b = val >> 16 */
- operands[4] = gen_reg_rtx (QImode); /* a * a */
- operands[5] = gen_reg_rtx (QImode); /* a * b */
- operands[6] = gen_reg_rtx (QImode); /* (a * b) << 17 */
- operands[7] = gen_reg_rtx (QImode); /* val */
- ")
-
-; Inlined integer multiply for C3x
-(define_expand "mulqi3_inline"
- [(set (match_dup 12) (const_int -16))
- (set (match_dup 13) (match_operand:QI 1 "src_operand" ""))
- (set (match_dup 14) (match_operand:QI 2 "src_operand" ""))
- (parallel [(set (match_dup 4)
- (lshiftrt:QI (match_dup 13) (neg:QI (match_dup 12))))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 6)
- (lshiftrt:QI (match_dup 14) (neg:QI (match_dup 12))))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 3)
- (and:QI (match_dup 13)
- (const_int 65535)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 5)
- (and:QI (match_dup 14)
- (const_int 65535)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 7)
- (mult:QI (sign_extend:QI (and:QI (match_dup 4)
- (const_int 16777215)))
- (sign_extend:QI (and:QI (match_dup 5)
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 8)
- (mult:QI (sign_extend:QI (and:QI (match_dup 3)
- (const_int 16777215)))
- (sign_extend:QI (and:QI (match_dup 5)
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 9)
- (mult:QI (sign_extend:QI (and:QI (match_dup 3)
- (const_int 16777215)))
- (sign_extend:QI (and:QI (match_dup 6)
- (const_int 16777215)))))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 10)
- (plus:QI (match_dup 7) (match_dup 9)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 11)
- (ashift:QI (match_dup 10) (const_int 16)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_operand:QI 0 "reg_operand" "")
- (plus:QI (match_dup 8) (match_dup 11)))
- (clobber (reg:CC_NOOV 21))])]
- "TARGET_C3X"
- "
- operands[3] = gen_reg_rtx (QImode); /* a = arg1 & 0xffff */
- operands[4] = gen_reg_rtx (QImode); /* b = arg1 >> 16 */
- operands[5] = gen_reg_rtx (QImode); /* a = arg2 & 0xffff */
- operands[6] = gen_reg_rtx (QImode); /* b = arg2 >> 16 */
- operands[7] = gen_reg_rtx (QImode); /* b * c */
- operands[8] = gen_reg_rtx (QImode); /* a * c */
- operands[9] = gen_reg_rtx (QImode); /* a * d */
- operands[10] = gen_reg_rtx (QImode); /* b * c + a * d */
- operands[11] = gen_reg_rtx (QImode); /* (b *c + a * d) << 16 */
- operands[12] = gen_reg_rtx (QImode); /* -16 */
- operands[13] = gen_reg_rtx (QImode); /* arg1 */
- operands[14] = gen_reg_rtx (QImode); /* arg2 */
- ")
-
-;
-; MPYSHI (C4x only)
-;
-(define_expand "smulqi3_highpart"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (truncate:QI
- (lshiftrt:HI
- (mult:HI
- (sign_extend:HI (match_operand:QI 1 "src_operand" ""))
- (sign_extend:HI (match_operand:QI 2 "src_operand" "")))
- (const_int 32))))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MULT, operands, QImode);
- if (TARGET_C3X)
- {
- c4x_emit_libcall_mulhi (SMULHI3_LIBCALL, SIGN_EXTEND, QImode, operands);
- DONE;
- }
- ")
-
-(define_insn "*smulqi3_highpart_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (truncate:QI
- (lshiftrt:HI
- (mult:HI
- (sign_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0"))
- (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
- (const_int 32))))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X && valid_operands (MULT, operands, QImode)"
- "@
- mpyshi3\\t%2,%1,%0
- mpyshi3\\t%2,%1,%0
- mpyshi\\t%2,%0
- mpyshi3\\t%2,%1,%0
- mpyshi3\\t%2,%1,%0
- mpyshi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")
- (set_attr "data" "int16,int16,int16,int16,int16,int16")])
-
-;
-; MPYUHI (C4x only)
-;
-(define_expand "umulqi3_highpart"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (truncate:QI
- (lshiftrt:HI
- (mult:HI
- (zero_extend:HI (match_operand:QI 1 "src_operand" ""))
- (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "")))
- (const_int 32))))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MULT, operands, QImode);
- if (TARGET_C3X)
- {
- c4x_emit_libcall_mulhi (UMULHI3_LIBCALL, ZERO_EXTEND, QImode, operands);
- DONE;
- }
- ")
-
-(define_insn "*umulqi3_highpart_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (truncate:QI
- (lshiftrt:HI
- (mult:HI
- (zero_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0"))
- (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,g,JR,rS<>,g")))
- (const_int 32))))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X && valid_operands (MULT, operands, QImode)"
- "@
- mpyuhi3\\t%2,%1,%0
- mpyuhi3\\t%2,%1,%0
- mpyuhi\\t%2,%0
- mpyuhi3\\t%2,%1,%0
- mpyuhi3\\t%2,%1,%0
- mpyuhi\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")
- (set_attr "data" "uint16,uint16,uint16,uint16,uint16,uint16")])
-
-;
-; AND
-;
-(define_expand "andqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (and:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "tsrc_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (AND, operands, QImode);")
-
-(define_insn "*andqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c")
- (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0,rR,rS<>,0,0")
- (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm,JR,rS<>,N,rLm")))
- (clobber (reg:CC 21))]
- "valid_operands (AND, operands, QImode)"
- "@
- and3\\t%2,%1,%0
- and3\\t%2,%1,%0
- andn\\t%N2,%0
- and\\t%2,%0
- and3\\t%2,%1,%0
- and3\\t%2,%1,%0
- andn\\t%N2,%0
- and\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")
- (set_attr "data" "int16,uint16,not_uint16,uint16,int16,uint16,not_uint16,uint16")])
-
-(define_insn "*andqi3_test"
- [(set (reg:CC 21)
- (compare:CC (and:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,r")
- (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=X,X,d,X"))]
- "valid_operands (AND, operands, QImode)"
- "@
- tstb3\\t%2,%1
- tstb3\\t%2,%1
- andn\\t%N2,%0
- tstb\\t%2,%1"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,not_uint16,uint16")])
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0")
- (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm")))
- (clobber (reg:CC 21))])
- (set (reg:CC 21)
- (compare:CC (match_dup 0) (const_int 0)))]
- "valid_operands (AND, operands, QImode)"
- "@
- and3\\t%2,%1,%0
- and3\\t%2,%1,%0
- andn\\t%N2,%0
- and\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,not_uint16,uint16")])
-
-(define_insn "*andqi3_set"
- [(set (reg:CC 21)
- (compare:CC (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0")
- (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (and:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (AND, operands, QImode)"
- "@
- and3\\t%2,%1,%0
- and3\\t%2,%1,%0
- andn\\t%N2,%0
- and\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,not_uint16,uint16")])
-
-;
-; ANDN
-;
-; NB, this insn doesn't have commutative operands, but valid_operands
-; assumes that the code AND does. We might have to kludge this if
-; we make valid_operands stricter.
-(define_insn "*andnqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm"))
- (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")))
- (clobber (reg:CC 21))]
- "valid_operands (AND, operands, QImode)"
- "@
- andn3\\t%2,%1,%0
- andn3\\t%2,%1,%0
- andn\\t%2,%0
- andn3\\t%2,%1,%0
- andn3\\t%2,%1,%0
- andn\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")
- (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")])
-
-(define_insn "*andnqi3_test"
- [(set (reg:CC 21)
- (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (match_operand:QI 1 "src_operand" "rR,rS<>,0"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (AND, operands, QImode)"
- "@
- andn3\\t%2,%1,%0
- andn3\\t%2,%1,%0
- andn\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-(define_insn "*andnqi3_set"
- [(set (reg:CC 21)
- (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (match_operand:QI 1 "src_operand" "rR,rS<>,0"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (and:QI (not:QI (match_dup 2))
- (match_dup 1)))]
- "valid_operands (AND, operands, QImode)"
- "@
- andn3\\t%2,%1,%0
- andn3\\t%2,%1,%0
- andn\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-;
-; OR
-;
-(define_expand "iorqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (ior:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "lsrc_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (IOR, operands, QImode);")
-
-(define_insn "*iorqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm")))
- (clobber (reg:CC 21))]
- "valid_operands (IOR, operands, QImode)"
- "@
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")
- (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")])
-
-(define_insn "*iorqi3_test"
- [(set (reg:CC 21)
- (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (IOR, operands, QImode)"
- "@
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")))
- (clobber (reg:CC 21))])
- (set (reg:CC 21)
- (compare:CC (match_dup 0) (const_int 0)))]
- "valid_operands (IOR, operands, QImode)"
- "@
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-(define_insn "*iorqi3_set"
- [(set (reg:CC 21)
- (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (ior:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (IOR, operands, QImode)"
- "@
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-; This pattern is used for loading symbol references in several parts.
-(define_insn "iorqi3_noclobber"
- [(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c")
- (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")))]
- "valid_operands (IOR, operands, QImode)"
- "@
- or3\\t%2,%1,%0
- or3\\t%2,%1,%0
- or\\t%2,%0"
- [(set_attr "type" "binary,binary,binary")
- (set_attr "data" "int16,uint16,uint16")])
-
-;
-; XOR
-;
-(define_expand "xorqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (xor:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "lsrc_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (XOR, operands, QImode);")
-
-(define_insn "*xorqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm")))
- (clobber (reg:CC 21))]
- "valid_operands (XOR, operands, QImode)"
- "@
- xor3\\t%2,%1,%0
- xor3\\t%2,%1,%0
- xor\\t%2,%0
- xor3\\t%2,%1,%0
- xor3\\t%2,%1,%0
- xor\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")
- (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")])
-
-(define_insn "*xorqi3_test"
- [(set (reg:CC 21)
- (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d,?d,d"))]
- "valid_operands (XOR, operands, QImode)"
- "@
- xor3\\t%2,%1,%0
- xor3\\t%2,%1,%0
- xor\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-(define_insn "*xorqi3_set"
- [(set (reg:CC 21)
- (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
- (xor:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (XOR, operands, QImode)"
- "@
- xor3\\t%2,%1,%0
- xor3\\t%2,%1,%0
- xor\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")
- (set_attr "data" "int16,uint16,uint16")])
-
-;
-; LSH/ASH (left)
-;
-; The C3x and C4x have two shift instructions ASH and LSH
-; If the shift count is positive, a left shift is performed
-; otherwise a right shift is performed. The number of bits
-; shifted is determined by the seven LSBs of the shift count.
-; If the absolute value of the count is 32 or greater, the result
-; using the LSH instruction is zero; with the ASH insn the result
-; is zero or negative 1. Note that the ISO C standard allows
-; the result to be machine dependent whenever the shift count
-; exceeds the size of the object.
-(define_expand "ashlqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (ashift:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (ASHIFT, operands, QImode);")
-
-(define_insn "*ashlqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
- (clobber (reg:CC 21))]
- "valid_operands (ASHIFT, operands, QImode)"
- "@
- ash3\\t%2,%1,%0
- ash3\\t%2,%1,%0
- ash\\t%2,%0
- ash3\\t%2,%1,%0
- ash3\\t%2,%1,%0
- ash\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-(define_insn "*ashlqi3_set"
- [(set (reg:CC 21)
- (compare:CC
- (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d,?d,d")
- (ashift:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (ASHIFT, operands, QImode)"
- "@
- ash3\\t%2,%1,%0
- ash3\\t%2,%1,%0
- ash\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-; Default to int16 data attr.
-
-; This is only used by lshrhi3_reg where we need a LSH insn that will
-; shift both ways.
-(define_insn "*lshlqi3_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")] 3)))
- (clobber (reg:CC 21))]
- "valid_operands (ASHIFT, operands, QImode)"
- "@
- lsh3\\t%2,%1,%0
- lsh3\\t%2,%1,%0
- lsh\\t%2,%0
- lsh3\\t%2,%1,%0
- lsh3\\t%2,%1,%0
- lsh\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-;
-; LSH (right)
-;
-; Logical right shift on the C[34]x works by negating the shift count,
-; then emitting a right shift with the shift count negated. This means
-; that all actual shift counts in the RTL will be positive.
-;
-(define_expand "lshrqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (lshiftrt:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (LSHIFTRT, operands, QImode);")
-
-; When the shift count is greater than the size of the word
-; the result can be implementation specific
-(define_insn "*lshrqi3_const_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c")
- (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r")
- (match_operand:QI 2 "const_int_operand" "n,n,J,J")))
- (clobber (reg:CC 21))]
- "valid_operands (LSHIFTRT, operands, QImode)"
- "@
- lsh\\t%n2,%0
- lsh\\t%n2,%0
- lsh3\\t%n2,%1,%0
- lsh3\\t%n2,%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-; When the shift count is greater than the size of the word
-; the result can be implementation specific
-(define_insn "*lshrqi3_const_set"
- [(set (reg:CC 21)
- (compare:CC
- (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,r")
- (match_operand:QI 2 "const_int_operand" "n,J"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=?d,d")
- (lshiftrt:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (LSHIFTRT, operands, QImode)"
- "@
- lsh\\t%n2,%0
- lsh3\\t%n2,%1,%0"
- [(set_attr "type" "binarycc,binarycc")])
-
-(define_insn "*lshrqi3_nonconst_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (lshiftrt:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (neg:QI (match_operand:QI 2 "src_operand" "R,rS<>,rm,R,rS<>,rm"))))
- (clobber (reg:CC 21))]
- "valid_operands (LSHIFTRT, operands, QImode)"
- "@
- lsh3\\t%2,%1,%0
- lsh3\\t%2,%1,%0
- lsh\\t%2,%0
- lsh3\\t%2,%1,%0
- lsh3\\t%2,%1,%0
- lsh\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-;
-; ASH (right)
-;
-; Arithmetic right shift on the C[34]x works by negating the shift count,
-; then emitting a right shift with the shift count negated. This means
-; that all actual shift counts in the RTL will be positive.
-
-(define_expand "ashrqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (ashiftrt:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (ASHIFTRT, operands, QImode);")
-
-; When the shift count is greater than the size of the word
-; the result can be implementation specific
-(define_insn "*ashrqi3_const_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c")
- (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r")
- (match_operand:QI 2 "const_int_operand" "n,n,J,J")))
- (clobber (reg:CC 21))]
- "valid_operands (ASHIFTRT, operands, QImode)"
- "@
- ash\\t%n2,%0
- ash\\t%n2,%0
- ash3\\t%n2,%1,%0
- ash3\\t%n2,%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-; When the shift count is greater than the size of the word
-; the result can be implementation specific
-(define_insn "*ashrqi3_const_set"
- [(set (reg:CC 21)
- (compare:CC
- (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,r")
- (match_operand:QI 2 "const_int_operand" "n,J"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=?d,d")
- (ashiftrt:QI (match_dup 1)
- (match_dup 2)))]
- "valid_operands (ASHIFTRT, operands, QImode)"
- "@
- ash\\t%n2,%0
- ash3\\t%n2,%1,%0"
- [(set_attr "type" "binarycc,binarycc")])
-
-(define_insn "*ashrqi3_nonconst_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
- (ashiftrt:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (neg:QI (match_operand:QI 2 "src_operand" "R,rS<>,rm,R,rS<>,rm"))))
- (clobber (reg:CC 21))]
- "valid_operands (ASHIFTRT, operands, QImode)"
- "@
- ash3\\t%2,%1,%0
- ash3\\t%2,%1,%0
- ash\\t%2,%0
- ash3\\t%2,%1,%0
- ash3\\t%2,%1,%0
- ash\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")])
-; Default to int16 data attr.
-
-;
-; CMPI
-;
-; Unfortunately the C40 doesn't allow cmpi3 7, *ar0++ so the next best
-; thing would be to get the small constant loaded into a register (say r0)
-; so that it could be hoisted out of the loop so that we only
-; would need to do cmpi3 *ar0++, r0. Now the loop optimisation pass
-; comes before the flow pass (which finds autoincrements) so we're stuck.
-; Ideally, GCC requires another loop optimisation pass (preferably after
-; reload) so that it can hoist invariants out of loops.
-; The current solution modifies legitimize_operands () so that small
-; constants are forced into a pseudo register.
-;
-(define_expand "cmpqi"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QI 0 "src_operand" "")
- (match_operand:QI 1 "src_operand" "")))]
- ""
- "legitimize_operands (COMPARE, operands, QImode);
- c4x_compare_op0 = operands[0];
- c4x_compare_op1 = operands[1];
- DONE;")
-
-(define_insn "*cmpqi_test"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QI 0 "src_operand" "rR,?rS<>,r")
- (match_operand:QI 1 "src_operand" "JR,rS<>,g")))]
- "valid_operands (COMPARE, operands, QImode)"
- "@
- cmpi3\\t%1,%0
- cmpi3\\t%1,%0
- cmpi\\t%1,%0"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpqi_test_noov"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:QI 0 "src_operand" "rR,?rS<>,r")
- (match_operand:QI 1 "src_operand" "JR,rS<>,g")))]
- "valid_operands (COMPARE, operands, QImode)"
- "@
- cmpi3\\t%1,%0
- cmpi3\\t%1,%0
- cmpi\\t%1,%0"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_expand "udivqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (udiv:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (UDIVQI3_LIBCALL, UDIV, QImode, operands);
- DONE;")
-
-(define_expand "divqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (div:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (DIVQI3_LIBCALL, DIV, QImode, operands);
- DONE;")
-
-(define_expand "umodqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (umod:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (UMODQI3_LIBCALL, UMOD, QImode, operands);
- DONE;")
-
-(define_expand "modqi3"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (mod:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (MODQI3_LIBCALL, MOD, QImode, operands);
- DONE;")
-
-(define_expand "ffsqi2"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (ffs:QI (match_operand:QI 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FFS_LIBCALL, FFS, QImode, QImode, 2, operands);
- DONE;")
-
-;
-; BIT-FIELD INSTRUCTIONS
-;
-
-;
-; LBx/LHw (C4x only)
-;
-(define_expand "extv"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (sign_extract:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "const_int_operand" "")
- (match_operand:QI 3 "const_int_operand" "")))
- (clobber (reg:CC 21))])]
- "! TARGET_C3X"
- "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16)
- || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0))
- FAIL;
- ")
-
-(define_insn "*extv_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (sign_extract:QI (match_operand:QI 1 "src_operand" "g,g")
- (match_operand:QI 2 "const_int_operand" "n,n")
- (match_operand:QI 3 "const_int_operand" "n,n")))
- (clobber (reg:CC 21))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lb%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lh%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc,binary")
- (set_attr "data" "int16,int16")])
-
-(define_insn "*extv_clobber_test"
- [(set (reg:CC 21)
- (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g")
- (match_operand:QI 2 "const_int_operand" "n")
- (match_operand:QI 3 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d"))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lb%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lh%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc")
- (set_attr "data" "int16")])
-
-(define_insn "*extv_clobber_set"
- [(set (reg:CC 21)
- (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g")
- (match_operand:QI 2 "const_int_operand" "n")
- (match_operand:QI 3 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d")
- (sign_extract:QI (match_dup 1)
- (match_dup 2)
- (match_dup 3)))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lb%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lh%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc")
- (set_attr "data" "int16")])
-
-;
-; LBUx/LHUw (C4x only)
-;
-(define_expand "extzv"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (zero_extract:QI (match_operand:QI 1 "src_operand" "")
- (match_operand:QI 2 "const_int_operand" "")
- (match_operand:QI 3 "const_int_operand" "")))
- (clobber (reg:CC 21))])]
- "! TARGET_C3X"
- "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16)
- || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0))
- FAIL;
- ")
-
-(define_insn "*extzv_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (zero_extract:QI (match_operand:QI 1 "src_operand" "g,g")
- (match_operand:QI 2 "const_int_operand" "n,n")
- (match_operand:QI 3 "const_int_operand" "n,n")))
- (clobber (reg:CC 21))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lbu%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lhu%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc,binary")
- (set_attr "data" "uint16,uint16")])
-
-(define_insn "*extzv_test"
- [(set (reg:CC 21)
- (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g")
- (match_operand:QI 2 "const_int_operand" "n")
- (match_operand:QI 3 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:QI 0 "=d"))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lbu%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lhu%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc")
- (set_attr "data" "uint16")])
-
-(define_insn "*extzv_set"
- [(set (reg:CC 21)
- (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g")
- (match_operand:QI 2 "const_int_operand" "n")
- (match_operand:QI 3 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d")
- (zero_extract:QI (match_dup 1)
- (match_dup 2)
- (match_dup 3)))]
- "! TARGET_C3X
- && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
- && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)"
- "*
- if (INTVAL (operands[2]) == 8)
- {
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return \"lbu%3\\t%1,%0\";
- }
- operands[3] = GEN_INT (INTVAL (operands[3]) / 16);
- return \"lhu%3\\t%1,%0\";
- "
- [(set_attr "type" "binarycc")
- (set_attr "data" "uint16")])
-
-;
-; MBx/MHw (C4x only)
-;
-(define_expand "insv"
- [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "")
- (match_operand:QI 1 "const_int_operand" "")
- (match_operand:QI 2 "const_int_operand" ""))
- (match_operand:QI 3 "src_operand" ""))
- (clobber (reg:CC 21))])]
- "! TARGET_C3X"
- "if (! (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
- && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0))
- || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)))
- FAIL;
- ")
-
-(define_insn "*insv_clobber"
- [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c")
- (match_operand:QI 1 "const_int_operand" "n,n")
- (match_operand:QI 2 "const_int_operand" "n,n"))
- (match_operand:QI 3 "src_operand" "g,g"))
- (clobber (reg:CC 21))]
- "! TARGET_C3X
- && (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
- && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0))
- || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8))"
- "*
- if (INTVAL (operands[1]) == 8)
- {
- operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
- return \"mb%2\\t%3,%0\";
- }
- else if (INTVAL (operands[1]) == 16)
- {
- operands[2] = GEN_INT (INTVAL (operands[2]) / 16);
- return \"mh%2\\t%3,%0\";
- }
- return \"lwl1\\t%3,%0\";
- "
- [(set_attr "type" "binarycc,binary")
- (set_attr "data" "uint16,uint16")])
-
-(define_peephole
- [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d")
- (match_operand:QI 1 "const_int_operand" "n")
- (match_operand:QI 2 "const_int_operand" "n"))
- (match_operand:QI 3 "src_operand" "g"))
- (clobber (reg:CC 21))])
- (set (reg:CC 21)
- (compare:CC (match_dup 0) (const_int 0)))]
- "! TARGET_C3X
- && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
- && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)"
- "*
- if (INTVAL (operands[1]) == 8)
- {
- operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
- return \"mb%2\\t%3,%0\";
- }
- operands[2] = GEN_INT (INTVAL (operands[2]) / 16);
- return \"mh%2\\t%3,%0\";
- "
- [(set_attr "type" "binarycc")
- (set_attr "data" "uint16")])
-
-;
-; TWO OPERAND FLOAT INSTRUCTIONS
-;
-
-;
-; LDF/STF
-;
-; If one of the operands is not a register, then we should
-; emit two insns, using a scratch register. This will produce
-; better code in loops if the source operand is invariant, since
-; the source reload can be optimised out. During reload we cannot
-; use change_address or force_reg.
-(define_expand "movqf"
- [(set (match_operand:QF 0 "src_operand" "")
- (match_operand:QF 1 "src_operand" ""))]
- ""
- "
- if (CONSTANT_P (operands[1]) && ! const_operand (operands[1], QFmode))
- {
- operands[1] = force_const_mem (QFmode, operands[1]);
- if (! memory_address_p (QFmode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], QFmode,
- XEXP (operands[1], 0));
- }
-
- if (! reload_in_progress
- && ! reg_operand (operands[0], QFmode)
- && ! reg_operand (operands[1], QFmode))
- operands[1] = force_reg (QFmode, operands[1]);
- ")
-
-; We must provide an alternative to store to memory in case we have to
-; spill a register.
-(define_insn "*movqf_noclobber"
- [(set (match_operand:QF 0 "src_operand" "=f,m")
- (match_operand:QF 1 "src_operand" "fmH,f"))]
- "reg_operand (operands[0], QFmode)
- || reg_operand (operands[1], QFmode)"
- "@
- ldfu\\t%1,%0
- stf\\t%1,%0"
- [(set_attr "type" "unary,store")])
-
-;(define_insn "*movqf_clobber"
-; [(set (match_operand:QF 0 "reg_operand" "=f")
-; (match_operand:QF 1 "src_operand" "fmH"))
-; (clobber (reg:CC 21))]
-; "0"
-; "ldf\\t%1,%0"
-; [(set_attr "type" "unarycc")])
-
-(define_insn "*movqf_test"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "src_operand" "fmH")
- (const_int 0)))
- (clobber (match_scratch:QF 0 "=f"))]
- ""
- "ldf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*movqf_set"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "src_operand" "fmH")
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (set (match_operand:QF 0 "reg_operand" "=f")
- (match_dup 1))]
- ""
- "ldf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*movqf_update"
- [(set (match_operand:QF 0 "reg_operand" "=r")
- (mem:QF (plus:QI (match_operand:QI 1 "addr_reg_operand" "a")
- (match_operand:QI 2 "index_reg_operand" "x"))))
- (set (match_dup 1)
- (plus:QI (match_dup 1) (match_dup 2)))]
- ""
- "ldfu\\t*%1++(%2),%0"
- [(set_attr "type" "unary")])
-
-(define_insn "*movqf_parallel"
- [(set (match_operand:QF 0 "parallel_operand" "=q,S<>,q,S<>")
- (match_operand:QF 1 "parallel_operand" "S<>,q,S<>,q"))
- (set (match_operand:QF 2 "parallel_operand" "=q,S<>,S<>,q")
- (match_operand:QF 3 "parallel_operand" "S<>,q,q,S<>"))]
- "valid_parallel_load_store (operands, QFmode)"
- "@
- ldf1\\t%1,%0\\n||\\tldf2\\t%3,%2
- stf1\\t%1,%0\\n||\\tstf2\\t%3,%2
- ldf\\t%1,%0\\n||\\tstf\\t%3,%2
- ldf\\t%3,%2\\n||\\tstf\\t%1,%0"
- [(set_attr "type" "load_load,store_store,load_store,store_load")])
-
-
-;
-; PUSH/POP
-;
-(define_insn "*pushqf"
- [(set (mem:QF (pre_inc:QI (reg:QI 20)))
- (match_operand:QF 0 "reg_operand" "f"))]
- ""
- "pushf\\t%0"
- [(set_attr "type" "push")])
-
-(define_insn "*popqf"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (mem:QF (post_dec:QI (reg:QI 20))))
- (clobber (reg:CC 21))]
- ""
- "popf\\t%0"
- [(set_attr "type" "pop")])
-
-
-;
-; ABSF
-;
-(define_expand "absqf2"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (abs:QF (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
-""
-"")
-
-(define_insn "*absqf2_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (abs:QF (match_operand:QF 1 "src_operand" "fmH")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*absqf2_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH"))
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (clobber (match_scratch:QF 0 "=f"))]
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*absqf2_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH"))
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (set (match_operand:QF 0 "reg_operand" "=f")
- (abs:QF (match_dup 1)))]
-
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; NEGF
-;
-(define_expand "negqf2"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (neg:QF (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
-""
-"")
-
-(define_insn "*negqf2_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (neg:QF (match_operand:QF 1 "src_operand" "fmH")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*negqf2_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH"))
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (clobber (match_scratch:QF 0 "=f"))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*negqf2_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH"))
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (set (match_operand:QF 0 "reg_operand" "=f")
- (neg:QF (match_dup 1)))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; FLOAT
-;
-(define_insn "floatqiqf2"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (float:QF (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- ""
- "float\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*floatqiqf2_set"
- [(set (reg:CC 21)
- (compare:CC (float:QF (match_operand:QI 1 "src_operand" "g"))
- (match_operand:QF 2 "fp_zero_operand" "G")))
- (set (match_operand:QF 0 "reg_operand" "=f")
- (float:QF (match_dup 1)))]
-
- ""
- "float\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-; Unsigned conversions are a little tricky because we need to
-; add the value for the high bit if necessary.
-;
-(define_expand "floatunsqiqf2"
- [(set (match_dup 2) (match_dup 3))
- (parallel [(set (reg:CC 21)
- (compare:CC (float:QF (match_operand:QI 1 "src_operand" ""))
- (match_dup 3)))
- (set (match_dup 4)
- (float:QF (match_dup 1)))])
- (set (match_dup 2)
- (if_then_else:QF (lt (reg:CC 21) (const_int 0))
- (mem:QF (symbol_ref:QF "*___unsfltconst"))
- (match_dup 2)))
- (parallel [(set (match_operand:QF 0 "reg_operand" "")
- (plus:QF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "operands[2] = gen_reg_rtx (QFmode);
- operands[3] = CONST0_RTX (QFmode);
- operands[4] = gen_reg_rtx (QFmode);
- ")
-
-(define_insn "floatqihf2"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (float:HF (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- ""
- "float\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; FIX
-;
-(define_insn "fixqfqi_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=d,c")
- (fix:QI (match_operand:QF 1 "src_operand" "fmH,fmH")))
- (clobber (reg:CC 21))]
- ""
- "fix\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*fixqfqi_set"
- [(set (reg:CC 21)
- (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fmH"))
- (const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d")
- (fix:QI (match_dup 1)))]
- ""
- "fix\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; The C[34]x fix instruction implements a floor, not a straight trunc,
-; so we have to invert the number, fix it, and reinvert it if negative
-;
-(define_expand "fix_truncqfqi2"
- [(parallel [(set (match_dup 2)
- (fix:QI (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 3) (neg:QF (match_dup 1)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (fix:QI (match_dup 3)))
- (clobber (reg:CC 21))])
- (parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0)))
- (set (match_dup 5) (neg:QI (match_dup 4)))])
- (set (match_dup 2)
- (if_then_else:QI (le (reg:CC 21) (const_int 0))
- (match_dup 5)
- (match_dup 2)))
- (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))]
- ""
- "if (TARGET_FAST_FIX)
- {
- emit_insn (gen_fixqfqi_clobber (operands[0], operands[1]));
- DONE;
- }
- operands[2] = gen_reg_rtx (QImode);
- operands[3] = gen_reg_rtx (QFmode);
- operands[4] = gen_reg_rtx (QImode);
- operands[5] = gen_reg_rtx (QImode);
- ")
-
-(define_expand "fix_truncqfhi2"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (fix:HI (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FIX_TRUNCQFHI2_LIBCALL, FIX, HImode, QFmode, 2, operands);
- DONE;")
-
-(define_expand "fixuns_truncqfqi2"
- [(set (match_dup 2) (match_dup 4))
- (set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "reg_operand" "")
- (mem:QF (symbol_ref "*___unsfltcompare"))))
- (set (match_dup 2)
- (if_then_else:QF (ge (reg:CC 21) (const_int 0))
- (mem:QF (symbol_ref "*___unsfltconst"))
- (match_dup 2)))
- (parallel [(set (match_dup 3)
- (minus:QF (match_dup 1) (match_dup 2)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:QI 0 "reg_operand" "")
- (fix:QI (match_dup 3)))
- (clobber (reg:CC 21))])]
- ""
- "operands[2] = gen_reg_rtx (QFmode);
- operands[3] = gen_reg_rtx (QFmode);
- operands[4] = CONST0_RTX (QFmode);
- ")
-
-(define_expand "fixuns_truncqfhi2"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (unsigned_fix:HI (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FIXUNS_TRUNCQFHI2_LIBCALL, UNSIGNED_FIX,
- HImode, QFmode, 2, operands);
- DONE;")
-
-;
-; RCPF
-;
-(define_insn "*rcpfqf_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 5))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rcpf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; RSQRF
-;
-(define_insn "*rsqrfqf_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 10))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rsqrf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; RNDF
-;
-(define_insn "*rndqf_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 6))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rnd\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-
-; Inlined float square root for C4x
-(define_expand "sqrtqf2_inline"
- [(parallel [(set (match_dup 2)
- (unspec [(match_operand:QF 1 "src_operand" "")] 10))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:QF (match_dup 5) (match_dup 1)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 1)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:QF 0 "reg_operand" "")
- (unspec [(match_dup 4)] 6))
- (clobber (reg:CC_NOOV 21))])]
- "! TARGET_C3X"
- "if (! reload_in_progress
- && ! reg_operand (operands[1], QFmode))
- operands[1] = force_reg (QFmode, operands[1]);
- operands[2] = gen_reg_rtx (QFmode);
- operands[3] = gen_reg_rtx (QFmode);
- operands[4] = gen_reg_rtx (QFmode);
- operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", QFmode),
- QFmode);
- operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", QFmode),
- QFmode);")
-
-(define_expand "sqrtqf2"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (sqrt:QF (match_operand:QF 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (TARGET_C3X || ! TARGET_INLINE)
- FAIL;
- else
- {
- emit_insn (gen_sqrtqf2_inline (operands[0], operands[1]));
- DONE;
- }
- ")
-
-;
-; THREE OPERAND FLOAT INSTRUCTIONS
-;
-
-;
-; ADDF
-;
-(define_expand "addqf3"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (plus:QF (match_operand:QF 1 "src_operand" "")
- (match_operand:QF 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (PLUS, operands, QFmode);")
-
-(define_insn "*addqf3_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
- (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (PLUS, operands, QFmode)"
- "@
- addf3\\t%2,%1,%0
- addf3\\t%2,%1,%0
- addf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_insn "*addqf3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G")))
- (clobber (match_scratch:QF 0 "=f,?f,f"))]
- "valid_operands (PLUS, operands, QFmode)"
- "@
- addf3\\t%2,%1,%0
- addf3\\t%2,%1,%0
- addf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_insn "*addqf3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G")))
- (set (match_operand:QF 0 "reg_operand" "=f,?f,f")
- (plus:QF (match_dup 1)
- (match_dup 2)))]
- "valid_operands (PLUS, operands, QFmode)"
- "@
- addf3\\t%2,%1,%0
- addf3\\t%2,%1,%0
- addf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-;
-; SUBF/SUBRF
-;
-(define_expand "subqf3"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (minus:QF (match_operand:QF 1 "src_operand" "")
- (match_operand:QF 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MINUS, operands, QFmode);")
-
-(define_insn "*subqf3_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f,?f,f,f")
- (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MINUS, operands, QFmode)"
- "@
- subf3\\t%2,%1,%0
- subf3\\t%2,%1,%0
- subf\\t%2,%0
- subrf\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-(define_insn "*subqf3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G,G")))
- (clobber (match_scratch:QF 0 "=f,?f,f,f"))]
- "valid_operands (MINUS, operands, QFmode)"
- "@
- subf3\\t%2,%1,%0
- subf3\\t%2,%1,%0
- subf\\t%2,%0
- subrf\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-(define_insn "*subqf3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G,G")))
- (set (match_operand:QF 0 "reg_operand" "=f,?f,f,f")
- (minus:QF (match_dup 1)
- (match_dup 2)))]
- "valid_operands (MINUS, operands, QFmode)"
- "@
- subf3\\t%2,%1,%0
- subf3\\t%2,%1,%0
- subf\\t%2,%0
- subrf\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")])
-
-;
-; MPYF
-;
-(define_expand "mulqf3"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (mult:QF (match_operand:QF 1 "src_operand" "")
- (match_operand:QF 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MULT, operands, QFmode);")
-
-(define_insn "*mulqf3_clobber"
- [(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
- (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MULT, operands, QFmode)"
- "@
- mpyf3\\t%2,%1,%0
- mpyf3\\t%2,%1,%0
- mpyf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_insn "*mulqf3_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G")))
- (clobber (match_scratch:QF 0 "=f,?f,f"))]
- "valid_operands (MULT, operands, QFmode)"
- "@
- mpyf3\\t%2,%1,%0
- mpyf3\\t%2,%1,%0
- mpyf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-(define_insn "*mulqf3_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
- (match_operand:QF 3 "fp_zero_operand" "G,G,G")))
- (set (match_operand:QF 0 "reg_operand" "=f,?f,f")
- (mult:QF (match_dup 1)
- (match_dup 2)))]
- "valid_operands (MULT, operands, QFmode)"
- "@
- mpyf3\\t%2,%1,%0
- mpyf3\\t%2,%1,%0
- mpyf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-;
-; CMPF
-;
-(define_expand "cmpqf"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QF 0 "src_operand" "")
- (match_operand:QF 1 "src_operand" "")))]
- ""
- "legitimize_operands (COMPARE, operands, QFmode);
- c4x_compare_op0 = operands[0];
- c4x_compare_op1 = operands[1];
- DONE;")
-
-(define_insn "*cmpqf"
- [(set (reg:CC 21)
- (compare:CC (match_operand:QF 0 "src_operand" "fR,?fS<>,f")
- (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))]
- "valid_operands (COMPARE, operands, QFmode)"
- "@
- cmpf3\\t%1,%0
- cmpf3\\t%1,%0
- cmpf\\t%1,%0"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpqf_noov"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:QF 0 "src_operand" "fR,?fS<>,f")
- (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))]
- "valid_operands (COMPARE, operands, QFmode)"
- "@
- cmpf3\\t%1,%0
- cmpf3\\t%1,%0
- cmpf\\t%1,%0"
- [(set_attr "type" "compare,compare,compare")])
-
-; Inlined float divide for C4x
-(define_expand "divqf3_inline"
- [(parallel [(set (match_dup 3)
- (unspec [(match_operand:QF 2 "src_operand" "")] 5))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3)
- (mult:QF (match_operand:QF 1 "src_operand" "")
- (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:QF 0 "reg_operand" "")
- (unspec [(match_dup 3)] 6))
- (clobber (reg:CC_NOOV 21))])]
- "! TARGET_C3X"
- "if (! reload_in_progress
- && ! reg_operand (operands[2], QFmode))
- operands[2] = force_reg (QFmode, operands[2]);
- operands[3] = gen_reg_rtx (QFmode);
- operands[4] = gen_reg_rtx (QFmode);
- operands[5] = CONST2_RTX (QFmode);")
-
-(define_expand "divqf3"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (div:QF (match_operand:QF 1 "src_operand" "")
- (match_operand:QF 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (TARGET_C3X || ! TARGET_INLINE)
- {
- c4x_emit_libcall3 (DIVQF3_LIBCALL, DIV, QFmode, operands);
- DONE;
- }
- else
- {
- emit_insn (gen_divqf3_inline (operands[0], operands[1], operands[2]));
- DONE;
- }
- ")
-
-;
-; CONDITIONAL MOVES
-;
-
-(define_insn "*ldi_conditional"
- [(set (match_operand:QI 0 "reg_operand" "=r,r")
- (if_then_else:QI (match_operator 1 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (match_operand:QI 2 "src_operand" "g,0")
- (match_operand:QI 3 "src_operand" "0,g")))]
- ""
- "@
- ldi%1\\t%2,%0
- ldi%I1\\t%3,%0"
- [(set_attr "type" "binary")])
-
-(define_insn "*ldi_conditional_noov"
- [(set (match_operand:QI 0 "reg_operand" "=r,r")
- (if_then_else:QI (match_operator 1 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (match_operand:QI 2 "src_operand" "g,0")
- (match_operand:QI 3 "src_operand" "0,g")))]
- "GET_CODE (operands[1]) != LE
- && GET_CODE (operands[1]) != GE
- && GET_CODE (operands[1]) != LT
- && GET_CODE (operands[1]) != GT"
- "@
- ldi%1\\t%2,%0
- ldi%I1\\t%3,%0"
- [(set_attr "type" "binary")])
-
-; Move operand 2 to operand 0 if condition (operand 1) is true
-; else move operand 3 to operand 0.
-; The temporary register is required below because some of the operands
-; might be identical (namely 0 and 2).
-;
-(define_expand "movqicc"
- [(set (match_operand:QI 0 "reg_operand" "")
- (if_then_else:QI (match_operand 1 "comparison_operator" "")
- (match_operand:QI 2 "src_operand" "")
- (match_operand:QI 3 "src_operand" "")))]
- ""
- "{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1);
- if (ccreg == NULL_RTX) FAIL;
- emit_insn (gen_rtx_SET (QImode, operands[0],
- gen_rtx_IF_THEN_ELSE (QImode,
- gen_rtx (code, VOIDmode, ccreg, const0_rtx),
- operands[2], operands[3])));
- DONE;}")
-
-(define_insn "*ldf_conditional"
- [(set (match_operand:QF 0 "reg_operand" "=f,f")
- (if_then_else:QF (match_operator 1 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (match_operand:QF 2 "src_operand" "fmH,0")
- (match_operand:QF 3 "src_operand" "0,fmH")))]
- ""
- "@
- ldf%1\\t%2,%0
- ldf%I1\\t%3,%0"
- [(set_attr "type" "binary")])
-
-(define_insn "*ldf_conditional_noov"
- [(set (match_operand:QF 0 "reg_operand" "=f,f")
- (if_then_else:QF (match_operator 1 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (match_operand:QF 2 "src_operand" "fmH,0")
- (match_operand:QF 3 "src_operand" "0,fmH")))]
- "GET_CODE (operands[1]) != LE
- && GET_CODE (operands[1]) != GE
- && GET_CODE (operands[1]) != LT
- && GET_CODE (operands[1]) != GT"
- "@
- ldf%1\\t%2,%0
- ldf%I1\\t%3,%0"
- [(set_attr "type" "binary")])
-
-(define_expand "movqfcc"
- [(set (match_operand:QF 0 "reg_operand" "")
- (if_then_else:QF (match_operand 1 "comparison_operator" "")
- (match_operand:QF 2 "src_operand" "")
- (match_operand:QF 3 "src_operand" "")))]
- ""
- "{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1);
- if (ccreg == NULL_RTX) FAIL;
- emit_insn (gen_rtx_SET (QFmode, operands[0],
- gen_rtx_IF_THEN_ELSE (QFmode,
- gen_rtx (code, VOIDmode, ccreg, const0_rtx),
- operands[2], operands[3])));
- DONE;}")
-
-(define_expand "seq"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (eq (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "sne"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (ne (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "slt"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (lt (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "sltu"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (ltu (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "sgt"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (gt (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "sgtu"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (gtu (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "sle"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (le (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "sleu"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (leu (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "sge"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (ge (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "sgeu"
- [(set (match_operand:QI 0 "reg_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (geu (match_dup 1) (const_int 0))
- (const_int 1)
- (match_dup 0)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_split
- [(set (match_operand:QI 0 "reg_operand" "")
- (match_operator 1 "comparison_operator" [(reg:CC 21) (const_int 0)]))]
- "reload_completed"
- [(set (match_dup 0) (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(reg:CC 21) (const_int 0)])
- (const_int 1)
- (match_dup 0)))]
- "")
-
-(define_split
- [(set (match_operand:QI 0 "reg_operand" "")
- (match_operator 1 "comparison_operator" [(reg:CC_NOOV 21) (const_int 0)]))]
- "reload_completed"
- [(set (match_dup 0) (const_int 0))
- (set (match_dup 0)
- (if_then_else:QI (match_op_dup 1 [(reg:CC_NOOV 21) (const_int 0)])
- (const_int 1)
- (match_dup 0)))]
- "")
-
-(define_insn "*bu"
- [(set (pc)
- (unspec [(match_operand:QI 0 "reg_operand" "r")] 1))]
- ""
- "bu%#\\t%0"
- [(set_attr "type" "jump")])
-
-(define_expand "caseqi"
- [(parallel [(set (match_dup 5)
- (minus:QI (match_operand:QI 0 "reg_operand" "")
- (match_operand:QI 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (reg:CC 21)
- (compare:CC (match_dup 5)
- (match_operand:QI 2 "src_operand" "")))
- (set (pc)
- (if_then_else (gtu (reg:CC 21)
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (parallel [(set (match_dup 6)
- (plus:QI (match_dup 5)
- (label_ref:QI (match_operand 3 "" ""))))
- (clobber (reg:CC_NOOV 21))])
- (set (match_dup 7)
- (mem:QI (match_dup 6)))
- (set (pc) (match_dup 7))]
- ""
- "operands[5] = gen_reg_rtx (QImode);
- operands[6] = gen_reg_rtx (QImode);
- operands[7] = gen_reg_rtx (QImode);")
-
-;
-; PARALLEL FLOAT INSTRUCTIONS
-;
-; This patterns are under development
-
-;
-; ABSF/STF
-;
-
-(define_insn "*absqf2_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (abs:QF (match_operand:QF 1 "par_ind_operand" "S<>")))
- (set (match_operand:QF 2 "par_ind_operand" "=S<>")
- (match_operand:QF 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC_NOOV 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)"
- "absf\\t%1,%0\\n||\\tstf\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; ADDF/STF
-;
-
-(define_insn "*addqf3_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (plus:QF (match_operand:QF 1 "parallel_operand" "%q")
- (match_operand:QF 2 "parallel_operand" "S<>")))
- (set (match_operand:QF 3 "par_ind_operand" "=S<>")
- (match_operand:QF 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)"
- "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; FLOAT/STF
-;
-
-(define_insn "*floatqiqf2_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (float:QF (match_operand:QI 1 "par_ind_operand" "S<>")))
- (set (match_operand:QF 2 "par_ind_operand" "=S<>")
- (match_operand:QF 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)"
- "float\\t%1,%0\\n||\\tstf\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; MPYF/ADDF
-;
-
-(define_insn "*mulqf3_addqf3_clobber"
- [(set (match_operand:QF 0 "r0r1_reg_operand" "=t")
- (mult:QF (match_operand:QF 1 "parallel_operand" "%S<>q")
- (match_operand:QF 2 "parallel_operand" "S<>q")))
- (set (match_operand:QF 3 "r2r3_reg_operand" "=u")
- (plus:QF (match_operand:QF 4 "parallel_operand" "%S<>q")
- (match_operand:QF 5 "parallel_operand" "S<>q")))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)"
- "mpyf3\\t%2,%1,%0\\n||\\taddf3\\t%5,%4,%3"
- [(set_attr "type" "binarycc")])
-
-
-;
-; MPYF/STF
-;
-
-(define_insn "*mulqf3_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (mult:QF (match_operand:QF 1 "parallel_operand" "%q")
- (match_operand:QF 2 "parallel_operand" "S<>")))
- (set (match_operand:QF 3 "par_ind_operand" "=S<>")
- (match_operand:QF 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)"
- "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; MPYF/SUBF
-;
-
-(define_insn "*mulqf3_subqf3_clobber"
- [(set (match_operand:QF 0 "r0r1_reg_operand" "=t")
- (mult:QF (match_operand:QF 1 "parallel_operand" "S<>q")
- (match_operand:QF 2 "parallel_operand" "S<>q")))
- (set (match_operand:QF 3 "r2r3_reg_operand" "=u")
- (minus:QF (match_operand:QF 4 "parallel_operand" "S<>q")
- (match_operand:QF 5 "parallel_operand" "S<>q")))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)"
- "mpyf3\\t%2,%1,%0\\n||\\tsubf3\\t%5,%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; NEGF/STF
-;
-
-(define_insn "*negqf2_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (neg:QF (match_operand:QF 1 "par_ind_operand" "S<>")))
- (set (match_operand:QF 2 "par_ind_operand" "=S<>")
- (match_operand:QF 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)"
- "negf\\t%1,%0\\n||\\tstf\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; SUBF/STF
-;
-
-(define_insn "*subqf3_movqf_clobber"
- [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
- (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "q")
- (match_operand:QF 2 "par_ind_operand" "S<>")))
- (set (match_operand:QF 3 "par_ind_operand" "=S<>")
- (match_operand:QF 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)"
- "subf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; PARALLEL INTEGER INSTRUCTIONS
-;
-; These patterns are under development
-
-;
-; ABSI/STI
-;
-
-(define_insn "*absqi2_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (abs:QI (match_operand:QI 1 "par_ind_operand" "S<>")))
- (set (match_operand:QI 2 "par_ind_operand" "=S<>")
- (match_operand:QI 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC_NOOV 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)"
- "absi\\t%1,%0\\n||\\tsti\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; ADDI/STI
-;
-
-(define_insn "*addqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (plus:QI (match_operand:QI 1 "parallel_operand" "%q")
- (match_operand:QI 2 "parallel_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; AND/STI
-;
-
-(define_insn "*andqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (and:QI (match_operand:QI 1 "parallel_operand" "%q")
- (match_operand:QI 2 "parallel_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; ASH(left)/STI
-;
-
-(define_insn "*ashlqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (ashift:QI (match_operand:QI 1 "par_ind_operand" "S<>")
- (match_operand:QI 2 "ext_low_reg_operand" "q")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; ASH(right)/STI
-;
-
-(define_insn "*ashrqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (ashiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>")
- (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q"))))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; FIX/STI
-;
-
-(define_insn "*fixqfqi2_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (fix:QI (match_operand:QF 1 "par_ind_operand" "S<>")))
- (set (match_operand:QI 2 "par_ind_operand" "=S<>")
- (match_operand:QI 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)"
- "fix\\t%1,%0\\n||\\tsti\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; LSH(right)/STI
-;
-
-(define_insn "*lshrqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (lshiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>")
- (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q"))))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "lsh3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; MPYI/ADDI
-;
-
-(define_insn "*mulqi3_addqi3_clobber"
- [(set (match_operand:QI 0 "r0r1_reg_operand" "=t")
- (mult:QI (match_operand:QI 1 "parallel_operand" "S<>q")
- (match_operand:QI 2 "parallel_operand" "S<>q")))
- (set (match_operand:QI 3 "r2r3_reg_operand" "=u")
- (plus:QI (match_operand:QI 4 "parallel_operand" "S<>q")
- (match_operand:QI 5 "parallel_operand" "S<>q")))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL_MPY && TARGET_MPYI
- && valid_parallel_operands_6 (operands, QImode)"
- "mpyi3\\t%2,%1,%0\\n||\\taddi3\\t%5,%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; MPYI/STI
-;
-
-(define_insn "*mulqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (mult:QI (match_operand:QI 1 "parallel_operand" "%q")
- (match_operand:QI 2 "parallel_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && TARGET_MPYI
- && valid_parallel_operands_5 (operands, QImode)"
- "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; MPYI/SUBI
-;
-
-(define_insn "*mulqi3_subqi3_clobber"
- [(set (match_operand:QI 0 "r0r1_reg_operand" "=t")
- (mult:QI (match_operand:QI 1 "parallel_operand" "S<>q")
- (match_operand:QI 2 "parallel_operand" "S<>q")))
- (set (match_operand:QI 3 "r2r3_reg_operand" "=u")
- (minus:QI (match_operand:QI 4 "parallel_operand" "S<>q")
- (match_operand:QI 5 "parallel_operand" "S<>q")))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL_MPY && TARGET_MPYI
- && valid_parallel_operands_6 (operands, QImode)"
- "mpyi3\\t%2,%1,%0\\n||\\tsubi3\\t%5,%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; NEGI/STI
-;
-
-(define_insn "*negqi2_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (neg:QI (match_operand:QI 1 "par_ind_operand" "S<>")))
- (set (match_operand:QI 2 "par_ind_operand" "=S<>")
- (match_operand:QI 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)"
- "negi\\t%1,%0\\n||\\tsti\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; NOT/STI
-;
-
-(define_insn "*notqi2_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (not:QI (match_operand:QI 1 "par_ind_operand" "S<>")))
- (set (match_operand:QI 2 "par_ind_operand" "=S<>")
- (match_operand:QI 3 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)"
- "not\\t%1,%0\\n||\\tsti\\t%3,%2"
- [(set_attr "type" "binarycc")])
-
-;
-; OR/STI
-;
-
-(define_insn "*iorqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (ior:QI (match_operand:QI 1 "parallel_operand" "%q")
- (match_operand:QI 2 "parallel_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; SUBI/STI
-;
-
-(define_insn "*subqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "q")
- (match_operand:QI 2 "par_ind_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; XOR/STI
-;
-
-(define_insn "*xorqi3_movqi_clobber"
- [(set (match_operand:QI 0 "ext_low_reg_operand" "=q")
- (xor:QI (match_operand:QI 1 "parallel_operand" "%q")
- (match_operand:QI 2 "parallel_operand" "S<>")))
- (set (match_operand:QI 3 "par_ind_operand" "=S<>")
- (match_operand:QI 4 "ext_low_reg_operand" "q"))
- (clobber (reg:CC 21))]
- "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)"
- "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3"
- [(set_attr "type" "binarycc")])
-
-;
-; BRANCH/CALL INSTRUCTIONS
-;
-
-;
-; Branch instructions
-;
-(define_insn "*b"
- [(set (pc) (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
- "*
- return c4x_output_cbranch (\"b%0\", insn);"
- [(set_attr "type" "jmpc")])
-
-(define_insn "*b_rev"
- [(set (pc) (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
- ""
- "*
- return c4x_output_cbranch (\"b%I0\", insn);"
- [(set_attr "type" "jmpc")])
-
-(define_insn "*b_noov"
- [(set (pc) (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "GET_CODE (operands[0]) != LE
- && GET_CODE (operands[0]) != GE
- && GET_CODE (operands[0]) != LT
- && GET_CODE (operands[0]) != GT"
- "*
- return c4x_output_cbranch (\"b%0\", insn);"
- [(set_attr "type" "jmpc")])
-
-(define_insn "*b_noov_rev"
- [(set (pc) (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
- "GET_CODE (operands[0]) != LE
- && GET_CODE (operands[0]) != GE
- && GET_CODE (operands[0]) != LT
- && GET_CODE (operands[0]) != GT"
- "*
- return c4x_output_cbranch (\"b%I0\", insn);"
- [(set_attr "type" "jmpc")])
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1);
- if (operands[1] == NULL_RTX) FAIL;")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (match_dup 1) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);")
-
-(define_insn "*b_reg"
- [(set (pc) (match_operand:QI 0 "reg_operand" "r"))]
- ""
- "bu%#\\t%0"
- [(set_attr "type" "jump")])
-
-(define_expand "indirect_jump"
- [(set (pc) (match_operand:QI 0 "reg_operand" ""))]
- ""
- "")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:QI 0 "src_operand" "r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "bu%#\\t%0"
- [(set_attr "type" "jump")])
-
-;
-; CALL
-;
-(define_insn "*call_c3x"
- [(call (match_operand:QI 0 "call_operand" "T,!o")
- (match_operand:QI 1 "general_operand" ""))
- (clobber (reg:QI 31))]
- ;; Operand 1 not really used on the C4x. The C30 doesn't have reg 31.
-
- "TARGET_C3X"
- "@
- call\\t%C0
- callu\\t%R0"
- [(set_attr "type" "call,call")])
-
-; LAJ requires R11 (31) for the return address
-(define_insn "*laj"
- [(call (match_operand:QI 0 "call_operand" "T,!o")
- (match_operand:QI 1 "general_operand" ""))
- (clobber (reg:QI 31))]
- ;; Operand 1 not really used on the C4x.
-
- "! TARGET_C3X"
- "*
- if (which_alternative == 0)
- {
- if (final_sequence)
- return \"laj\\t%C0\";
- else
- return \"call\\t%C0\";
- }
- else
- {
- if (final_sequence)
- return \"laju\\t%R0\";
- else
- return \"callu\\t%R0\";
- }"
- [(set_attr "type" "laj,laj")])
-
-(define_expand "call"
- [(parallel [(call (match_operand:QI 0 "call_operand" "")
- (match_operand:QI 1 "general_operand" ""))
- (clobber (reg:QI 31))])]
- ""
- "")
-
-(define_insn "*callv_c3x"
- [(set (match_operand 0 "" "=r,r")
- (call (match_operand:QI 1 "call_operand" "T,!o")
- (match_operand:QI 2 "general_operand" "")))
- (clobber (reg:QI 31))]
- ;; Operand 0 and 2 not really used for the C4x.
- ;; The C30 doesn't have reg 31.
-
- "TARGET_C3X"
- "@
- call\\t%C1
- callu\\t%R1"
- [(set_attr "type" "call,call")])
-
-; LAJ requires R11 (31) for the return address
-(define_insn "*lajv"
- [(set (match_operand 0 "" "=r,r")
- (call (match_operand:QI 1 "call_operand" "T,!o")
- (match_operand:QI 2 "general_operand" "")))
- (clobber (reg:QI 31))]
- ;; Operand 0 and 2 not really used in the C30 instruction.
-
- "! TARGET_C3X"
- "*
- if (which_alternative == 0)
- {
- if (final_sequence)
- return \"laj\\t%C1\";
- else
- return \"call\\t%C1\";
- }
- else
- {
- if (final_sequence)
- return \"laju\\t%R1\";
- else
- return \"callu\\t%R1\";
- }"
- [(set_attr "type" "laj,laj")])
-
-(define_expand "call_value"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "call_operand" "")
- (match_operand:QI 2 "general_operand" "")))
- (clobber (reg:QI 31))])]
- ""
- "")
-
-(define_insn "return"
- [(return)]
- "c4x_null_epilogue_p ()"
- "rets"
- [(set_attr "type" "rets")])
-
-(define_insn "*return_cc"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (return)
- (pc)))]
- "c4x_null_epilogue_p ()"
- "rets%0"
- [(set_attr "type" "rets")])
-
-(define_insn "*return_cc_noov"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (return)
- (pc)))]
- "GET_CODE (operands[0]) != LE
- && GET_CODE (operands[0]) != GE
- && GET_CODE (operands[0]) != LT
- && GET_CODE (operands[0]) != GT
- && c4x_null_epilogue_p ()"
- "rets%0"
- [(set_attr "type" "rets")])
-
-(define_insn "*return_cc_inverse"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (pc)
- (return)))]
- "c4x_null_epilogue_p ()"
- "rets%I0"
- [(set_attr "type" "rets")])
-
-(define_insn "*return_cc_noov_inverse"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(reg:CC_NOOV 21) (const_int 0)])
- (pc)
- (return)))]
- "GET_CODE (operands[0]) != LE
- && GET_CODE (operands[0]) != GE
- && GET_CODE (operands[0]) != LT
- && GET_CODE (operands[0]) != GT
- && c4x_null_epilogue_p ()"
- "rets%I0"
- [(set_attr "type" "rets")])
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "br%#\\t%l0"
- [(set_attr "type" "jump")])
-
-;
-; DBcond
-;
-; Note we have to emit a dbu instruction if there are no delay slots
-; to fill.
-; Also note that GCC will try to reverse a loop to see if it can
-; utilise this instruction. However, if there are more than one
-; memory reference in the loop, it cannot guarantee that reversing
-; the loop will work :( (see check_dbra_loop() in loop.c)
-; Note that the C3x only decrements the 24 LSBs of the address register
-; and the 8 MSBs are untouched. The C4x uses all 32-bits. We thus
-; have an option to disable this instruction.
-(define_insn "*db"
- [(set (pc)
- (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0)
- (const_int -1)))
- (clobber (reg:CC_NOOV 21))]
- "TARGET_DB && TARGET_LOOP_UNSIGNED"
- "*
- if (which_alternative == 0)
- return \"dbu%#\\t%0,%l1\";
- else if (which_alternative == 1)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn);
- else if (which_alternative == 2)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn);
- else
- return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn);
- "
- [(set_attr "type" "db,jmpc,jmpc,jmpc")])
-
-
-; This insn is used for some loop tests, typically loops reversed when
-; strength reduction is used. It is actually created when the instruction
-; combination phase combines the special loop test. Since this insn
-; is both a jump insn and has an output, it must deal with its own
-; reloads, hence the `m' constraints.
-
-; The C4x does the decrement and then compares the result against zero.
-; It branches if the result was greater than or equal to zero.
-; In the RTL the comparison and decrement are assumed to happen
-; at the same time so we bias the iteration counter with by -1
-; when we make the test.
-(define_insn "decrement_and_branch_until_zero"
- [(set (pc)
- (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
- (const_int -1))
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0)
- (const_int -1)))
- (clobber (reg:CC_NOOV 21))]
- "TARGET_DB && find_reg_note (insn, REG_NONNEG, 0)"
- "*
- if (which_alternative == 0)
- return \"dbu%#\\t%0,%l1\";
- else if (which_alternative == 1)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn);
- else if (which_alternative == 2)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn);
- else
- return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn);
- "
- [(set_attr "type" "db,jmpc,jmpc,jmpc")])
-
-;
-; MISC INSTRUCTIONS
-;
-
-;
-; NOP
-;
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop")
-; Default to misc type attr.
-
-
-;
-; RPTB
-;
-(define_insn "rptb_top"
- [(use (label_ref (match_operand 0 "" "")))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "*
- return ! final_sequence && c4x_rptb_rpts_p (insn, operands[0])
- ? \"rpts\\trc\" : \"rptb%#\\t%l1-1\";
- "
- [(set_attr "type" "repeat_top")])
-
-; This pattern needs to be emitted at the start of the loop to
-; say that RS and RE are loaded.
-(define_insn "init_branch_on_count"
- [(unspec[(match_operand:QI 0 "rc_reg_operand" "v")] 22)
- (clobber (reg:QI 25))
- (clobber (reg:QI 26))]
- ""
- ""
- [(set_attr "type" "repeat")])
-
-; The RS (25) and RE (26) registers must be unviolate from the top of the loop
-; to here.
-(define_insn "rptb_end"
- [(set (pc)
- (if_then_else (ge (match_operand:QI 2 "rc_reg_operand" "0,0,0,0,0")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_operand:QI 0 "rc_reg_operand" "+v,*a,*d,*x*k,*m")
- (plus:QI (match_dup 0)
- (const_int -1)))
- (use (reg:QI 25))
- (use (reg:QI 26))
- (clobber (reg:CC_NOOV 21))]
- ""
- "*
- if (which_alternative == 0)
- return c4x_rptb_nop_p (insn) ? \"nop\" : \"\";
- else if (which_alternative == 1)
- return \"dbu%#\\t%0,%l1\";
- else if (which_alternative == 2)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn);
- else if (which_alternative == 3)
- return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn);
- else
- return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn);
- "
- [(set_attr "type" "repeat,db,jmpc,jmpc,jmpc")])
-
-
-(define_expand "decrement_and_branch_on_count"
- [(parallel [(set (pc)
- (if_then_else (ge (match_operand:QI 0 "rc_reg_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0)
- (const_int -1)))
- (use (reg:QI 25))
- (use (reg:QI 26))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "")
-
-
-(define_expand "movstrqi_small2"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" ""))
- (mem:BLK (match_operand:BLK 1 "src_operand" "")))
- (use (match_operand:QI 2 "immediate_operand" ""))
- (use (match_operand:QI 3 "immediate_operand" ""))
- (clobber (match_operand:QI 4 "ext_low_reg_operand" ""))])]
- ""
- "
- {
- rtx src, dst, tmp;
- rtx src_mem, dst_mem;
- int len;
- int i;
-
- dst = operands[0];
- src = operands[1];
- len = INTVAL (operands[2]);
- tmp = operands[4];
-
- src_mem = gen_rtx_MEM (QImode, src);
- dst_mem = gen_rtx_MEM (QImode, dst);
-
- emit_insn (gen_movqi (tmp, src_mem));
- emit_insn (gen_addqi3_noclobber (src, src, const1_rtx));
- for (i = 1; i < len; i++)
- {
- emit_insn (gen_movqi_parallel (tmp, src_mem, dst_mem, tmp));
- emit_insn (gen_addqi3_noclobber (src, src, const1_rtx));
- emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx));
- }
- emit_insn (gen_movqi (dst_mem, tmp));
- emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx));
- DONE;
- }
- ")
-
-
-;
-; BLOCK MOVE
-; We should probably get RC loaded when using RPTB automagically...
-; There's probably no need to call _memcpy() if we don't get
-; a immediate operand for the size. We could do a better job here
-; than most memcpy() implementations.
-; operand 2 is the number of bytes
-; operand 3 is the shared alignment
-; operand 4 is a scratch register
-
-(define_insn "movstrqi_small"
- [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a"))
- (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a")))
- (use (match_operand:QI 2 "immediate_operand" "i"))
- (use (match_operand:QI 3 "immediate_operand" ""))
- (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))]
- ""
- "*
- {
- int i;
- int len = INTVAL (operands[2]);
- int first = 1;
-
- for (i = 0; i < len; i++)
- {
- if (first)
- output_asm_insn (\"ldiu\\t*%1++,%4\", operands);
- else
- output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
- output_asm_insn (\"sti\\t%4,*%0++\", operands);
- first = 0;
- }
- return \"\";
- }
- "
- [(set_attr "type" "multi")])
-
-(define_insn "movstrqi_large"
- [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a"))
- (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a")))
- (use (match_operand:QI 2 "immediate_operand" "i"))
- (use (match_operand:QI 3 "immediate_operand" ""))
- (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
- (clobber (reg:QI 25))
- (clobber (reg:QI 26))
- (clobber (reg:QI 27))]
- ""
- "*
- {
- int len = INTVAL (operands[2]);
-
- output_asm_insn (\"ldiu\\t*%1++,%4\", operands);
- if (TARGET_RPTS_CYCLES (len))
- {
- output_asm_insn (\"rpts\\t%2-2\", operands);
- output_asm_insn (\"sti\\t%4,*%0++\", operands);
- output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
- return \"sti\\t%4,*%0++\";
- }
- else
- {
- output_asm_insn (\"ldiu\\t%2-2,rc\", operands);
- output_asm_insn (\"rptb\\t$+1\", operands);
- output_asm_insn (\"sti\\t%4,*%0++\", operands);
- output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
-
- return \"sti\\t%4,*%0++\";
- }
- }
- "
- [(set_attr "type" "multi")])
-
-; Operand 2 is the count, operand 3 is the alignment.
-(define_expand "movstrqi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" ""))
- (mem:BLK (match_operand:BLK 1 "src_operand" "")))
- (use (match_operand:QI 2 "immediate_operand" ""))
- (use (match_operand:QI 3 "immediate_operand" ""))])]
- ""
- "
- {
- rtx tmp;
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 32767
- || INTVAL (operands[2]) <= 0)
- {
- FAIL; /* Try to call _memcpy */
- }
-
- operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- tmp = gen_reg_rtx (QImode);
- if (INTVAL (operands[2]) < 8)
- emit_insn (gen_movstrqi_small (operands[0], operands[1], operands[2],
- operands[3], tmp));
- else
- {
- emit_insn (gen_movstrqi_large (operands[0], operands[1], operands[2],
- operands[3], tmp));
- }
- DONE;
- }")
-
-
-(define_insn "*cmpstrqi"
- [(set (match_operand:QI 0 "reg_operand" "=d")
- (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))
- (mem:BLK (match_operand:QI 2 "addr_reg_operand" "a"))))
- (use (match_operand:QI 3 "immediate_operand" "i"))
- (use (match_operand:QI 4 "immediate_operand" ""))
- (clobber (match_operand:QI 5 "std_reg_operand" "=&c"))
- (clobber (reg:QI 21))]
- ""
- "*
- {
- output_asm_insn (\"ldi\\t%3-1,%5\", operands);
- output_asm_insn (\"$1:\tsubi3\\t*%1++,*%2++,%0\", operands);
- output_asm_insn (\"dbeq\\t%5,$1\", operands);
- return \"\";
- }")
-
-(define_expand "cmpstrqi"
- [(parallel [(set (match_operand:QI 0 "reg_operand" "")
- (compare:QI (match_operand:BLK 1 "general_operand" "")
- (match_operand:BLK 2 "general_operand" "")))
- (use (match_operand:QI 3 "immediate_operand" ""))
- (use (match_operand:QI 4 "immediate_operand" ""))
- (clobber (match_dup 5))
- (clobber (reg:QI 21))])]
- ""
- "
-{
- if (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 32767
- || INTVAL (operands[3]) <= 0)
- {
- FAIL;
- }
- operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- operands[2] = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
- operands[5] = gen_reg_rtx (QImode);
-}")
-
-;
-; TWO OPERAND LONG DOUBLE INSTRUCTIONS
-;
-
-(define_expand "movhf"
- [(set (match_operand:HF 0 "src_operand" "")
- (match_operand:HF 1 "src_operand" ""))]
- ""
- "if (CONSTANT_P (operands[1]))
- {
- operands[1] = force_const_mem (HFmode, operands[1]);
- if (! memory_address_p (HFmode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], HFmode,
- XEXP (operands[1], 0));
- }
-
- /* Memory to memory copies must go through a register. */
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM
- && ! reload_in_progress)
- operands[1] = force_reg (HFmode, operands[1]);
-")
-
-(define_insn "*movhf_noclobber_reg"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (match_operand:HF 1 "reg_operand" "h"))]
- ""
- "ldfu\\t%1,%0"
- [(set_attr "type" "unary")])
-
-; The predicates could be tightened to disallow constants
-(define_insn "*movhf_noclobber"
- [(set (match_operand:HF 0 "src_operand" "=h,m")
- (match_operand:HF 1 "src_operand" "m,h"))]
- "reg_operand (operands[0], HFmode) ^ reg_operand (operands[1], HFmode)"
- "#"
- [(set_attr "type" "multi,multi")])
-
-(define_insn "*movhf_test"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HF 1 "reg_operand" "h")
- (const_int 0)))
- (clobber (match_scratch:HF 0 "=h"))]
- ""
- "ldf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*movhf_set"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HF 1 "reg_operand" "h")
- (match_operand:HF 2 "fp_zero_operand" "G")))
- (set (match_operand:HF 0 "reg_operand" "=h")
- (match_dup 1))]
- ""
- "ldf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_split
- [(set (match_operand:HF 0 "reg_operand" "")
- (match_operand:HF 1 "memory_operand" ""))]
- "reload_completed"
- [(set (match_dup 0) (float_extend:HF (match_dup 2)))
- (set (match_dup 0) (unspec[(subreg:QI (match_dup 0) 0) (match_dup 3)] 8))]
- "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode);
- operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode);
- PUT_MODE (operands[2], QFmode);
- PUT_MODE (operands[3], QImode);")
-
-(define_split
- [(set (match_operand:HF 0 "reg_operand" "")
- (match_operand:HF 1 "const_operand" ""))]
- "reload_completed && 0"
- [(set (match_dup 0) (float_extend:HF (match_dup 2)))
- (set (match_dup 0) (unspec[(subreg:QI (match_dup 0) 0) (match_dup 3)] 8))]
- "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode);
- operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode);
- PUT_MODE (operands[2], QFmode);
- PUT_MODE (operands[3], QImode);")
-
-(define_split
- [(set (match_operand:HF 0 "memory_operand" "")
- (match_operand:HF 1 "reg_operand" ""))]
- "reload_completed"
- [(set (match_dup 2) (float_truncate:QF (match_dup 1)))
- (set (match_dup 3) (unspec [(match_dup 1)] 9))]
- "operands[2] = c4x_operand_subword (operands[0], 0, 1, HFmode);
- operands[3] = c4x_operand_subword (operands[0], 1, 1, HFmode);
- PUT_MODE (operands[2], QFmode);
- PUT_MODE (operands[3], QImode);")
-
-(define_insn "*loadhf_float"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (float_extend:HF (match_operand:QF 1 "src_operand" "fmH")))]
- ""
- "@
- ldfu\\t%1,%0"
- [(set_attr "type" "unary")])
-
-(define_insn "*loadhf_int"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (unspec[(subreg:QI (match_dup 0) 0)
- (match_operand:QI 1 "src_operand" "g")] 8))]
- ""
- "@
- ldiu\\t%1,%0"
- [(set_attr "type" "unary")])
-
-(define_insn "*storehf_float"
- [(set (match_operand:QF 0 "memory_operand" "=m")
- (float_truncate:QF (match_operand:HF 1 "reg_operand" "h")))]
- ""
- "stf\\t%1,%0"
- [(set_attr "type" "store")])
-
-(define_insn "*storehf_int"
- [(set (match_operand:QI 0 "memory_operand" "=m")
- (unspec [(match_operand:HF 1 "reg_operand" "h")] 9))]
- ""
- "@
- sti\\t%1,%0"
- [(set_attr "type" "store")])
-
-(define_insn "extendqfhf2"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (float_extend:HF (match_operand:QF 1 "reg_operand" "h")))]
- ""
- "ldfu\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "trunchfqf2"
- [(set (match_operand:QF 0 "reg_operand" "=h")
- (float_truncate:QF (match_operand:HF 1 "reg_operand" "0")))
- (clobber (reg:CC 21))]
- ""
- "andn\\t0ffh,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; PUSH/POP
-;
-(define_insn "*pushhf"
- [(set (mem:HF (pre_inc:QI (reg:QI 20)))
- (match_operand:HF 0 "reg_operand" "h"))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (mem:HF (pre_inc:QI (reg:QI 20)))
- (match_operand:HF 0 "reg_operand" ""))]
- "reload_completed"
- [(set (mem:QF (pre_inc:QI (reg:QI 20)))
- (float_truncate:QF (match_dup 0)))
- (set (mem:QI (pre_inc:QI (reg:QI 20)))
- (unspec [(match_dup 0)] 9))]
- "")
-
-(define_insn "pushhf_trunc"
- [(set (mem:QF (pre_inc:QI (reg:QI 20)))
- (float_truncate:QF (match_operand:HF 0 "reg_operand" "h")))]
- ""
- "pushf\\t%0"
- [(set_attr "type" "push")])
-
-(define_insn "pushhf_int"
- [(set (mem:QI (pre_inc:QI (reg:QI 20)))
- (unspec [(match_operand:HF 0 "reg_operand" "h")] 9))]
- ""
- "push\\t%0"
- [(set_attr "type" "push")])
-
-; we can not use this because the popf will destroy the low 8 bits
-;(define_insn "*pophf"
-; [(set (match_operand:HF 0 "reg_operand" "=h")
-; (mem:HF (post_dec:QI (reg:QI 20))))
-; (clobber (reg:CC 21))]
-; ""
-; "#"
-; [(set_attr "type" "multi")])
-
-(define_split
- [(set (match_operand:HF 0 "reg_operand" "")
- (mem:HF (post_dec:QI (reg:QI 20))))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "=h")
- (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20)))))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 0)
- (unspec[(subreg:QI (match_dup 0) 0)
- (mem:QI (post_dec:QI (reg:QI 20)))] 8))
- (clobber (reg:CC 21))])]
- "")
-
-(define_insn "*pophf_int"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (unspec[(subreg:QI (match_dup 0) 0)
- (mem:QI (post_dec:QI (reg:QI 20)))] 8))
- (clobber (reg:CC 21))]
- ""
- "@
- pop\\t%0"
- [(set_attr "type" "pop")])
-
-(define_insn "*pophf_float"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20)))))
- (clobber (reg:CC 21))]
- ""
- "@
- popf\\t%0"
- [(set_attr "type" "unary")])
-
-;
-; FIX
-;
-(define_insn "fixhfqi_clobber"
- [(set (match_operand:QI 0 "reg_operand" "=dc")
- (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH")))
- (clobber (reg:CC 21))]
- ""
- "fix\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; ABSF
-;
-(define_expand "abshf2"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (abs:HF (match_operand:HF 1 "reg_or_const_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
-""
-"")
-
-(define_insn "*abshf2_clobber"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*abshf2_test"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_operand" "h"))
- (match_operand:HF 2 "fp_zero_operand" "G")))
- (clobber (match_scratch:HF 0 "=h"))]
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*abshf2_set"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
- (match_operand:HF 2 "fp_zero_operand" "G")))
- (set (match_operand:HF 0 "reg_operand" "=h")
- (abs:HF (match_dup 1)))]
-
- ""
- "absf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; NEGF
-;
-(define_expand "neghf2"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (neg:HF (match_operand:HF 1 "reg_or_const_operand" "")))
- (clobber (reg:CC 21))])]
-""
-"")
-
-(define_insn "*neghf2_clobber"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")))
- (clobber (reg:CC 21))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*neghf2_test"
- [(set (reg:CC 21)
- (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
- (match_operand:HF 2 "fp_zero_operand" "G")))
- (clobber (match_scratch:HF 0 "=h"))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-(define_insn "*neghf2_set"
- [(set (reg:CC 21)
- (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
- (match_operand:HF 2 "fp_zero_operand" "G")))
- (set (match_operand:HF 0 "reg_operand" "=h")
- (neg:HF (match_dup 1)))]
- ""
- "negf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; RCPF
-;
-(define_insn "*rcpfhf_clobber"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 5))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rcpf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; RSQRF
-;
-(define_insn "*rsqrfhf_clobber"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 10))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rsqrf\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-;
-; RNDF
-;
-(define_insn "*rndhf_clobber"
- [(set (match_operand:HF 0 "reg_operand" "=h")
- (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 6))
- (clobber (reg:CC_NOOV 21))]
- "! TARGET_C3X"
- "rnd\\t%1,%0"
- [(set_attr "type" "unarycc")])
-
-
-; Inlined float square root for C4x
-(define_expand "sqrthf2_inline"
- [(parallel [(set (match_dup 2)
- (unspec [(match_operand:HF 1 "reg_operand" "")] 10))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:HF (match_dup 5) (match_dup 1)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:HF 0 "reg_operand" "")
- (mult:HF (match_dup 2) (match_dup 1)))
- (clobber (reg:CC_NOOV 21))])]
- "! TARGET_C3X"
- "
- operands[2] = gen_reg_rtx (HFmode);
- operands[3] = gen_reg_rtx (HFmode);
- operands[4] = gen_reg_rtx (HFmode);
- operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", HFmode), HFmode);
- operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", HFmode), HFmode);
- ")
-
-
-(define_expand "sqrthf2"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (sqrt:HF (match_operand:HF 1 "reg_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (TARGET_C3X || ! TARGET_INLINE)
- FAIL;
- else
- {
- emit_insn (gen_sqrthf2_inline (operands[0], operands[1]));
- DONE;
- }
- ")
-
-(define_expand "fix_trunchfhi2"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (fix:HI (match_operand:HF 1 "reg_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FIX_TRUNCHFHI2_LIBCALL, FIX, HImode, HFmode, 2, operands);
- DONE;")
-
-(define_expand "fixuns_trunchfhi2"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (unsigned_fix:HI (match_operand:HF 1 "reg_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FIXUNS_TRUNCHFHI2_LIBCALL, UNSIGNED_FIX,
- HImode, HFmode, 2, operands);
- DONE;")
-
-;
-; THREE OPERAND LONG DOUBLE INSTRUCTIONS
-;
-
-;
-; ADDF
-;
-(define_insn "addhf3"
- [(set (match_operand:HF 0 "reg_operand" "=?h,h")
- (plus:HF (match_operand:HF 1 "reg_operand" "%h,0")
- (match_operand:HF 2 "reg_or_const_operand" "h,H")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "@
- addf3\\t%2,%1,%0
- addf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc")])
-
-;
-; SUBF
-;
-(define_insn "subhf3"
- [(set (match_operand:HF 0 "reg_operand" "=?h,h,h")
- (minus:HF (match_operand:HF 1 "reg_or_const_operand" "h,0,H")
- (match_operand:HF 2 "reg_or_const_operand" "h,H,0")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "@
- subf3\\t%2,%1,%0
- subf\\t%2,%0
- subrf\\t%1,%0"
- [(set_attr "type" "binarycc,binarycc,binarycc")])
-
-;
-; MULF
-;
-; The C3x MPYF only uses 24 bit precision while the C4x uses 32 bit precison.
-;
-(define_expand "mulhf3"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "=h")
- (mult:HF (match_operand:HF 1 "reg_operand" "h")
- (match_operand:HF 2 "reg_operand" "h")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "if (TARGET_C3X)
- {
- c4x_emit_libcall3 (MULHF3_LIBCALL, MULT, HFmode, operands);
- DONE;
- }
- ")
-
-(define_insn "*mulhf3_c40"
- [(set (match_operand:HF 0 "reg_operand" "=?h,h")
- (mult:HF (match_operand:HF 1 "reg_operand" "%h,0")
- (match_operand:HF 2 "reg_or_const_operand" "h,hH")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "@
- mpyf3\\t%2,%1,%0
- mpyf\\t%2,%0"
- [(set_attr "type" "binarycc,binarycc")])
-
-;
-; CMPF
-;
-(define_expand "cmphf"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HF 0 "reg_operand" "")
- (match_operand:HF 1 "reg_or_const_operand" "")))]
- ""
- "c4x_compare_op0 = operands[0];
- c4x_compare_op1 = operands[1];
- DONE;")
-
-(define_insn "*cmphf"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HF 0 "reg_operand" "h")
- (match_operand:HF 1 "reg_or_const_operand" "hH")))]
- ""
- "cmpf\\t%1,%0"
- [(set_attr "type" "compare")])
-
-(define_insn "*cmphf_noov"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:HF 0 "reg_operand" "h")
- (match_operand:HF 1 "reg_or_const_operand" "hH")))]
- ""
- "cmpf\\t%1,%0"
- [(set_attr "type" "compare")])
-
-; Inlined float divide for C4x
-(define_expand "divhf3_inline"
- [(parallel [(set (match_dup 3)
- (unspec [(match_operand:HF 2 "reg_operand" "")] 5))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:HF 0 "reg_operand" "")
- (mult:HF (match_operand:HF 1 "reg_operand" "")
- (match_dup 3)))
- (clobber (reg:CC_NOOV 21))])]
- "! TARGET_C3X"
- "
- operands[3] = gen_reg_rtx (HFmode);
- operands[4] = gen_reg_rtx (HFmode);
- operands[5] = CONST2_RTX (HFmode);
- ")
-
-(define_expand "divhf3"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (div:HF (match_operand:HF 1 "reg_operand" "")
- (match_operand:HF 2 "reg_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (TARGET_C3X || ! TARGET_INLINE)
- {
- c4x_emit_libcall3 (DIVHF3_LIBCALL, DIV, HFmode, operands);
- DONE;
- }
- else
- {
- emit_insn (gen_divhf3_inline (operands[0], operands[1], operands[2]));
- DONE;
- }
- ")
-
-
-;
-; TWO OPERAND LONG LONG INSTRUCTIONS
-;
-
-; We could load some constants using define_splits for the C30
-; in the large memory model---these would emit shift and or insns.
-(define_expand "movhi"
- [(set (match_operand:HI 0 "src_operand" "")
- (match_operand:HI 1 "src_operand" ""))]
- ""
- "if (CONSTANT_P (operands[1]))
- {
- /* We don't need to force all constants into memory.
- This could be improved.... */
- operands[1] = force_const_mem (HImode, operands[1]);
- if (! memory_address_p (HImode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], HImode,
- XEXP (operands[1], 0));
- }
-
- /* Memory to memory copies must go through a register. */
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM
- && ! reload_in_progress)
- operands[1] = force_reg (HImode, operands[1]);
-")
-
-; The constraints for movhi must include 'r' if we don't
-; restrict HImode regnos to start on an even number, since
-; we can get RC, R8 allocated as a pair. We want more
-; votes for FP_REGS so we use dr as the constraints.
-(define_insn "*movhi_noclobber"
- [(set (match_operand:HI 0 "src_operand" "=dr,m")
- (match_operand:HI 1 "src_operand" "drm,r"))]
- "reg_operand (operands[0], HImode)
- || reg_operand (operands[1], HImode)"
- "#"
- [(set_attr "type" "multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "src_operand" "")
- (match_operand:HI 1 "src_operand" ""))]
- "reload_completed
- && (reg_operand (operands[0], HImode) || reg_operand (operands[1], HImode))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);")
-
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "reg_operand" "=dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "=?dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- "reload_completed && TARGET_C3X"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 3) (match_dup 2))
- (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 3) (const_int 31)))
- (clobber (reg:CC 21))])]
- "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode);
- operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "=?dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- "reload_completed && ! TARGET_C3X"
- [(set (match_dup 2) (match_dup 1))
- (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 2) (const_int 31)))
- (clobber (reg:CC 21))])]
- "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode);
- operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "reg_operand" "=?dc")
- (zero_extend:HI (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-; If operand0 and operand1 are the same register we don't need
-; the first set.
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "=?dc")
- (zero_extend:HI (match_operand:QI 1 "src_operand" "g")))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 3) (const_int 0))]
- "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode);
- operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
-
-;
-; PUSH/POP
-;
-(define_insn "*pushhi"
- [(set (mem:HI (pre_inc:QI (reg:QI 20)))
- (match_operand:HI 0 "reg_operand" "r"))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (mem:HI (pre_inc:QI (reg:QI 20)))
- (match_operand:HI 0 "reg_operand" ""))]
- "reload_completed"
- [(set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 2))
- (set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 3))]
- "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode);
- operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
-
-(define_insn "*pophi"
- [(set (match_operand:HI 0 "reg_operand" "=r")
- (mem:HI (post_dec:QI (reg:QI 20))))
- (clobber (reg:CC 21))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "")
- (mem:HI (pre_inc:QI (reg:QI 20))))]
- "reload_completed"
- [(set (match_dup 2) (mem:QI (pre_inc:QI (reg:QI 20))))
- (set (match_dup 3) (mem:QI (pre_inc:QI (reg:QI 20))))]
- "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode);
- operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
-
-;
-; NEG
-;
-(define_insn "neghi2"
- [(set (match_operand:HI 0 "ext_reg_operand" "=d")
- (neg:HI (match_operand:HI 1 "src_operand" "rm")))
- (clobber (reg:CC_NOOV 21))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (match_operand:HI 0 "ext_reg_operand" "")
- (neg:HI (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))]
- "reload_completed"
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_dup 3))
- (const_int 0)))
- (set (match_dup 2) (neg:QI (match_dup 3)))])
- (parallel [(set (match_dup 4) (neg:QI (match_dup 5)))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))])]
- "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);")
-
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "reg_operand" "=r")
- (not:HI (match_operand:HI 1 "src_operand" "rm")))
- (clobber (reg:CC 21))]
- ""
- "#"
- [(set_attr "type" "multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "")
- (not:HI (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(parallel [(set (match_dup 2) (not:QI (match_dup 3)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 4) (not:QI (match_dup 5)))
- (clobber (reg:CC 21))])]
- "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);")
-
-(define_expand "floathiqf2"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (float:QF (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FLOATHIQF2_LIBCALL, FLOAT, QFmode, HImode, 2, operands);
- DONE;")
-
-(define_expand "floatunshiqf2"
- [(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (unsigned_float:QF (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FLOATUNSHIQF2_LIBCALL, UNSIGNED_FLOAT,
- QFmode, HImode, 2, operands);
- DONE;")
-
-(define_expand "floathihf2"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (float:HF (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FLOATHIHF2_LIBCALL, FLOAT, HFmode, HImode, 2, operands);
- DONE;")
-
-(define_expand "floatunshihf2"
- [(parallel [(set (match_operand:HF 0 "reg_operand" "")
- (unsigned_float:HF (match_operand:HI 1 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall (FLOATUNSHIHF2_LIBCALL, UNSIGNED_FLOAT,
- HFmode, HImode, 2, operands);
- DONE;")
-
-
-;
-; THREE OPERAND LONG LONG INSTRUCTIONS
-;
-
-(define_expand "addhi3"
- [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "")
- (plus:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (PLUS, operands, HImode);")
-
-(define_insn "*addhi3_clobber"
- [(set (match_operand:HI 0 "ext_reg_operand" "=d,?d,d")
- (plus:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:HI 2 "src_operand" "R,rS<>,rm")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (PLUS, operands, HImode)"
- "#"
- [(set_attr "type" "multi,multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "ext_reg_operand" "")
- (plus:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))]
- "reload_completed"
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QI (match_dup 4) (match_dup 5))
- (const_int 0)))
- (set (match_dup 3) (plus:QI (match_dup 4) (match_dup 5)))])
- (parallel [(set (match_dup 6) (plus:QI (match_dup 7) (match_dup 8)))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))])]
- "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode);
- operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode);
- operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);")
-
-(define_expand "subhi3"
- [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "")
- (minus:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "legitimize_operands (MINUS, operands, HImode);")
-
-
-(define_insn "*subhi3_clobber"
- [(set (match_operand:HI 0 "ext_reg_operand" "=d,?d,d")
- (minus:HI (match_operand:HI 1 "src_operand" "rR,rS<>,0")
- (match_operand:HI 2 "src_operand" "R,rS<>,rm")))
- (clobber (reg:CC_NOOV 21))]
- "valid_operands (MINUS, operands, HImode)"
- "#"
- [(set_attr "type" "multi,multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "ext_reg_operand" "")
- (minus:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC_NOOV 21))]
- "reload_completed"
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_dup 4) (match_dup 5))
- (const_int 0)))
- (set (match_dup 3) (minus:QI (match_dup 4) (match_dup 5)))])
- (parallel [(set (match_dup 6) (minus:QI (match_dup 7) (match_dup 8)))
- (use (reg:CC_NOOV 21))
- (clobber (reg:CC_NOOV 21))])]
- "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode);
- operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode);
- operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);")
-
-(define_expand "iorhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (ior:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (IOR, operands, HImode);")
-
-(define_insn "*iorhi3_clobber"
- [(set (match_operand:HI 0 "reg_operand" "=d,?d,d")
- (ior:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:HI 2 "src_operand" "R,rS<>,rm")))
- (clobber (reg:CC 21))]
- "valid_operands (IOR, operands, HImode)"
- "#"
- [(set_attr "type" "multi,multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "")
- (ior:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(parallel [(set (match_dup 3) (ior:QI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 6) (ior:QI (match_dup 7) (match_dup 8)))
- (clobber (reg:CC 21))])]
- "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode);
- operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode);
- operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);")
-
-(define_expand "andhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (and:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (AND, operands, HImode);")
-
-(define_insn "*andhi3_clobber"
- [(set (match_operand:HI 0 "reg_operand" "=d,?d,d")
- (and:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:HI 2 "src_operand" "R,rS<>,rm")))
- (clobber (reg:CC 21))]
- "valid_operands (AND, operands, HImode)"
- "#"
- [(set_attr "type" "multi,multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "")
- (and:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(parallel [(set (match_dup 3) (and:QI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 6) (and:QI (match_dup 7) (match_dup 8)))
- (clobber (reg:CC 21))])]
- "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode);
- operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode);
- operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);")
-
-(define_expand "xorhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (xor:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "legitimize_operands (AND, operands, HImode);")
-
-
-(define_insn "*xorhi3_clobber"
- [(set (match_operand:HI 0 "reg_operand" "=d,?d,d")
- (xor:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:HI 2 "src_operand" "R,rS<>,rm")))
- (clobber (reg:CC 21))]
- "valid_operands (XOR, operands, HImode)"
- "#"
- [(set_attr "type" "multi,multi,multi")])
-
-(define_split
- [(set (match_operand:HI 0 "reg_operand" "")
- (xor:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))]
- "reload_completed"
- [(parallel [(set (match_dup 3) (xor:QI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 6) (xor:QI (match_dup 7) (match_dup 8)))
- (clobber (reg:CC 21))])]
- "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode);
- operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
- operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode);
- operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode);
- operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode);
- operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);")
-
-; This should do all the dirty work with define_split
-(define_expand "ashlhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (ashift:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32)
- {
- rtx op0hi = operand_subword (operands[0], 1, 0, HImode);
- rtx op0lo = operand_subword (operands[0], 0, 0, HImode);
- rtx op1lo = operand_subword (operands[1], 0, 0, HImode);
- rtx count = GEN_INT ((INTVAL (operands[2]) - 32));
-
- if (INTVAL (count))
- emit_insn (gen_ashlqi3 (op0hi, op1lo, count));
- else
- emit_insn (gen_movqi (op0hi, op1lo));
- emit_insn (gen_movqi (op0lo, const0_rtx));
- DONE;
- }
- emit_insn (gen_ashlhi3_reg (operands[0], operands[1], operands[2]));
- DONE;")
-
-; %0.lo = %1.lo << %2
-; %0.hi = (%1.hi << %2 ) | (%1.lo >> (32 - %2))
-; This algorithm should work for shift counts greater than 32
-(define_expand "ashlhi3_reg"
- [(use (match_operand:HI 1 "src_operand" ""))
- (use (match_operand:HI 0 "reg_operand" ""))
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 7)
- (ashift:QI (match_dup 3)
- (match_operand:QI 2 "reg_operand" "")))
- (clobber (reg:CC 21))])
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 8)
- (ashift:QI (match_dup 4) (match_dup 2)))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 10)
- (plus:QI (match_dup 2) (const_int -32)))
- (clobber (reg:CC_NOOV 21))])
- /* If the shift count is greater than 32 this will do a left shift. */
- (parallel [(set (match_dup 9)
- (lshiftrt:QI (match_dup 3) (neg:QI (match_dup 10))))
- (clobber (reg:CC 21))])
- (set (match_dup 5) (match_dup 7))
- (parallel [(set (match_dup 6)
- (ior:QI (match_dup 8) (match_dup 9)))
- (clobber (reg:CC 21))])]
- ""
- "
- operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */
- operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */
- operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */
- operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */
- operands[7] = gen_reg_rtx (QImode); /* lo << count */
- operands[8] = gen_reg_rtx (QImode); /* hi << count */
- operands[9] = gen_reg_rtx (QImode); /* lo >> (32 - count) */
- operands[10] = gen_reg_rtx (QImode); /* 32 - count */
- ")
-
-; This should do all the dirty work with define_split
-(define_expand "lshrhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (lshiftrt:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32)
- {
- rtx op0hi = operand_subword (operands[0], 1, 0, HImode);
- rtx op0lo = operand_subword (operands[0], 0, 0, HImode);
- rtx op1hi = operand_subword (operands[1], 1, 0, HImode);
- rtx count = GEN_INT ((INTVAL (operands[2]) - 32));
-
- if (INTVAL (count))
- emit_insn (gen_lshrqi3 (op0lo, op1hi, count));
- else
- emit_insn (gen_movqi (op0lo, op1hi));
- emit_insn (gen_movqi (op0hi, const0_rtx));
- DONE;
- }
- emit_insn (gen_lshrhi3_reg (operands[0], operands[1], operands[2]));
- DONE;")
-
-; %0.hi = %1.hi >> %2
-; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2))
-; This algorithm should work for shift counts greater than 32
-(define_expand "lshrhi3_reg"
- [(use (match_operand:HI 1 "src_operand" ""))
- (use (match_operand:HI 0 "reg_operand" ""))
- (parallel [(set (match_dup 11)
- (neg:QI (match_operand:QI 2 "reg_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 7)
- (lshiftrt:QI (match_dup 3)
- (neg:QI (match_dup 11))))
- (clobber (reg:CC 21))])
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 8)
- (lshiftrt:QI (match_dup 4)
- (neg:QI (match_dup 11))))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 10)
- (plus:QI (match_dup 11) (const_int 32)))
- (clobber (reg:CC_NOOV 21))])
- /* If the shift count is greater than 32 this will do an arithmetic
- right shift. However, we need a logical right shift. */
- (parallel [(set (match_dup 9)
- (ashift:QI (match_dup 4) (unspec [(match_dup 10)] 3)))
- (clobber (reg:CC 21))])
- (set (match_dup 6) (match_dup 8))
- (parallel [(set (match_dup 5)
- (ior:QI (match_dup 7) (match_dup 9)))
- (clobber (reg:CC 21))])]
- ""
- "
- operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */
- operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */
- operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */
- operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */
- operands[7] = gen_reg_rtx (QImode); /* lo >> count */
- operands[8] = gen_reg_rtx (QImode); /* hi >> count */
- operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */
- operands[10] = gen_reg_rtx (QImode); /* 32 - count */
- operands[11] = gen_reg_rtx (QImode); /* -count */
- ")
-
-; This should do all the dirty work with define_split
-(define_expand "ashrhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (ashiftrt:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:QI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32)
- {
- rtx op0hi = operand_subword (operands[0], 1, 0, HImode);
- rtx op0lo = operand_subword (operands[0], 0, 0, HImode);
- rtx op1hi = operand_subword (operands[1], 1, 0, HImode);
- rtx count = GEN_INT ((INTVAL (operands[2]) - 32));
-
- if (INTVAL (count))
- emit_insn (gen_ashrqi3 (op0lo, op1hi, count));
- else
- emit_insn (gen_movqi (op0lo, op1hi));
- emit_insn (gen_ashrqi3 (op0hi, op1hi, GEN_INT (31)));
- DONE;
- }
- emit_insn (gen_ashrhi3_reg (operands[0], operands[1], operands[2]));
- DONE;")
-
-; %0.hi = %1.hi >> %2
-; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2))
-; This algorithm should work for shift counts greater than 32
-(define_expand "ashrhi3_reg"
- [(use (match_operand:HI 1 "src_operand" ""))
- (use (match_operand:HI 0 "reg_operand" ""))
- (parallel [(set (match_dup 11)
- (neg:QI (match_operand:QI 2 "reg_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 7)
- (lshiftrt:QI (match_dup 3)
- (neg:QI (match_dup 11))))
- (clobber (reg:CC 21))])
- /* If the shift count is greater than 32 this will give zero. */
- (parallel [(set (match_dup 8)
- (ashiftrt:QI (match_dup 4)
- (neg:QI (match_dup 11))))
- (clobber (reg:CC 21))])
- (parallel [(set (match_dup 10)
- (plus:QI (match_dup 11) (const_int 32)))
- (clobber (reg:CC_NOOV 21))])
- /* If the shift count is greater than 32 this will do an arithmetic
- right shift. */
- (parallel [(set (match_dup 9)
- (ashift:QI (match_dup 4) (match_dup 10)))
- (clobber (reg:CC 21))])
- (set (match_dup 6) (match_dup 8))
- (parallel [(set (match_dup 5)
- (ior:QI (match_dup 7) (match_dup 9)))
- (clobber (reg:CC 21))])]
- ""
- "
- operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */
- operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */
- operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */
- operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */
- operands[7] = gen_reg_rtx (QImode); /* lo >> count */
- operands[8] = gen_reg_rtx (QImode); /* hi >> count */
- operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */
- operands[10] = gen_reg_rtx (QImode); /* 32 - count */
- operands[11] = gen_reg_rtx (QImode); /* -count */
- ")
-
-(define_expand "cmphi"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HI 0 "src_operand" "")
- (match_operand:HI 1 "src_operand" "")))]
- ""
- "legitimize_operands (COMPARE, operands, HImode);
- c4x_compare_op0 = operands[0];
- c4x_compare_op1 = operands[1];
- DONE;")
-
-; This works only before reload because we need 2 extra registers.
-; Use unspec to avoid recursive split.
-(define_split
- [(set (reg:CC 21)
- (compare:CC (match_operand:HI 0 "src_operand" "")
- (match_operand:HI 1 "src_operand" "")))]
- "! reload_completed"
- [(parallel [(set (reg:CC 21)
- (unspec [(compare:CC (match_dup 0)
- (match_dup 1))] 4))
- (clobber (match_scratch:QI 2 ""))
- (clobber (match_scratch:QI 3 ""))])]
- "")
-
-(define_split
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:HI 0 "src_operand" "")
- (match_operand:HI 1 "src_operand" "")))]
- "! reload_completed"
- [(parallel [(set (reg:CC_NOOV 21)
- (unspec [(compare:CC_NOOV (match_dup 0)
- (match_dup 1))] 4))
- (clobber (match_scratch:QI 2 ""))
- (clobber (match_scratch:QI 3 ""))])]
- "")
-
-; This is normally not used. The define splits above are used first.
-(define_insn "*cmphi"
- [(set (reg:CC 21)
- (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>")
- (match_operand:HI 1 "src_operand" "R,rS<>")))]
- "valid_operands (COMPARE, operands, HImode)"
- "*
- {
- int use_ir1 = (reg_operand (operands[0], HImode)
- && REG_P (operands[0])
- && REGNO (operands[0]) == IR1_REGNO)
- || (reg_operand (operands[1], HImode)
- && REG_P (operands[1])
- && REGNO (operands[1]) == IR1_REGNO);
-
- if (use_ir1)
- output_asm_insn (\"push\\tir1\", operands);
- else
- output_asm_insn (\"push\\tbk\", operands);
- output_asm_insn (\"push\\tr0\", operands);
- output_asm_insn (\"subi3\\t%1,%0,r0\", operands);
- if (use_ir1)
- {
- output_asm_insn (\"ldiu\\tst,ir1\", operands);
- output_asm_insn (\"or\\t07bh,ir1\", operands);
- }
- else
- {
- output_asm_insn (\"ldiu\\tst,bk\", operands);
- output_asm_insn (\"or\\t07bh,bk\", operands);
- }
- output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands);
- if (use_ir1)
- output_asm_insn (\"and3\\tir1,st,ir1\", operands);
- else
- output_asm_insn (\"and3\\tbk,st,bk\", operands);
- output_asm_insn (\"pop\\tr0\", operands);
- if (use_ir1)
- {
- output_asm_insn (\"ldiu\\tir1,st\", operands);
- output_asm_insn (\"pop\\tir1\", operands);
- }
- else
- {
- output_asm_insn (\"ldiu\\tbk,st\", operands);
- output_asm_insn (\"pop\\tbk\", operands);
- }
- return \"\";
- }"
- [(set_attr "type" "multi")])
-
-(define_insn "*cmphi_noov"
- [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>")
- (match_operand:HI 1 "src_operand" "R,rS<>")))]
- "valid_operands (COMPARE, operands, HImode)"
- "*
- {
- int use_ir1 = (reg_operand (operands[0], HImode)
- && REG_P (operands[0])
- && REGNO (operands[0]) == IR1_REGNO)
- || (reg_operand (operands[1], HImode)
- && REG_P (operands[1])
- && REGNO (operands[1]) == IR1_REGNO);
-
- if (use_ir1)
- output_asm_insn (\"push\\tir1\", operands);
- else
- output_asm_insn (\"push\\tbk\", operands);
- output_asm_insn (\"push\\tr0\", operands);
- output_asm_insn (\"subi3\\t%1,%0,r0\", operands);
- if (use_ir1)
- {
- output_asm_insn (\"ldiu\\tst,ir1\", operands);
- output_asm_insn (\"or\\t07bh,ir1\", operands);
- }
- else
- {
- output_asm_insn (\"ldiu\\tst,bk\", operands);
- output_asm_insn (\"or\\t07bh,bk\", operands);
- }
- output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands);
- if (use_ir1)
- output_asm_insn (\"and3\\tir1,st,ir1\", operands);
- else
- output_asm_insn (\"and3\\tbk,st,bk\", operands);
- output_asm_insn (\"pop\\tr0\", operands);
- if (use_ir1)
- {
- output_asm_insn (\"ldiu\\tir1,st\", operands);
- output_asm_insn (\"pop\\tir1\", operands);
- }
- else
- {
- output_asm_insn (\"ldiu\\tbk,st\", operands);
- output_asm_insn (\"pop\\tbk\", operands);
- }
- return \"\";
- }"
- [(set_attr "type" "multi")])
-
-
-(define_insn "cmphi_cc"
- [(set (reg:CC 21)
- (unspec [(compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>")
- (match_operand:HI 1 "src_operand" "R,rS<>"))] 4))
- (clobber (match_scratch:QI 2 "=&d,&d"))
- (clobber (match_scratch:QI 3 "=&c,&c"))]
- "valid_operands (COMPARE, operands, HImode)"
- "*
- output_asm_insn (\"subi3\\t%1,%0,%2\", operands);
- output_asm_insn (\"ldiu\\tst,%3\", operands);
- output_asm_insn (\"or\\t07bh,%3\", operands);
- output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands);
- output_asm_insn (\"and\\t%3,st\", operands);
- return \"\";"
- [(set_attr "type" "multi")])
-
-(define_insn "cmphi_cc_noov"
- [(set (reg:CC_NOOV 21)
- (unspec [(compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>")
- (match_operand:HI 1 "src_operand" "R,rS<>"))] 4))
- (clobber (match_scratch:QI 2 "=&d,&d"))
- (clobber (match_scratch:QI 3 "=&c,&c"))]
- "valid_operands (COMPARE, operands, HImode)"
- "*
- output_asm_insn (\"subi3\\t%1,%0,%2\", operands);
- output_asm_insn (\"ldiu\\tst,%3\", operands);
- output_asm_insn (\"or\\t07bh,%3\", operands);
- output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands);
- output_asm_insn (\"and\\t%3,st\", operands);
- return \"\";"
- [(set_attr "type" "multi")])
-
-(define_expand "mulhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (mult:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (MULHI3_LIBCALL, MULT, HImode, operands);
- DONE;")
-
-(define_expand "udivhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (udiv:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (UDIVHI3_LIBCALL, UDIV, HImode, operands);
- DONE;")
-
-(define_expand "divhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (div:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (DIVHI3_LIBCALL, DIV, HImode, operands);
- DONE;")
-
-(define_expand "umodhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (umod:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (UMODHI3_LIBCALL, UMOD, HImode, operands);
- DONE;")
-
-(define_expand "modhi3"
- [(parallel [(set (match_operand:HI 0 "reg_operand" "")
- (mod:HI (match_operand:HI 1 "src_operand" "")
- (match_operand:HI 2 "src_operand" "")))
- (clobber (reg:CC 21))])]
- ""
- "c4x_emit_libcall3 (MODHI3_LIBCALL, MOD, HImode, operands);
- DONE;")
-
-;
-; PEEPHOLES
-;
-
-; dbCC peepholes
-;
-; Turns
-; loop:
-; [ ... ]
-; bCC label ; abnormal loop termination
-; dbu aN, loop ; normal loop termination
-;
-; Into
-; loop:
-; [ ... ]
-; dbCC aN, loop
-; bCC label
-;
-; Which moves the bCC condition outside the inner loop for free.
-;
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ge (plus:QI (match_operand:QI 4 "addr_reg_operand" "0")
- (const_int -1))
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a")
- (plus:QI (match_dup 0)
- (const_int -1)))
- (clobber (reg:CC_NOOV 21))])]
- "! c4x_label_conflict (insn, operands[2], operands[1])"
- "db%I3\\t%0,%l1\\n\\tb%3\\t%l2"
- [(set_attr "type" "multi")])
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "comparison_operator"
- [(reg:CC 21) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:QI 4 "addr_reg_operand" "0")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a")
- (plus:QI (match_dup 0)
- (const_int -1)))
- (clobber (reg:CC_NOOV 21))])]
- "! c4x_label_conflict (insn, operands[2], operands[1])"
- "db%I3\\t%0,%l1\\n\\tb%3\\t%l2"
- [(set_attr "type" "multi")])
-
-;
-; Peepholes to convert 'call label; rets' into jump label
-;
-(define_peephole
- [(parallel [(call (match_operand:QI 0 "call_operand" "T,!o")
- (match_operand:QI 1 "general_operand" ""))
- (clobber (reg:QI 31))])
- (return)]
- "c4x_null_epilogue_p ()"
- "@
- br%#\\t%C0
- bu%#\\t%R0"
- [(set_attr "type" "jump,jump")])
-
-(define_peephole
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "call_operand" "T,!o")
- (match_operand:QI 2 "general_operand" "")))
- (clobber (reg:QI 31))])
- (return)]
- "c4x_null_epilogue_p ()"
- "@
- br%#\\t%C1
- bu%#\\t%R1"
- [(set_attr "type" "jump,jump")])
-
-;
-; Peepholes for parallel instructions
-;
-(define_peephole
- [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (match_operand:QI 1 "par_ind_operand" ""))
- (set (match_operand:QI 2 "ext_low_reg_operand" "")
- (match_operand:QI 3 "par_ind_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[2]))
- && ! c4x_address_conflict (operands[1], operands[3], 0, 0)"
- "ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2")
-
-; load occurs before store if 1 and 2 point to same address
-(define_peephole
- [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (match_operand:QI 1 "par_ind_operand" ""))
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))
- && ! c4x_address_conflict (operands[1], operands[2], 0, 1)"
- "ldi\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-; load occurs before store if 0 and 3 point to same address
-(define_peephole
- [(set (match_operand:QI 0 "par_ind_operand" "")
- (match_operand:QI 1 "ext_low_reg_operand" ""))
- (set (match_operand:QI 2 "ext_low_reg_operand" "")
- (match_operand:QI 3 "par_ind_operand" ""))]
- "(REGNO (operands[1]) != REGNO (operands[2]))
- && ! c4x_address_conflict (operands[0], operands[3], 1, 0)"
- "ldi\\t%3,%2\\n||\\tsti\\t%1,%0")
-
-(define_peephole
- [(set (match_operand:QI 0 "par_ind_operand" "")
- (match_operand:QI 1 "ext_low_reg_operand" ""))
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "! c4x_address_conflict (operands[0], operands[2], 1, 1)"
- "sti\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-; This peephole should be unnecessary with my patches to flow.c
-; for better autoincrement detection
-(define_peephole
- [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (mem:QF (match_operand:QI 1 "addr_reg_operand" "")))
- (set (match_operand:QF 2 "ext_low_reg_operand" "")
- (mem:QF (plus:QI (match_dup 1) (const_int 1))))
- (parallel [(set (match_dup 1) (plus:QI (match_dup 1) (const_int 2)))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "ldf\\t*%1++,%0\\n\\tldf\\t*%1++,%2")
-
-(define_peephole
- [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (match_operand:QF 1 "par_ind_operand" ""))
- (set (match_operand:QF 2 "ext_low_reg_operand" "")
- (match_operand:QF 3 "par_ind_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[2]))
- && ! c4x_address_conflict (operands[1], operands[3], 0, 1)"
- "ldf1\\t%1,%0\\n||\\tldf2\\t%3,%2")
-
-; This peephole should be unnecessary with my patches to flow.c
-; for better autoincrement detection
-(define_peephole
- [(set (mem:QF (match_operand:QI 0 "addr_reg_operand" ""))
- (match_operand:QF 1 "ext_low_reg_operand" ""))
- (set (mem:QF (plus:QI (match_dup 0) (const_int 1)))
- (match_operand:QF 2 "ext_low_reg_operand" ""))
- (parallel [(set (match_dup 0) (plus:QI (match_dup 0) (const_int 2)))
- (clobber (reg:CC_NOOV 21))])]
- ""
- "stf\\t%1,*%0++\\n\\tstf\\t%2,*%0++")
-
-(define_peephole
- [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (match_operand:QF 1 "par_ind_operand" ""))
- (set (match_operand:QF 2 "par_ind_operand" "")
- (match_operand:QF 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "ldf\\t%1,%0\\n||\\tstf\\t%3,%2")
-
-(define_peephole
- [(set (match_operand:QF 0 "par_ind_operand" "")
- (match_operand:QF 1 "ext_low_reg_operand" ""))
- (set (match_operand:QF 2 "ext_low_reg_operand" "")
- (match_operand:QF 3 "par_ind_operand" ""))]
- "! c4x_address_conflict (operands[0], operands[3], 1, 1)"
- "ldf\\t%3,%2\\n||\\tstf\\t%1,%0")
-
-(define_peephole
- [(set (match_operand:QF 0 "par_ind_operand" "")
- (match_operand:QF 1 "ext_low_reg_operand" ""))
- (set (match_operand:QF 2 "par_ind_operand" "")
- (match_operand:QF 3 "ext_low_reg_operand" ""))]
- "! c4x_address_conflict (operands[0], operands[2], 1, 1)"
- "stf1\\t%1,%0\\n||\\tstf2\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QF (match_operand:QF 1 "par_ind_operand" ""))
- (match_operand:QF 2 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (abs:QF (match_dup 1)))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "absf\\t%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (abs:QF (match_operand:QF 1 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QF 2 "par_ind_operand" "")
- (match_operand:QF 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "absf\\t%1,%0\\n||\\tstf\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QI (match_operand:QI 1 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (abs:QI (match_dup 1)))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "absi\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (abs:QI (match_operand:QI 1 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "absi\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (plus:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (plus:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (plus:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (plus:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" ""))
- (match_operand:QF 3 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (plus:QF (match_dup 1) (match_dup 2)))])
- (set (match_operand:QF 4 "par_ind_operand" "")
- (match_operand:QF 5 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[5]))"
- "addf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (plus:QF (match_operand:QF 1 "par_ind_operand" "")
- (match_operand:QF 2 "ext_low_reg_operand" ""))
- (match_operand:QF 3 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (plus:QF (match_dup 1) (match_dup 2)))])
- (set (match_operand:QF 4 "par_ind_operand" "")
- (match_operand:QF 5 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[5]))"
- "addf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (plus:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (plus:QF (match_operand:QF 1 "par_ind_operand" "")
- (match_operand:QF 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (and:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (and:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (and:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (and:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (and:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (and:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ashift:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ashiftrt:QI (match_operand:QI 1 "par_ind_operand" "")
- (neg:QI (match_operand:QI 2 "ext_low_reg_operand" ""))))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (fix:QI (match_operand:QF 1 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (fix:QI (match_dup 1)))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "fix\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (fix:QI (match_operand:QF 1 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "fix\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (float:QF (match_operand:QI 1 "par_ind_operand" ""))
- (match_operand:QF 2 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (float:QF (match_dup 1)))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "float\\t%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (float:QF (match_operand:QI 1 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QF 2 "par_ind_operand" "")
- (match_operand:QF 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "float\\t%1,%0\\n||\\tstf\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (mult:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (mult:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (mult:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (mult:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" ""))
- (match_operand:QF 3 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (mult:QF (match_dup 1) (match_dup 2)))])
- (set (match_operand:QF 4 "par_ind_operand" "")
- (match_operand:QF 5 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[5]))"
- "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (mult:QF (match_operand:QF 1 "par_ind_operand" "")
- (match_operand:QF 2 "ext_low_reg_operand" ""))
- (match_operand:QF 3 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (mult:QF (match_dup 1) (match_dup 2)))])
- (set (match_operand:QF 4 "par_ind_operand" "")
- (match_operand:QF 5 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[5]))"
- "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (mult:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (mult:QF (match_operand:QF 1 "par_ind_operand" "")
- (match_operand:QF 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QF (match_operand:QF 1 "par_ind_operand" ""))
- (match_operand:QF 2 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (neg:QF (match_dup 1)))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "negf\\t%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (neg:QF (match_operand:QF 1 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QF 2 "par_ind_operand" "")
- (match_operand:QF 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "negf\\t%1,%0\\n||\\tstf\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_operand:QI 1 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (neg:QI (match_dup 1)))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "negi\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (neg:QI (match_operand:QI 1 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "negi\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (not:QI (match_operand:QI 1 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (not:QI (match_dup 1)))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "not\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (not:QI (match_operand:QI 1 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 2 "par_ind_operand" "")
- (match_operand:QI 3 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[3]))"
- "not\\t%1,%0\\n||\\tsti\\t%3,%2")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (ior:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ior:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (ior:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ior:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ior:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (ior:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (minus:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" ""))
- (match_operand:QF 3 "fp_zero_operand" "")))
- (set (match_operand:QF 0 "ext_low_reg_operand" "")
- (minus:QF (match_dup 1) (match_dup 2)))])
- (set (match_operand:QF 4 "par_ind_operand" "")
- (match_operand:QF 5 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[5]))"
- "subf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4")
-
-(define_peephole
- [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "")
- (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "")
- (match_operand:QF 2 "par_ind_operand" "")))
- (clobber (reg:CC_NOOV 21))])
- (set (match_operand:QF 3 "par_ind_operand" "")
- (match_operand:QF 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "subf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (xor:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (xor:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (reg:CC 21)
- (compare:CC (xor:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:QI 0 "ext_low_reg_operand" "")
- (xor:QI (match_dup 1) (match_dup 2)))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (xor:QI (match_operand:QI 1 "ext_low_reg_operand" "")
- (match_operand:QI 2 "par_ind_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-(define_peephole
- [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "")
- (xor:QI (match_operand:QI 1 "par_ind_operand" "")
- (match_operand:QI 2 "ext_low_reg_operand" "")))
- (clobber (reg:CC 21))])
- (set (match_operand:QI 3 "par_ind_operand" "")
- (match_operand:QI 4 "ext_low_reg_operand" ""))]
- "(REGNO (operands[0]) != REGNO (operands[4]))"
- "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3")
-
-
diff --git a/gcc/config/c4x/libgcc.S b/gcc/config/c4x/libgcc.S
deleted file mode 100755
index fb79cf8..0000000
--- a/gcc/config/c4x/libgcc.S
+++ /dev/null
@@ -1,1501 +0,0 @@
-/* libgcc1 routines for the Texas Instruments TMS320C[34]x
- Copyright (C) 1997,98 Free Software Foundation, Inc.
-
- Contributed by Michael Hayes (m.hayes@elec.canterbury.cri.nz)
- and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
-
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file. (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not cause
- the resulting executable to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
-
-
-; These routines are called using the standard TI register argument
-; passing model.
-; The following registers do not have to be saved:
-; r0, r1, r2, r3, ar0, ar1, ar2, ir0, ir1, bk, rs, rc, re, (r9, r10, r11)
-;
-; Perform floating point divqf3
-;
-; This routine performs a reciprocal of the divisor using the method
-; described in the C30/C40 user manuals. It then multiplies that
-; result by the dividend.
-;
-; Let r be the reciprocal of the divisor v and let the ith estimate
-; of r be denoted by r[i]. An iterative approach can be used to
-; improve the estimate of r, given an initial estimate r[0], where
-;
-; r[i + 1] = r[i] * (2.0 - v * r[i])
-;
-; The normalised error e[i] at the ith iteration is
-;
-; e[i] = (r - r[i]) / r = (1 / v - r[i]) * v = (1 - v * r[i])
-;
-; Note that
-;
-; e[i + 1] = (1 - v * r[i + 1]) = 1 - 2 * v * r[i] + v^2 + (r[i])^2
-; = (1 - v * r[i])^2 = (e[i])^2
-
-; r2 dividend, r3 divisor, r0 quotient
-; clobbers r1, ar1
-#ifdef L_divqf3
- .text
- .global ___divqf3
-___divqf3:
-
-#ifdef _TMS320C4x
- .if .REGPARM == 0
- lda sp,ar0
- ldf *-ar0(2), r3
- .endif
-
- pop ar1 ; Pop return address
-
-; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor
- rcpf r3, r0 ; Compute initial estimate r[0]
-
- mpyf3 r0, r3, r1 ; r1 = r[0] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[0] * v
- mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
-; End of 1st iteration (16 bits accuracy)
-
- mpyf3 r0, r3, r1 ; r1 = r[1] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[1] * v
-
- bud ar1 ; Delayed branch
- mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
-; End of 2nd iteration (32 bits accuracy)
- .if .REGPARM == 0
- mpyf *-ar0(1), r0 ; Multiply by the dividend
- .else
- mpyf r2, r0 ; Multiply by the dividend
- .endif
- rnd r0
- ; Branch occurs here
-#else
- .if .REGPARM == 0
- ldiu sp,ar0
- ldf *-ar0(2), r3
- .endif
-
- pop ar1 ; Pop return address
-
-; Initial estimate r[0] = 1.0 * 2^(-e - 1)
-; where v = m * 2^e
-
-; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor
-
-; Calculate initial estimate r[0]
- pushf r3
- pop r0
- not r0 ; r0 = -e
- ; complement exponent = -e -1
- ; complement sign (side effect)
- ; complement mantissa (almost 3 bit accurate)
- push r0
- popf r0 ; r0 = 1.0 * e^(-e - 1) + inverted mantissa
- ldf -1.0, r1 ; undo complement sign bit
- xor r1, r0
-
- mpyf3 r0, r3, r1 ; r1 = r[0] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[0] * v
- mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
-; End of 1st iteration
-
- mpyf3 r0, r3, r1 ; r1 = r[1] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[1] * v
- mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
-; End of 2nd iteration
-
- mpyf3 r0, r3, r1 ; r1 = r[2] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[2] * v
- mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3]
-; End of 3rd iteration
-
- or 080h, r0 ; add 1 lsb to result. needed when complemeting
- ; 1.0 / 2.0
- rnd r0
-
-; Use modified last iteration
-; r[4] = (r[3] * (1.0 - (v * r[3]))) + r[3]
- mpyf3 r0, r3, r1 ; r1 = r[3] * v
- subrf 1.0, r1 ; r1 = 1.0 - r[3] * v
- mpyf r0, r1 ; r1 = r[3] * (1.0 - r[3] * v)
-
- bud ar1 ; Delayed branch
- addf r1, r0 ; r0 = r[3] * (1.0 - r[3] * v) + r[3] = r[4]
- .if .REGPARM == 0
- mpyf *-ar0(1), r0 ; Multiply by the dividend
- .else
- mpyf r2, r0 ; Multiply by the dividend
- .endif
- rnd r0
- ; Branch occurs here
-#endif
-
-#endif
-;
-; Integer signed division
-;
-; ar2 dividend, r2 divisor, r0 quotient
-; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re
-#ifdef L_divqi3
- .text
- .global ___divqi3
- .ref udivqi3n
-___divqi3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
- xor3 ar2, r2, r3 ; Get the sign
- absi ar2, r0
- bvd divq32
- ldi r0, ar2
- absi r2, r2
- cmpi ar2, r2 ; Divisor > dividend?
-
- pop ir1
- bhid zero ; If so, return 0
-
-;
-; Normalize oeprands. Use difference exponents as shift count
-; for divisor, and as repeat count for "subc"
-;
- float ar2, r1 ; Normalize dividend
- pushf r1 ; Get as integer
- pop ar0
- lsh -24, ar0 ; Get exponent
-
- float r2, r1 ; Normalize divisor
- pushf r1 ; Get as integer
- pop ir0
- lsh -24, ir0 ; Get exponent
-
- subi ir0, ar0 ; Get difference of exponents
- lsh ar0, r2 ; Align divisor with dividend
-
-;
-; Do count + 1 subtracts and shifts
-;
- rpts ar0
- subc r2, ar2
-
-;
-; Mask off the lower count+1 bits of ar2
-;
- subri 31, ar0 ; Shift count is (32 - (ar0 + 1))
- lsh ar0, ar2 ; Shift left
- negi ar0, ar0
- lsh3 ar0, ar2, r0 ; Shift right and put result in r0
-
-;
-; Check sign and negate result if necessary
-;
- bud ir1 ; Delayed return
- negi r0, r1 ; Negate result
- ash -31, r3 ; Check sign
- ldinz r1, r0 ; If set, use negative result
- ; Branch occurs here
-
-zero: bud ir1 ; Delayed branch
- ldi 0, r0
- nop
- nop
- ; Branch occurs here
-;
-; special case where ar2 = abs(ar2) = 0x80000000. We handle this by
-; calling unsigned divide and negating the result if necessary.
-;
-divq32:
- push r3 ; Save sign
- call udivqi3n
- pop r3
- pop ir1
- bd ir1
- negi r0, r1 ; Negate result
- ash -31, r3 ; Check sign
- ldinz r1, r0 ; If set, use negative result
- ; Branch occurs here
-#endif
-;
-;
-; ar2 dividend, r2 divisor, r0 quotient,
-; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re
-#ifdef L_udivqi3
- .text
- .global ___udivqi3
- .global udivqi3n
-___udivqi3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
-udivqi3n:
- pop ir1
-
- cmpi ar2, r2 ; If divisor > dividend
- bhi qzero ; return zero
- ldi r2, ar1 ; Store divisor in ar1
-
- tstb ar2, ar2 ; Check top bit, jump if set to special handler
- bld div_32 ; Delayed branch
-
-;
-; Get divisor exponent
-;
- float ar1, r1 ; Normalize the divisor
- pushf r1 ; Get into int register
- pop rc
- ; branch occurs here
-
- bzd qzero ; if (float) divisor zero, return zero
-
- float ar2, r1 ; Normalize the dividend
- pushf r1 ; Get into int register
- pop ar0
- lsh -24, ar0 ; Get both the exponents
- lsh -24, rc
-
- subi rc, ar0 ; Get the difference between the exponents
- lsh ar0, ar1 ; Normalize the divisor with the dividend
-
-;
-; Do count_1 subtracts and shifts
-;
- rpts ar0
- subc ar1, ar2
-
-;
-; mask off the lower count+1 bits
-;
- subri 31, ar0 ; Shift count (31 - (ar0+1))
- bud ir1 ; Delayed return
- lsh3 ar0, ar2, r0
- negi ar0, ar0
- lsh ar0, r0
- ; Branch occurs here
-
-;
-; Handle a full 32-bit dividend
-;
-div_32: tstb ar1, ar1
- bld qone ; if divisor high bit is one, the result is one
- lsh -24, rc
- subri 31, rc
- lsh rc, ar1 ; Line up the divisor
-
-;
-; Now divisor and dividend are aligned. Do first SUBC by hand, save
-; of the forst quotient digit. Then, shift divisor right rather
-; than shifting dividend left. This leaves a zero in the top bit of
-; the divident
-;
- ldi 1, ar0 ; Initizialize MSB of quotient
- lsh rc, ar0 ; create a mask for MSBs
- subi 1, ar0 ; mask is (2 << count) - 1
-
- subi3 ar1, ar2, r1
- ldihs r1, ar2
- ldihs 1, r1
- ldilo 0, r1
- lsh rc, r1
-
- lsh -1, ar1
- subi 1, rc
-;
-; do the rest of the shifts and subtracts
-;
- rpts rc
- subc ar1, ar2
-
- bud ir1
- and ar0, ar2
- or3 r1, ar2, r0
- nop
-
-qone:
- bud ir1
- ldi 1, r0
- nop
- nop
-
-qzero:
- bud ir1
- ldi 0, r0
- nop
- nop
-#endif
-
-#ifdef L_umodqi3
- .text
- .global ___umodqi3
- .global umodqi3n
-___umodqi3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
-umodqi3n:
- pop ir1 ; return address
- cmpi ar2, r2 ; divisor > dividend ?
- bhi uzero ; if so, return dividend
- ldi r2, ar1 ; load divisor
-;
-; If top bit of dividend is set, handle specially.
-;
- tstb ar2, ar2 ; check top bit
- bld umod_32 ; get divisor exponent, then jump.
-;
-; Get divisor exponent by converting to float.
-;
- float ar1, r1 ; normalize divisor
- pushf r1 ; push as float
- pop rc ; pop as int to get exponent
- bzd uzero ; if (float)divisor was zero, return
-;
-; 31 or less bits in dividend. Get dividend exponent.
-;
- float ar2, r1 ; normalize dividend
- pushf r1 ; push as float
- pop ar0 ; pop as int to get exponent
-;
-; Use difference in exponents as shift count to line up MSBs.
-;
- lsh -24, rc ; divisor exponent
- lsh -24, ar0 ; dividend exponent
- subi rc, ar0 ; difference
- lsh ar0, ar1 ; shift divisor up
-;
-; Do COUNT+1 subtract & shifts.
-;
- rpts ar0
- subc ar1, ar2
-;
-; Remainder is in upper 31-COUNT bits.
-;
- bud ir1 ; delayed branch to return
- addi 1, ar0 ; shift count is COUNT+1
- negi ar0, ar0 ; negate for right shift
- lsh3 ar0, ar2, r0 ; shift to get result
- ; Return occurs here
-
-;
-; The following code handles cases of a full 32-bit dividend. Before
-; SUBC can be used, the top bit must be cleared (otherwise SUBC can
-; possibly shift a significant 1 out the top of the dividend). This
-; is accomplished by first doing a normal subtraction, then proceeding
-; with SUBCs.
-;
-umod_32:
-;
-; If the top bit of the divisor is set too, the remainder is simply
-; the difference between the dividend and divisor. Otherwise, shift
-; the divisor up to line up the MSBs.
-;
- tstb ar1, ar1 ; check divisor
- bld uone ; if negative, remainder is diff
-
- lsh -24, rc ; divisor exponent
- subri 31, rc ; shift count = 31 - exp
- negi rc, ar0 ; used later as shift count
- lsh rc, ar1 ; shift up to line up MSBs
-;
-; Now MSBs are aligned. Do first SUBC by hand using a plain subtraction.
-; Then, shift divisor right rather than shifting dividend left. This leaves
-; a 0 in the top bit of the dividend.
-;
- subi3 ar1, ar2, r1 ; subtract
- ldihs r1, ar2 ; if positive, replace dividend
- subi 1, rc ; first iteration is done
- lsh -1, ar1 ; shift divisor down
-;
-; Do EXP subtract & shifts.
-;
- rpts rc
- subc ar1, ar2
-;
-; Quotient is in EXP+1 LSBs; shift remainder (in MSBs) down.
-;
- bud ir1
- lsh3 ar0, ar2, r0 ; COUNT contains -(EXP+1)
- nop
- nop
-;
-; Return (dividend - divisor).
-;
-uone: bud ir1
- subi3 r2, ar2, r0
- nop
- nop
-;
-; Return dividend.
-;
-uzero: bud ir1
- ldi ar2, r0 ; set status from result
- nop
- nop
-#endif
-
-#ifdef L_modqi3
- .text
- .global ___modqi3
- .ref umodqi3n
-___modqi3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
-;
-; Determine sign of result. Get absolute value of operands.
-;
- ldi ar2, ar0 ; sign of result same as dividend
- absi ar2, r0 ; make dividend positive
- bvd mod_32 ; if still negative, escape
- absi r2, r1 ; make divisor positive
- ldi r1, ar1 ; save in ar1
- cmpi r0, ar1 ; divisor > dividend ?
-
- pop ir1 ; return address
- bhid return ; if so, return dividend
-;
-; Normalize operands. Use difference in exponents as shift count
-; for divisor, and as repeat count for SUBC.
-;
- float r1, r1 ; normalize divisor
- pushf r1 ; push as float
- pop rc ; pop as int
- bzd return ; if (float)divisor was zero, return
-
- float r0, r1 ; normalize dividend
- pushf r1 ; push as float
- pop r1 ; pop as int
-
- lsh -24, rc ; get divisor exponent
- lsh -24, r1 ; get dividend exponent
- subi rc, r1 ; get difference in exponents
- lsh r1, ar1 ; align divisor with dividend
-;
-; Do COUNT+1 subtract & shifts.
-;
- rpts r1
- subc ar1, r0
-;
-; Remainder is in upper bits of R0
-;
- addi 1, r1 ; shift count is -(r1+1)
- negi r1, r1
- lsh r1, r0 ; shift right
-;
-; Check sign and negate result if necessary.
-;
-return:
- bud ir1 ; delayed branch to return
- negi r0, r1 ; negate result
- cmpi 0, ar0 ; check sign
- ldin r1, r0 ; if set, use negative result
- ; Return occurs here
-;
-; The following code handles cases of a full 32-bit dividend. This occurs
-; when R0 = abs(R0) = 080000000h. Handle this by calling the unsigned mod
-; function, then negating the result if necessary.
-;
-mod_32:
- push ar0 ; remember sign
- call umodqi3n ; do divide
-
- brd return ; return
- pop ar0 ; restore sign
- pop ir1 ; return address
- nop
-#endif
-
-#ifdef L_unsfltconst
- .section .const
- .global ___unsfltconst
-___unsfltconst: .float 4294967296.0
-#endif
-
-#ifdef L_unsfltcompare
- .section .const
- .global ___unsfltcompare
-___unsfltcompare: .float 2147483648.0
-#endif
-
-; Integer 32-bit signed multiplication
-;
-; The TMS320C3x MPYI instruction takes two 24-bit signed integers
-; and produces a 48-bit signed result which is truncated to 32-bits.
-;
-; A 32-bit by 32-bit multiplication thus requires a number of steps.
-;
-; Consider the product of two 32-bit signed integers,
-;
-; z = x * y
-;
-; where x = (b << 16) + a, y = (d << 16) + c
-;
-; This can be expressed as
-;
-; z = ((b << 16) + a) * ((d << 16) + c)
-;
-; = ((b * d) << 32) + ((b * c + a * d) << 16) + a * c
-;
-; Let z = (f << 16) + e where f < (1 << 16).
-;
-; Since we are only interested in a 32-bit result, we can ignore the
-; (b * d) << 32 term, and thus
-;
-; f = b * c + a * d, e = a * c
-;
-; We can simplify things if we have some a priori knowledge of the
-; operands, for example, if -32768 <= y <= 32767, then y = c and d = 0 and thus
-;
-; f = b * c, e = a * c
-;
-; ar2 multiplier, r2 multiplicand, r0 product
-; clobbers r1, r2, r3
-#ifdef L_mulqi3
- .text
- .global ___mulqi3
-___mulqi3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
- pop ir1 ; return address
- ldi ar2, r0 ;
- and 0ffffh, r0 ; a
- lsh -16, ar2 ; b
- ldi r2, r3 ;
- and 0ffffh, r3 ; c
- mpyi r3, ar2 ; c * b
- lsh -16, r2 ; d
- mpyi r0, r2 ; a * d
- addi ar2, r2 ; c * b + a * d
- bd ir1 ; delayed branch to return
- lsh 16, r2 ; (c * b + a * d) << 16
- mpyi r3, r0 ; a * c
- addi r2, r0 ; a * c + (c * b + a * d) << 16
-; branch occurs here
-
-#endif
-
-;
-; Integer 64 by 64 multiply
-; long1 and long2 on stack
-; result in r0,r1
-;
-#ifdef L_mulhi3
- .text
- .global ___mulhi3
-#ifdef _TMS320C4x
-___mulhi3:
- pop ar0
- ldi sp,ar2
- ldi *-ar2(1),r2
- ldi *-ar2(3),r3
- mpyi3 r2,r3,r0
- mpyuhi3 r2,r3,r1
- mpyi *-ar2(2),r2
- bd ar0
- mpyi *-ar2(0),r3
- addi r2,r1
- addi r3,r1
-#else
-___mulhi3:
- ldi sp,ar2
- ldi -16,rs
- ldi *-ar2(2),ar0
- ldi *-ar2(4),ar1
- ldi ar0,r2
- and 0ffffh,r2
- ldi ar1,r3
- and 0ffffh,r3
- lsh rs,ar0
- lsh rs,ar1
-
- mpyi r2,r3,r0
- mpyi ar0,ar1,r1
- mpyi r2,ar1,rc
- lsh rs,rc,re
- addi re,r1
- lsh 16,rc
- addi rc,r0
- addc 0,r1
- mpyi r3,ar0,rc
- lsh rs,rc,re
- addi re,r1
- lsh 16,rc
- addi rc,r0
- addc 0,r1
-
- ldi *-ar2(1),ar0
- ldi ar0,r2
- and 0ffffh,r2
- lsh rs,ar0
- mpyi r2,r3,rc
- addi rc,r1
- mpyi r2,ar1,rc
- mpyi r3,ar0,re
- addi re,rc
- lsh 16,rc
- addi rc,r1
-
- ldi *-ar2(2),ar0
- ldi *-ar2(3),ar1
- ldi ar0,r2
- and 0ffffh,r2
- ldi ar1,r3
- and 0ffffh,r3
- lsh rs,ar0
- lsh rs,ar1
- mpyi r2,r3,rc
- addi rc,r1
- mpyi r2,ar1,rc
- mpyi r3,ar0,re
- pop ar0
- bd ar0
- addi re,rc
- lsh 16,rc
- addi rc,r1
-#endif
-#endif
-
-;
-; Integer 32 by 32 multiply highpart unsigned
-; src1 in ar2
-; src2 in r2
-; result in r0
-;
-#ifdef L_umulhi3_high
- .text
- .global ___umulhi3_high
-___umulhi3_high:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
- ldi -16,rs
- ldi r2,r3
- and 0ffffh,r2
- ldi ar2,ar1
- and 0ffffh,ar2
- lsh rs,r3
- lsh rs,ar1
-
- mpyi ar2,r2,r1
- mpyi ar1,r3,r0
- mpyi ar2,r3,rc
- lsh rs,rc,re
- addi re,r0
- lsh 16,rc
- addi rc,r1
- addc 0,r0
- mpyi r2,ar1,rc
- lsh rs,rc,re
- addi re,r0
- pop ar0
- bd ar0
- lsh 16,rc
- addi rc,r1
- addc 0,r0
-#endif
-
-;
-; Integer 32 by 32 multiply highpart signed
-; src1 in ar2
-; src2 in r2
-; result in r0
-;
-#ifdef L_smulhi3_high
- .text
- .global ___smulhi3_high
-___smulhi3_high:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- ldi *-ar0(2), r2
- .endif
-
- ldi -16,rs
- ldi 0,rc
- subi3 ar2,rc,r0
- ldi r2,r3
- ldilt r0,rc
- subi3 r2,rc,r0
- ldi ar2,ar1
- tstb ar1,ar1
- ldilt r0,rc
- and 0ffffh,r2
- and 0ffffh,ar2
- lsh rs,r3
- lsh rs,ar1
-
- mpyi ar2,r2,r1
- mpyi ar1,r3,r0
- addi rc,r0
- mpyi ar2,r3,rc
- lsh rs,rc,re
- addi re,r0
- lsh 16,rc
- addi rc,r1
- addc 0,r0
- mpyi r2,ar1,rc
- lsh rs,rc,re
- addi re,r0
- pop ar0
- bd ar0
- lsh 16,rc
- addi rc,r1
- addc 0,r0
-#endif
-
-;
-; Integer 64 by 64 unsigned divide
-; long1 and long2 on stack
-; divide in r0,r1
-; modulo in r2,r3
-; routine takes a maximum of 64*9+21=597 cycles = 24 us @ 50Mhz
-;
-#ifdef L_udivhi3
- .text
- .global ___udivhi3
- .global ___udivide
- .global ___umodulo
- .ref udivqi3n
- .ref umodqi3n
-___udivhi3:
- ldi sp,ar2
- ldi *-ar2(4),ar0
- ldi *-ar2(3),ar1
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
-
-___udivide:
- or r1,ar1,r2
- bne udiv0
- ldi ar0,r2
- ldi r0,ar2
- call udivqi3n
- ldiu 0,r1
- rets
-
-___umodulo:
- or r1,ar1,r2
- bne udiv0
- ldi ar0,r2
- ldi r0,ar2
- call umodqi3n
- ldi r0,r2
- ldiu 0,r3
- rets
-
-udiv0:
- tstb ar1,ar1
- bne udiv1
- tstb ar0,ar0
- bn udiv1
-
- ldiu 63,rc
-#ifdef _TMS320C4x
- rptbd udivend0
- ldiu 0,r2
- addi r0,r0
- rolc r1
-#else
- ldiu 0,r2
- addi r0,r0
- rolc r1
- rptb udivend0
-#endif
-
- rolc r2
- subi3 ar0,r2,r3
- xor 1,st
- ldic r3,r2
- rolc r0
-udivend0:
- rolc r1
-
- ldiu 0,r3
- rets
-udiv1:
- push r4
- push r5
- ldiu 63,rc
- ldiu 0,r2
-#ifdef _TMS320C4x
- rptbd udivend1
- ldiu 0,r3
- addi r0,r0
- rolc r1
-#else
- ldiu 0,r3
- addi r0,r0
- rolc r1
- rptb udivend1
-#endif
-
- rolc r2
- rolc r3
- subi3 ar0,r2,r4
- subb3 ar1,r3,r5
- xor 1,st
- ldic r4,r2
- ldic r5,r3
- rolc r0
-udivend1:
- rolc r1
-
- pop r5
- pop r4
- rets
-#endif
-
-;
-; Integer 64 by 64 unsigned modulo
-; long1 and long2 on stack
-; result in r0,r1
-;
-#ifdef L_umodhi3
- .text
- .global ___umodhi3
- .ref ___modulo
-___umodhi3:
- ldi sp,ar2
- ldi *-ar2(4),ar0
- ldi *-ar2(3),ar1
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
- call ___umodulo
- pop ar0
- bd ar0
- ldi r2,r0
- ldi r3,r1
- nop
-#endif
-
-;
-; Integer 64 by 64 signed divide
-; long1 and long2 on stack
-; result in r0,r1
-;
-#ifdef L_divhi3
- .text
- .global ___divhi3
- .ref ___udivide
-___divhi3:
- ldi 0,ir0
- ldi sp,ar2
- ldi *-ar2(4),r0
- ldi *-ar2(3),r1
- bge div1
- negi ir0
- negi r0
- negb r1
-div1:
- ldi r0,ar0
- ldi r1,ar1
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
- bge div2
- negi ir0
- negi r0
- negb r1
-div2:
- call ___udivide
- tstb ir0,ir0
- bge div3
- negi r0
- negb r1
-div3:
- rets
-#endif
-
-;
-; Integer 64 by 64 signed modulo
-; long1 and long2 on stack
-; result in r0,r1
-;
-#ifdef L_modhi3
- .text
- .global ___modhi3
- .ref ___umodulo
-___modhi3:
- ldi 0,ir0
- ldi sp,ar2
- ldi *-ar2(4),r0
- ldi *-ar2(3),r1
- bge mod1
- negi ir0
- negi r0
- negb r1
-mod1:
- ldi r0,ar0
- ldi r1,ar1
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
- bge mod2
- negi ir0
- negi r0
- negb r1
-mod2:
- call ___umodulo
- ldi r2,r0
- ldi r3,r1
- tstb ir0,ir0
- bge mod3
- negi r0
- negb r1
-mod3:
- rets
-#endif
-
-;
-; double to signed long long converion
-; input in r2
-; result in r0,r1
-;
-#ifdef L_fix_truncqfhi2
- .text
- .global ___fix_truncqfhi2
- .ref ufix_truncqfhi2n
-___fix_truncqfhi2:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(1), r2
- .endif
-
- cmpf 0.0,r2
- bge ufix_truncqfhi2n
- negf r2
- call ufix_truncqfhi2n
- negi r0
- negb r1
- rets
-#endif
-
-;
-; double to unsigned long long converion
-; input in r2
-; result in r0,r1
-;
-#ifdef L_ufix_truncqfhi2
- .text
- .global ___ufix_truncqfhi2
- .global ufix_truncqfhi2n
-___ufix_truncqfhi2:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(1), r2
- .endif
-
-ufix_truncqfhi2n:
- cmpf 0.0,r2
- ble ufix1
- pushf r2
- pop r3
- ash -24,r3
- subi 31,r3
- cmpi 32,r3
- bge ufix1
- cmpi -32,r3
- ble ufix1
- ldi 1,r0
- ash 31,r0
- or3 r0,r2,r0
- ldi r0,r1
- lsh3 r3,r0,r0
- subi 32,r3
- cmpi -32,r3
- ldile 0,r1
- lsh3 r3,r1,r1
- rets
-ufix1:
- ldi 0,r0
- ldi 0,r1
- rets
-#endif
-
-;
-; signed long long to double converion
-; input on stack
-; result in r0
-;
-#ifdef L_floathiqf2
- .text
- .global ___floathiqf2
- .ref ufloathiqf2n
-___floathiqf2:
- ldi sp,ar2
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
- bge ufloathiqf2n
- negi r0
- negb r1
- call ufloathiqf2n
- negf r0
- rets
-#endif
-
-;
-; unsigned long long to double converion
-; input on stack
-; result in r0
-;
-#ifdef L_ufloathiqf2
- .text
- .global ___ufloathiqf2
- .global ufloathiqf2n
- .ref ___unsfltconst
-___ufloathiqf2:
- ldi sp,ar2
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
-ufloathiqf2n:
- .if .BIGMODEL
-#ifdef _TMS320C4x
- ldpk @___unsfltconst
-#else
- ldp @___unsfltconst
-#endif
- .endif
- ldf @___unsfltconst,r2
- float r0
- bge uflt1
- addf r2,r0
-uflt1:
- float r1
- bge uflt2
- addf r2,r1
-uflt2:
-#ifdef _TMS320C4x
- pop r3
- bd r3
- mpyf r2,r1
- addf r1,r0
- nop
-#else
- ldf r1,r3
- and 0ffh,r3
- norm r3,r3
- mpyf r2,r3
- pop ar2
- bd ar2
- addf r3,r0
- mpyf r2,r1
- addf r1,r0
-#endif
-#endif
-
-;
-; long double to signed long long converion
-; input in r2
-; result in r0,r1
-;
-#ifdef L_fix_trunchfhi2
- .text
- .global ___fix_trunchfhi2
- .ref ufix_trunchfhi2n
-___fix_trunchfhi2:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(2), r2
- ldi *-ar0(1), r2
- .endif
-
- cmpf 0.0,r2
- bge ufix_trunchfhi2n
- negf r2
- call ufix_trunchfhi2n
- negi r0
- negb r1
- rets
-#endif
-
-;
-; long double to unsigned long long converion
-; input in r2
-; result in r0,r1
-;
-#ifdef L_ufix_trunchfhi2
- .text
- .global ___ufix_trunchfhi2
- .global ufix_trunchfhi2n
-___ufix_trunchfhi2:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(2), r2
- ldi *-ar0(1), r2
- .endif
-
-ufix_trunchfhi2n:
- cmpf 0.0,r2
- ble ufixh1
- pushf r2
- pop r3
- ash -24,r3
- subi 31,r3
- cmpi 32,r3
- bge ufixh1
- cmpi -32,r3
- ble ufixh1
- ldi 1,r0
- ash 31,r0
- or3 r0,r2,r0
- ldi r0,r1
- lsh3 r3,r0,r0
- subi 32,r3
- cmpi -32,r3
- ldile 0,r1
- lsh3 r3,r1,r1
- rets
-ufixh1:
- ldi 0,r0
- ldi 0,r1
- rets
-#endif
-
-;
-; signed long long to long double converion
-; input on stack
-; result in r0
-;
-#ifdef L_floathihf2
- .text
- .global ___floathihf2
- .ref ufloathihf2n
-___floathihf2:
- ldi sp,ar2
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
- bge ufloathihf2n
- negi r0
- negb r1
- call ufloathihf2n
- negf r0
- rets
-#endif
-
-;
-; unsigned long long to double converion
-; input on stack
-; result in r0
-;
-#ifdef L_ufloathihf2
- .text
- .global ___ufloathihf2
- .global ufloathihf2n
- .ref ___unsfltconst
-___ufloathihf2:
- ldi sp,ar2
- ldi *-ar2(2),r0
- ldi *-ar2(1),r1
-ufloathihf2n
- .if .BIGMODEL
-#ifdef _TMS320C4x
- ldpk @___unsfltconst
-#else
- ldp @___unsfltconst
-#endif
- .endif
- ldf @___unsfltconst,r2
- float r0
- bge uflth1
- addf r2,r0
-uflth1:
- float r1
- bge uflth2
- addf r2,r1
-uflth2:
-#ifdef _TMS320C4x
- pop r3
- bd r3
- mpyf r2,r1
- addf r1,r0
- nop
-#else
- ldf r1,r3
- and 0ffh,r3
- norm r3,r3
- mpyf r2,r3
- pop ar2
- bd ar2
- addf r3,r0
- mpyf r2,r1
- addf r1,r0
-#endif
-#endif
-
-;
-; calculate ffs
-; input in ar2
-; result in r0
-;
-#ifdef L_ffs
- .global ___ffs
- .ref ___unsfltconst
- .text
-___ffs:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldi *-ar0(1), ar2
- .endif
-
- negi ar2,r0
- and ar2,r0
- float r0,r0
- ldfu 0.0,r1
- .if .BIGMODEL
-#ifdef _TMS320C4x
- ldpk @___unsfltconst
-#else
- ldp @___unsfltconst
-#endif
- .endif
- ldflt @___unsfltconst,r1
- addf r1,r0
- pushf r0
- pop r0
- pop ar0
- bd ar0
- ash -24,r0
- ldilt -1,r0
- addi 1,r0
-#endif
-
-;
-; calculate long double * long double
-; input in r2, r3
-; output in r0
-;
-#ifdef L_mulhf3
- .global ___mulhf3
- .text
-___mulhf3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(2), r2
- ldi *-ar0(1), r2
- ldf *-ar0(4), r3
- ldi *-ar0(3), r3
- .endif
-
- pop ar2 ; return ad
- ldf r2,r0 ; copy lsb0
- ldf r3,r1 ; copy lsb1
- and 0ffh,r0 ; mask lsb0
- and 0ffh,r1 ; mask lsb1
- norm r0,r0 ; correct lsb0
- norm r1,r1 ; correct lsb1
- mpyf r2,r1 ; arg0*lsb1
- mpyf r3,r0 ; arg1*lsb0
- bd ar2 ; return (delayed)
- addf r0,r1 ; arg0*lsb1 + arg1*lsb0
- mpyf r2,r3,r0 ; msb0*msb1
- addf r1,r0 ; msb0*msb1 + arg0*lsb1 + arg1*lsb0
-#endif
-
-;
-; calculate long double / long double
-; r2 dividend, r3 divisor, r0 quotient
-;
-#ifdef L_divhf3
- .global ___divhf3
- .text
-___divhf3:
- .if .REGPARM == 0
-#ifdef _TMS320C4x
- lda sp,ar0
-#else
- ldiu sp,ar0
-#endif
- ldf *-ar0(2), r2
- ldi *-ar0(1), r2
- ldf *-ar0(4), r3
- ldi *-ar0(3), r3
- .endif
-
-#ifdef _TMS320C4x
- pop ar1
- rcpf r3, r0
- mpyf3 r0, r3, r1
- subrf 2.0, r1
- mpyf r1, r0
- mpyf3 r0, r3, r1
- bud ar1
- subrf 2.0, r1
- mpyf r1, r0
- mpyf r2, r0
-#else
- pop ar1
- pushf r3
- pop r0
- not r0
- push r0
- popf r0
- ldf -1.0, r1
- xor r1, r0
-
- mpyf3 r0, r3, r1 ; r1 = r[0] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[0] * v
- mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
-; End of 1st iteration
-
- mpyf3 r0, r3, r1 ; r1 = r[1] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[1] * v
- mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
-; End of 2nd iteration
-
- mpyf3 r0, r3, r1 ; r1 = r[2] * v
- subrf 2.0, r1 ; r1 = 2.0 - r[2] * v
- mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3]
-; End of 3rd iteration
-
- or 080h, r0
- rnd r0
-
-; mpyf3 r0, r3, r1 ; r1 = r[3] * v
- push r4
- pushf r4
- mpyf r0, r3, r1
-
- ldf r0, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r3, r4
- addf r4, r1
-
- ldf r3, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r0, r4
- addf r4, r1
-
- subrf 2.0, r1 ; r1 = 2.0 - r[3] * v
-
- mpyf r1, r0, r3 ; r3 = r[3] * (2.0 - r[3] * v) = r[5]
-
- ldf r1, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r0, r4
- addf r4, r3
-
- ldf r0, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r1, r4
- addf r4, r3
-
- mpyf r2, r3, r0 ; Multiply by the dividend
-
- ldf r2, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r3, r4
- addf r4, r0
-
- ldf r3, r4
- and 0ffh, r4
- norm r4, r4
- mpyf r2, r4
- bd ar1
- addf r4, r0
-
- popf r4
- pop r4
-#endif
-#endif
diff --git a/gcc/config/c4x/t-c4x b/gcc/config/c4x/t-c4x
deleted file mode 100755
index 39e316e..0000000
--- a/gcc/config/c4x/t-c4x
+++ /dev/null
@@ -1,22 +0,0 @@
-CROSS_LIBGCC1 = libgcc1-asm.a
-LIB1ASMSRC = c4x/libgcc.S
-LIB1ASMFUNCS = _divqf3 _divqi3 _udivqi3 _umodqi3 _modqi3 _mulqi3 \
- _mulhf3 _divhf3 _unsfltconst _unsfltcompare \
- _mulhi3 _umulhi3_high _smulhi3_high _divhi3 _modhi3 _umodhi3 _udivhi3 \
- _fix_truncqfhi2 _ufix_truncqfhi2 _floathiqf2 _ufloathiqf2 \
- _floathihf2 _ufloathihf2 _fix_trunchfhi2 _ufix_trunchfhi2 _ffs
-
-# We do not have DF or DI types (or SF and SI for that matter),
-# so fake out the libgcc2 compilation.
-LIBGCC2_CFLAGS = -O2 -Dexit=unused_exit $(GCC_CFLAGS) $(LIBGCC2_INCLUDES) -DDF=HF -DDI=HI -DSF=QF -DSI=QI -Dinhibit_libc
-
-MULTILIB_OPTIONS = m30 msmall mmemparm
-MULTILIB_DIRNAMES = c3x small mem
-MULTILIB_MATCHES = m30=mcpu?30 m30=mcpu?31 m30=mcpu?32 m30=m31 m30=m32
-MULTILIB_EXCEPTIONS =
-MULTILIB_EXTRA_OPTS =
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Don't make libgcc1-test since require crt0.o
-LIBGCC1_TEST =
diff --git a/gcc/config/c4x/xm-c4x.h b/gcc/config/c4x/xm-c4x.h
deleted file mode 100755
index dc329eb..0000000
--- a/gcc/config/c4x/xm-c4x.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* #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 32
-#define HOST_BITS_PER_SHORT 32
-#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
-