diff options
Diffstat (limited to 'gcc/config/c4x')
-rwxr-xr-x | gcc/config/c4x/c4x.c | 4341 | ||||
-rwxr-xr-x | gcc/config/c4x/c4x.h | 2671 | ||||
-rwxr-xr-x | gcc/config/c4x/c4x.md | 6877 | ||||
-rwxr-xr-x | gcc/config/c4x/libgcc.S | 1501 | ||||
-rwxr-xr-x | gcc/config/c4x/t-c4x | 22 | ||||
-rwxr-xr-x | gcc/config/c4x/xm-c4x.h | 21 |
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 - |