diff options
author | Dan Albert <danalbert@google.com> | 2015-06-17 11:09:54 -0700 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2015-06-17 14:15:22 -0700 |
commit | f378ebf14df0952eae870c9865bab8326aa8f137 (patch) | |
tree | 31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.7/gcc/config/bfin | |
parent | 2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff) | |
download | toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.gz toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.bz2 toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.zip |
Delete old versions of GCC.
Change-Id: I710f125d905290e1024cbd67f48299861790c66c
Diffstat (limited to 'gcc-4.7/gcc/config/bfin')
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin-modes.def | 28 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin-opts.h | 60 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin-protos.h | 118 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin.c | 5804 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin.h | 1159 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin.md | 4210 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/bfin.opt | 118 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/constraints.md | 225 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/elf.h | 74 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/linux.h | 52 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/predicates.md | 241 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/print-sysroot-suffix.sh | 81 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/rtems.h | 28 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/sync.md | 178 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/t-bfin-elf | 49 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/t-bfin-linux | 52 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/t-bfin-uclinux | 48 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/t-rtems | 6 | ||||
-rw-r--r-- | gcc-4.7/gcc/config/bfin/uclinux.h | 46 |
19 files changed, 0 insertions, 12577 deletions
diff --git a/gcc-4.7/gcc/config/bfin/bfin-modes.def b/gcc-4.7/gcc/config/bfin/bfin-modes.def deleted file mode 100644 index 27459cc13..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin-modes.def +++ /dev/null @@ -1,28 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Blackfin. - Copyright (C) 2005, 2007 Free Software Foundation, Inc. - Contributed by Analog Devices. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -/* PDImode for the 40-bit accumulators. */ -PARTIAL_INT_MODE (DI); - -/* Two of those - covering both accumulators for vector multiplications. */ -VECTOR_MODE (INT, PDI, 2); - -VECTOR_MODE (INT, HI, 2); /* V2HI */ -VECTOR_MODE (INT, SI, 2); /* V2SI - occasionally used. */ diff --git a/gcc-4.7/gcc/config/bfin/bfin-opts.h b/gcc-4.7/gcc/config/bfin/bfin-opts.h deleted file mode 100644 index 329fa1e62..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin-opts.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Definitions for the Blackfin port needed for option handling. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef BFIN_OPTS_H -#define BFIN_OPTS_H - -/* CPU type. */ -typedef enum bfin_cpu_type -{ - BFIN_CPU_UNKNOWN, - BFIN_CPU_BF512, - BFIN_CPU_BF514, - BFIN_CPU_BF516, - BFIN_CPU_BF518, - BFIN_CPU_BF522, - BFIN_CPU_BF523, - BFIN_CPU_BF524, - BFIN_CPU_BF525, - BFIN_CPU_BF526, - BFIN_CPU_BF527, - BFIN_CPU_BF531, - BFIN_CPU_BF532, - BFIN_CPU_BF533, - BFIN_CPU_BF534, - BFIN_CPU_BF536, - BFIN_CPU_BF537, - BFIN_CPU_BF538, - BFIN_CPU_BF539, - BFIN_CPU_BF542, - BFIN_CPU_BF542M, - BFIN_CPU_BF544, - BFIN_CPU_BF544M, - BFIN_CPU_BF547, - BFIN_CPU_BF547M, - BFIN_CPU_BF548, - BFIN_CPU_BF548M, - BFIN_CPU_BF549, - BFIN_CPU_BF549M, - BFIN_CPU_BF561, - BFIN_CPU_BF592 -} bfin_cpu_t; - -#endif diff --git a/gcc-4.7/gcc/config/bfin/bfin-protos.h b/gcc-4.7/gcc/config/bfin/bfin-protos.h deleted file mode 100644 index a76210f59..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin-protos.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Prototypes for Blackfin functions used in the md file & elsewhere. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - - This file is part of GNU CC. - - GNU CC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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 GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -/* Function prototypes that cannot exist in bfin.h due to dependency - complications. */ -#ifndef GCC_BFIN_PROTOS_H -#define GCC_BFIN_PROTOS_H - -/* For the anomaly 05-00-0245 */ -#define WA_SPECULATIVE_LOADS 0x00000001 -#define ENABLE_WA_SPECULATIVE_LOADS \ - (bfin_workarounds & WA_SPECULATIVE_LOADS) - -/* For the anomaly 05-00-0244 */ -#define WA_SPECULATIVE_SYNCS 0x00000002 -#define ENABLE_WA_SPECULATIVE_SYNCS \ - (bfin_workarounds & WA_SPECULATIVE_SYNCS) - -/* For the anomaly 05-00-0371 */ -#define WA_RETS 0x00000004 -#define ENABLE_WA_RETS \ - (bfin_workarounds & WA_RETS) - -/* For the anomaly 05-00-0426 */ -#define WA_INDIRECT_CALLS 0x00000008 -#define ENABLE_WA_INDIRECT_CALLS \ - ((bfin_workarounds & WA_INDIRECT_CALLS) && !TARGET_ICPLB) - -#define WA_05000257 0x00000010 -#define ENABLE_WA_05000257 \ - (bfin_workarounds & WA_05000257) - -#define WA_05000283 0x00000020 -#define ENABLE_WA_05000283 \ - (bfin_workarounds & WA_05000283) - -#define WA_05000315 0x00000040 -#define ENABLE_WA_05000315 \ - (bfin_workarounds & WA_05000315) - -/* For the anomaly 05-00-0312 */ -#define WA_LOAD_LCREGS 0x00000080 -#define ENABLE_WA_LOAD_LCREGS \ - (bfin_workarounds & WA_LOAD_LCREGS) - -#define WA_05000074 0x00000100 -#define ENABLE_WA_05000074 \ - (bfin_workarounds & WA_05000074) - -extern bool function_arg_regno_p (int); - -extern const char *output_load_immediate (rtx *); -extern const char *output_casesi_internal (rtx *); -extern char *bfin_asm_long (void); -extern char *bfin_asm_short (void); -extern int log2constp (unsigned HOST_WIDE_INT); - -extern int hard_regno_mode_ok (int, enum machine_mode); -extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx); -extern HOST_WIDE_INT bfin_initial_elimination_offset (int, int); - -extern int effective_address_32bit_p (rtx, enum machine_mode); -extern int symbolic_reference_mentioned_p (rtx); -extern rtx bfin_gen_compare (rtx, enum machine_mode); -extern bool expand_move (rtx *, enum machine_mode); -extern void bfin_expand_call (rtx, rtx, rtx, rtx, int); -extern bool bfin_longcall_p (rtx, int); -extern bool bfin_dsp_memref_p (rtx); -extern bool bfin_expand_movmem (rtx, rtx, rtx, rtx); - -extern enum reg_class secondary_input_reload_class (enum reg_class, - enum machine_mode, - rtx); -extern enum reg_class secondary_output_reload_class (enum reg_class, - enum machine_mode, - rtx); -extern char *section_asm_op_1 (SECT_ENUM_T); -extern char *section_asm_op (SECT_ENUM_T); -extern void print_operand (FILE *, rtx, char); -extern void print_address_operand (FILE *, rtx); -extern void split_di (rtx [], int, rtx [], rtx []); -extern int split_load_immediate (rtx []); -extern void emit_pic_move (rtx *, enum machine_mode); -extern void asm_conditional_branch (rtx, rtx *, int, int); -extern rtx bfin_gen_compare (rtx, enum machine_mode); - -extern unsigned bfin_local_alignment (tree, unsigned); -extern rtx bfin_va_arg (tree, tree); - -extern void bfin_expand_prologue (void); -extern void bfin_expand_epilogue (int, int, bool); -extern int push_multiple_operation (rtx, enum machine_mode); -extern int pop_multiple_operation (rtx, enum machine_mode); -extern void output_push_multiple (rtx, rtx *); -extern void output_pop_multiple (rtx, rtx *); -extern int bfin_hard_regno_rename_ok (unsigned int, unsigned int); -extern rtx bfin_return_addr_rtx (int); -extern void bfin_hardware_loop (void); - -#endif - diff --git a/gcc-4.7/gcc/config/bfin/bfin.c b/gcc-4.7/gcc/config/bfin/bfin.c deleted file mode 100644 index 28ec6ef0b..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin.c +++ /dev/null @@ -1,5804 +0,0 @@ -/* The Blackfin code generation auxiliary output file. - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - Contributed by Analog Devices. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "insn-config.h" -#include "insn-codes.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "tree.h" -#include "flags.h" -#include "except.h" -#include "function.h" -#include "input.h" -#include "target.h" -#include "target-def.h" -#include "expr.h" -#include "diagnostic-core.h" -#include "recog.h" -#include "optabs.h" -#include "ggc.h" -#include "integrate.h" -#include "cgraph.h" -#include "langhooks.h" -#include "bfin-protos.h" -#include "tm-preds.h" -#include "tm-constrs.h" -#include "gt-bfin.h" -#include "basic-block.h" -#include "cfglayout.h" -#include "timevar.h" -#include "df.h" -#include "sel-sched.h" -#include "hw-doloop.h" -#include "opts.h" - -/* A C structure for machine-specific, per-function data. - This is added to the cfun structure. */ -struct GTY(()) machine_function -{ - /* Set if we are notified by the doloop pass that a hardware loop - was created. */ - int has_hardware_loops; - - /* Set if we create a memcpy pattern that uses loop registers. */ - int has_loopreg_clobber; -}; - -/* RTX for condition code flag register and RETS register */ -extern GTY(()) rtx bfin_cc_rtx; -extern GTY(()) rtx bfin_rets_rtx; -rtx bfin_cc_rtx, bfin_rets_rtx; - -int max_arg_registers = 0; - -/* Arrays used when emitting register names. */ -const char *short_reg_names[] = SHORT_REGISTER_NAMES; -const char *high_reg_names[] = HIGH_REGISTER_NAMES; -const char *dregs_pair_names[] = DREGS_PAIR_NAMES; -const char *byte_reg_names[] = BYTE_REGISTER_NAMES; - -static int arg_regs[] = FUNCTION_ARG_REGISTERS; -static int ret_regs[] = FUNCTION_RETURN_REGISTERS; - -int splitting_for_sched, splitting_loops; - -static void -bfin_globalize_label (FILE *stream, const char *name) -{ - fputs (".global ", stream); - assemble_name (stream, name); - fputc (';',stream); - fputc ('\n',stream); -} - -static void -output_file_start (void) -{ - FILE *file = asm_out_file; - int i; - - fprintf (file, ".file \"%s\";\n", input_filename); - - for (i = 0; arg_regs[i] >= 0; i++) - ; - max_arg_registers = i; /* how many arg reg used */ -} - -/* Examine machine-dependent attributes of function type FUNTYPE and return its - type. See the definition of E_FUNKIND. */ - -static e_funkind -funkind (const_tree funtype) -{ - tree attrs = TYPE_ATTRIBUTES (funtype); - if (lookup_attribute ("interrupt_handler", attrs)) - return INTERRUPT_HANDLER; - else if (lookup_attribute ("exception_handler", attrs)) - return EXCPT_HANDLER; - else if (lookup_attribute ("nmi_handler", attrs)) - return NMI_HANDLER; - else - return SUBROUTINE; -} - -/* Legitimize PIC addresses. If the address is already position-independent, - we return ORIG. Newly generated position-independent addresses go into a - reg. This is REG if nonzero, otherwise we allocate register(s) as - necessary. PICREG is the register holding the pointer to the PIC offset - table. */ - -static rtx -legitimize_pic_address (rtx orig, rtx reg, rtx picreg) -{ - rtx addr = orig; - rtx new_rtx = orig; - - if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) - { - int unspec; - rtx tmp; - - if (TARGET_ID_SHARED_LIBRARY) - unspec = UNSPEC_MOVE_PIC; - else if (GET_CODE (addr) == SYMBOL_REF - && SYMBOL_REF_FUNCTION_P (addr)) - unspec = UNSPEC_FUNCDESC_GOT17M4; - else - unspec = UNSPEC_MOVE_FDPIC; - - if (reg == 0) - { - gcc_assert (can_create_pseudo_p ()); - reg = gen_reg_rtx (Pmode); - } - - tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec); - new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp)); - - emit_move_insn (reg, new_rtx); - if (picreg == pic_offset_table_rtx) - crtl->uses_pic_offset_table = 1; - return reg; - } - - else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) - { - rtx base; - - if (GET_CODE (addr) == CONST) - { - addr = XEXP (addr, 0); - gcc_assert (GET_CODE (addr) == PLUS); - } - - if (XEXP (addr, 0) == picreg) - return orig; - - if (reg == 0) - { - gcc_assert (can_create_pseudo_p ()); - reg = gen_reg_rtx (Pmode); - } - - base = legitimize_pic_address (XEXP (addr, 0), reg, picreg); - addr = legitimize_pic_address (XEXP (addr, 1), - base == reg ? NULL_RTX : reg, - picreg); - - if (GET_CODE (addr) == CONST_INT) - { - gcc_assert (! reload_in_progress && ! reload_completed); - addr = force_reg (Pmode, addr); - } - - if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1))) - { - base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0)); - addr = XEXP (addr, 1); - } - - return gen_rtx_PLUS (Pmode, base, addr); - } - - return new_rtx; -} - -/* Stack frame layout. */ - -/* For a given REGNO, determine whether it must be saved in the function - prologue. IS_INTHANDLER specifies whether we're generating a normal - prologue or an interrupt/exception one. */ -static bool -must_save_p (bool is_inthandler, unsigned regno) -{ - if (D_REGNO_P (regno)) - { - bool is_eh_return_reg = false; - if (crtl->calls_eh_return) - { - unsigned j; - for (j = 0; ; j++) - { - unsigned test = EH_RETURN_DATA_REGNO (j); - if (test == INVALID_REGNUM) - break; - if (test == regno) - is_eh_return_reg = true; - } - } - - return (is_eh_return_reg - || (df_regs_ever_live_p (regno) - && !fixed_regs[regno] - && (is_inthandler || !call_used_regs[regno]))); - } - else if (P_REGNO_P (regno)) - { - return ((df_regs_ever_live_p (regno) - && !fixed_regs[regno] - && (is_inthandler || !call_used_regs[regno])) - || (is_inthandler - && (ENABLE_WA_05000283 || ENABLE_WA_05000315) - && regno == REG_P5) - || (!TARGET_FDPIC - && regno == PIC_OFFSET_TABLE_REGNUM - && (crtl->uses_pic_offset_table - || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf)))); - } - else - return ((is_inthandler || !call_used_regs[regno]) - && (df_regs_ever_live_p (regno) - || (!leaf_function_p () && call_used_regs[regno]))); - -} - -/* Compute the number of DREGS to save with a push_multiple operation. - This could include registers that aren't modified in the function, - since push_multiple only takes a range of registers. - If IS_INTHANDLER, then everything that is live must be saved, even - if normally call-clobbered. - If CONSECUTIVE, return the number of registers we can save in one - instruction with a push/pop multiple instruction. */ - -static int -n_dregs_to_save (bool is_inthandler, bool consecutive) -{ - int count = 0; - unsigned i; - - for (i = REG_R7 + 1; i-- != REG_R0;) - { - if (must_save_p (is_inthandler, i)) - count++; - else if (consecutive) - return count; - } - return count; -} - -/* Like n_dregs_to_save, but compute number of PREGS to save. */ - -static int -n_pregs_to_save (bool is_inthandler, bool consecutive) -{ - int count = 0; - unsigned i; - - for (i = REG_P5 + 1; i-- != REG_P0;) - if (must_save_p (is_inthandler, i)) - count++; - else if (consecutive) - return count; - return count; -} - -/* Determine if we are going to save the frame pointer in the prologue. */ - -static bool -must_save_fp_p (void) -{ - return df_regs_ever_live_p (REG_FP); -} - -/* Determine if we are going to save the RETS register. */ -static bool -must_save_rets_p (void) -{ - return df_regs_ever_live_p (REG_RETS); -} - -static bool -stack_frame_needed_p (void) -{ - /* EH return puts a new return address into the frame using an - address relative to the frame pointer. */ - if (crtl->calls_eh_return) - return true; - return frame_pointer_needed; -} - -/* Emit code to save registers in the prologue. SAVEALL is nonzero if we - must save all registers; this is used for interrupt handlers. - SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing - this for an interrupt (or exception) handler. */ - -static void -expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler) -{ - rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg); - rtx predec = gen_rtx_MEM (SImode, predec1); - int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false); - int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false); - int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true); - int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true); - int dregno, pregno; - int total_consec = ndregs_consec + npregs_consec; - int i, d_to_save; - - if (saveall || is_inthandler) - { - rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT)); - - RTX_FRAME_RELATED_P (insn) = 1; - for (dregno = REG_LT0; dregno <= REG_LB1; dregno++) - if (! current_function_is_leaf - || cfun->machine->has_hardware_loops - || cfun->machine->has_loopreg_clobber - || (ENABLE_WA_05000257 - && (dregno == REG_LC0 || dregno == REG_LC1))) - { - insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno)); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - - if (total_consec != 0) - { - rtx insn; - rtx val = GEN_INT (-total_consec * 4); - rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2)); - - XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val), - UNSPEC_PUSH_MULTIPLE); - XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg, - gen_rtx_PLUS (Pmode, - spreg, - val)); - RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1; - d_to_save = ndregs_consec; - dregno = REG_R7 + 1 - ndregs_consec; - pregno = REG_P5 + 1 - npregs_consec; - for (i = 0; i < total_consec; i++) - { - rtx memref = gen_rtx_MEM (word_mode, - gen_rtx_PLUS (Pmode, spreg, - GEN_INT (- i * 4 - 4))); - rtx subpat; - if (d_to_save > 0) - { - subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, - dregno++)); - d_to_save--; - } - else - { - subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, - pregno++)); - } - XVECEXP (pat, 0, i + 1) = subpat; - RTX_FRAME_RELATED_P (subpat) = 1; - } - insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; - } - - for (dregno = REG_R0; ndregs != ndregs_consec; dregno++) - { - if (must_save_p (is_inthandler, dregno)) - { - rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno)); - RTX_FRAME_RELATED_P (insn) = 1; - ndregs--; - } - } - for (pregno = REG_P0; npregs != npregs_consec; pregno++) - { - if (must_save_p (is_inthandler, pregno)) - { - rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno)); - RTX_FRAME_RELATED_P (insn) = 1; - npregs--; - } - } - for (i = REG_P7 + 1; i < REG_CC; i++) - if (saveall - || (is_inthandler - && (df_regs_ever_live_p (i) - || (!leaf_function_p () && call_used_regs[i])))) - { - rtx insn; - if (i == REG_A0 || i == REG_A1) - insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1), - gen_rtx_REG (PDImode, i)); - else - insn = emit_move_insn (predec, gen_rtx_REG (SImode, i)); - RTX_FRAME_RELATED_P (insn) = 1; - } -} - -/* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we - must save all registers; this is used for interrupt handlers. - SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing - this for an interrupt (or exception) handler. */ - -static void -expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) -{ - rtx postinc1 = gen_rtx_POST_INC (SImode, spreg); - rtx postinc = gen_rtx_MEM (SImode, postinc1); - - int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false); - int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false); - int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true); - int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true); - int total_consec = ndregs_consec + npregs_consec; - int i, regno; - rtx insn; - - /* A slightly crude technique to stop flow from trying to delete "dead" - insns. */ - MEM_VOLATILE_P (postinc) = 1; - - for (i = REG_CC - 1; i > REG_P7; i--) - if (saveall - || (is_inthandler - && (df_regs_ever_live_p (i) - || (!leaf_function_p () && call_used_regs[i])))) - { - if (i == REG_A0 || i == REG_A1) - { - rtx mem = gen_rtx_MEM (PDImode, postinc1); - MEM_VOLATILE_P (mem) = 1; - emit_move_insn (gen_rtx_REG (PDImode, i), mem); - } - else - emit_move_insn (gen_rtx_REG (SImode, i), postinc); - } - - regno = REG_P5 - npregs_consec; - for (; npregs != npregs_consec; regno--) - { - if (must_save_p (is_inthandler, regno)) - { - emit_move_insn (gen_rtx_REG (word_mode, regno), postinc); - npregs--; - } - } - regno = REG_R7 - ndregs_consec; - for (; ndregs != ndregs_consec; regno--) - { - if (must_save_p (is_inthandler, regno)) - { - emit_move_insn (gen_rtx_REG (word_mode, regno), postinc); - ndregs--; - } - } - - if (total_consec != 0) - { - rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1)); - XVECEXP (pat, 0, 0) - = gen_rtx_SET (VOIDmode, spreg, - gen_rtx_PLUS (Pmode, spreg, - GEN_INT (total_consec * 4))); - - if (npregs_consec > 0) - regno = REG_P5 + 1; - else - regno = REG_R7 + 1; - - for (i = 0; i < total_consec; i++) - { - rtx addr = (i > 0 - ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4)) - : spreg); - rtx memref = gen_rtx_MEM (word_mode, addr); - - regno--; - XVECEXP (pat, 0, i + 1) - = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref); - - if (npregs_consec > 0) - { - if (--npregs_consec == 0) - regno = REG_R7 + 1; - } - } - - insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; - } - if (saveall || is_inthandler) - { - for (regno = REG_LB1; regno >= REG_LT0; regno--) - if (! current_function_is_leaf - || cfun->machine->has_hardware_loops - || cfun->machine->has_loopreg_clobber - || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1))) - emit_move_insn (gen_rtx_REG (SImode, regno), postinc); - - emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc); - } -} - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. - - Blackfin specific : - - VDSP C compiler manual (our ABI) says that a variable args function - should save the R0, R1 and R2 registers in the stack. - - The caller will always leave space on the stack for the - arguments that are passed in registers, so we dont have - to leave any extra space. - - now, the vastart pointer can access all arguments from the stack. */ - -static void -setup_incoming_varargs (cumulative_args_t cum, - enum machine_mode mode ATTRIBUTE_UNUSED, - tree type ATTRIBUTE_UNUSED, int *pretend_size, - int no_rtl) -{ - rtx mem; - int i; - - if (no_rtl) - return; - - /* The move for named arguments will be generated automatically by the - compiler. We need to generate the move rtx for the unnamed arguments - if they are in the first 3 words. We assume at least 1 named argument - exists, so we never generate [ARGP] = R0 here. */ - - for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++) - { - mem = gen_rtx_MEM (Pmode, - plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD))); - emit_move_insn (mem, gen_rtx_REG (Pmode, i)); - } - - *pretend_size = 0; -} - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms may - be accessed via the stack pointer) in functions that seem suitable. */ - -static bool -bfin_frame_pointer_required (void) -{ - e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); - - if (fkind != SUBROUTINE) - return true; - - /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used, - so we have to override it for non-leaf functions. */ - if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf) - return true; - - return false; -} - -/* Return the number of registers pushed during the prologue. */ - -static int -n_regs_saved_by_prologue (void) -{ - e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); - bool is_inthandler = fkind != SUBROUTINE; - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE - || (is_inthandler && !current_function_is_leaf)); - int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false); - int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false); - int n = ndregs + npregs; - int i; - - if (all || stack_frame_needed_p ()) - n += 2; - else - { - if (must_save_fp_p ()) - n++; - if (must_save_rets_p ()) - n++; - } - - if (fkind != SUBROUTINE || all) - { - /* Increment once for ASTAT. */ - n++; - if (! current_function_is_leaf - || cfun->machine->has_hardware_loops - || cfun->machine->has_loopreg_clobber) - { - n += 6; - } - } - - if (fkind != SUBROUTINE) - { - /* RETE/X/N. */ - if (lookup_attribute ("nesting", attrs)) - n++; - } - - for (i = REG_P7 + 1; i < REG_CC; i++) - if (all - || (fkind != SUBROUTINE - && (df_regs_ever_live_p (i) - || (!leaf_function_p () && call_used_regs[i])))) - n += i == REG_A0 || i == REG_A1 ? 2 : 1; - - return n; -} - -/* Given FROM and TO register numbers, say whether this elimination is - allowed. Frame pointer elimination is automatically handled. - - All other eliminations are valid. */ - -static bool -bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) -{ - return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true); -} - -/* Return the offset between two registers, one to be eliminated, and the other - its replacement, at the start of a routine. */ - -HOST_WIDE_INT -bfin_initial_elimination_offset (int from, int to) -{ - HOST_WIDE_INT offset = 0; - - if (from == ARG_POINTER_REGNUM) - offset = n_regs_saved_by_prologue () * 4; - - if (to == STACK_POINTER_REGNUM) - { - if (crtl->outgoing_args_size >= FIXED_STACK_AREA) - offset += crtl->outgoing_args_size; - else if (crtl->outgoing_args_size) - offset += FIXED_STACK_AREA; - - offset += get_frame_size (); - } - - return offset; -} - -/* Emit code to load a constant CONSTANT into register REG; setting - RTX_FRAME_RELATED_P on all insns we generate if RELATED is true. - Make sure that the insns we generate need not be split. */ - -static void -frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related) -{ - rtx insn; - rtx cst = GEN_INT (constant); - - if (constant >= -32768 && constant < 65536) - insn = emit_move_insn (reg, cst); - else - { - /* We don't call split_load_immediate here, since dwarf2out.c can get - confused about some of the more clever sequences it can generate. */ - insn = emit_insn (gen_movsi_high (reg, cst)); - if (related) - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_movsi_low (reg, reg, cst)); - } - if (related) - RTX_FRAME_RELATED_P (insn) = 1; -} - -/* Generate efficient code to add a value to a P register. - Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero. - EPILOGUE_P is zero if this function is called for prologue, - otherwise it's nonzero. And it's less than zero if this is for - sibcall epilogue. */ - -static void -add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p) -{ - if (value == 0) - return; - - /* Choose whether to use a sequence using a temporary register, or - a sequence with multiple adds. We can add a signed 7-bit value - in one instruction. */ - if (value > 120 || value < -120) - { - rtx tmpreg; - rtx tmpreg2; - rtx insn; - - tmpreg2 = NULL_RTX; - - /* For prologue or normal epilogue, P1 can be safely used - as the temporary register. For sibcall epilogue, we try to find - a call used P register, which will be restored in epilogue. - If we cannot find such a P register, we have to use one I register - to help us. */ - - if (epilogue_p >= 0) - tmpreg = gen_rtx_REG (SImode, REG_P1); - else - { - int i; - for (i = REG_P0; i <= REG_P5; i++) - if ((df_regs_ever_live_p (i) && ! call_used_regs[i]) - || (!TARGET_FDPIC - && i == PIC_OFFSET_TABLE_REGNUM - && (crtl->uses_pic_offset_table - || (TARGET_ID_SHARED_LIBRARY - && ! current_function_is_leaf)))) - break; - if (i <= REG_P5) - tmpreg = gen_rtx_REG (SImode, i); - else - { - tmpreg = gen_rtx_REG (SImode, REG_P1); - tmpreg2 = gen_rtx_REG (SImode, REG_I0); - emit_move_insn (tmpreg2, tmpreg); - } - } - - if (frame) - frame_related_constant_load (tmpreg, value, TRUE); - else - insn = emit_move_insn (tmpreg, GEN_INT (value)); - - insn = emit_insn (gen_addsi3 (reg, reg, tmpreg)); - if (frame) - RTX_FRAME_RELATED_P (insn) = 1; - - if (tmpreg2 != NULL_RTX) - emit_move_insn (tmpreg, tmpreg2); - } - else - do - { - int size = value; - rtx insn; - - if (size > 60) - size = 60; - else if (size < -60) - /* We could use -62, but that would leave the stack unaligned, so - it's no good. */ - size = -60; - - insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size))); - if (frame) - RTX_FRAME_RELATED_P (insn) = 1; - value -= size; - } - while (value != 0); -} - -/* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant - is too large, generate a sequence of insns that has the same effect. - SPREG contains (reg:SI REG_SP). */ - -static void -emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size) -{ - HOST_WIDE_INT link_size = frame_size; - rtx insn; - int i; - - if (link_size > 262140) - link_size = 262140; - - /* Use a LINK insn with as big a constant as possible, then subtract - any remaining size from the SP. */ - insn = emit_insn (gen_link (GEN_INT (-8 - link_size))); - RTX_FRAME_RELATED_P (insn) = 1; - - for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) - { - rtx set = XVECEXP (PATTERN (insn), 0, i); - gcc_assert (GET_CODE (set) == SET); - RTX_FRAME_RELATED_P (set) = 1; - } - - frame_size -= link_size; - - if (frame_size > 0) - { - /* Must use a call-clobbered PREG that isn't the static chain. */ - rtx tmpreg = gen_rtx_REG (Pmode, REG_P1); - - frame_related_constant_load (tmpreg, -frame_size, TRUE); - insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg)); - RTX_FRAME_RELATED_P (insn) = 1; - } -} - -/* Return the number of bytes we must reserve for outgoing arguments - in the current function's stack frame. */ - -static HOST_WIDE_INT -arg_area_size (void) -{ - if (crtl->outgoing_args_size) - { - if (crtl->outgoing_args_size >= FIXED_STACK_AREA) - return crtl->outgoing_args_size; - else - return FIXED_STACK_AREA; - } - return 0; -} - -/* Save RETS and FP, and allocate a stack frame. ALL is true if the - function must save all its registers (true only for certain interrupt - handlers). */ - -static void -do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all) -{ - frame_size += arg_area_size (); - - if (all - || stack_frame_needed_p () - || (must_save_rets_p () && must_save_fp_p ())) - emit_link_insn (spreg, frame_size); - else - { - if (must_save_rets_p ()) - { - rtx pat = gen_movsi (gen_rtx_MEM (Pmode, - gen_rtx_PRE_DEC (Pmode, spreg)), - bfin_rets_rtx); - rtx insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; - } - if (must_save_fp_p ()) - { - rtx pat = gen_movsi (gen_rtx_MEM (Pmode, - gen_rtx_PRE_DEC (Pmode, spreg)), - gen_rtx_REG (Pmode, REG_FP)); - rtx insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; - } - add_to_reg (spreg, -frame_size, 1, 0); - } -} - -/* Like do_link, but used for epilogues to deallocate the stack frame. - EPILOGUE_P is zero if this function is called for prologue, - otherwise it's nonzero. And it's less than zero if this is for - sibcall epilogue. */ - -static void -do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p) -{ - frame_size += arg_area_size (); - - if (stack_frame_needed_p ()) - emit_insn (gen_unlink ()); - else - { - rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg)); - - add_to_reg (spreg, frame_size, 0, epilogue_p); - if (all || must_save_fp_p ()) - { - rtx fpreg = gen_rtx_REG (Pmode, REG_FP); - emit_move_insn (fpreg, postinc); - emit_use (fpreg); - } - if (all || must_save_rets_p ()) - { - emit_move_insn (bfin_rets_rtx, postinc); - emit_use (bfin_rets_rtx); - } - } -} - -/* Generate a prologue suitable for a function of kind FKIND. This is - called for interrupt and exception handler prologues. - SPREG contains (reg:SI REG_SP). */ - -static void -expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all) -{ - HOST_WIDE_INT frame_size = get_frame_size (); - rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg); - rtx predec = gen_rtx_MEM (SImode, predec1); - rtx insn; - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - tree kspisusp = lookup_attribute ("kspisusp", attrs); - - if (kspisusp) - { - insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP)); - RTX_FRAME_RELATED_P (insn) = 1; - } - - /* We need space on the stack in case we need to save the argument - registers. */ - if (fkind == EXCPT_HANDLER) - { - insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - /* If we're calling other functions, they won't save their call-clobbered - registers, so we must save everything here. */ - if (!current_function_is_leaf) - all = true; - expand_prologue_reg_save (spreg, all, true); - - if (ENABLE_WA_05000283 || ENABLE_WA_05000315) - { - rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode)); - rtx p5reg = gen_rtx_REG (Pmode, REG_P5); - emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx)); - emit_insn (gen_movsi_high (p5reg, chipid)); - emit_insn (gen_movsi_low (p5reg, p5reg, chipid)); - emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx)); - } - - if (lookup_attribute ("nesting", attrs)) - { - rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]); - insn = emit_move_insn (predec, srcreg); - RTX_FRAME_RELATED_P (insn) = 1; - } - - do_link (spreg, frame_size, all); - - if (fkind == EXCPT_HANDLER) - { - rtx r0reg = gen_rtx_REG (SImode, REG_R0); - rtx r1reg = gen_rtx_REG (SImode, REG_R1); - rtx r2reg = gen_rtx_REG (SImode, REG_R2); - - emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT)); - emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26))); - emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26))); - emit_move_insn (r1reg, spreg); - emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP)); - emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8))); - } -} - -/* Generate an epilogue suitable for a function of kind FKIND. This is - called for interrupt and exception handler epilogues. - SPREG contains (reg:SI REG_SP). */ - -static void -expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all) -{ - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - rtx postinc1 = gen_rtx_POST_INC (SImode, spreg); - rtx postinc = gen_rtx_MEM (SImode, postinc1); - - /* A slightly crude technique to stop flow from trying to delete "dead" - insns. */ - MEM_VOLATILE_P (postinc) = 1; - - do_unlink (spreg, get_frame_size (), all, 1); - - if (lookup_attribute ("nesting", attrs)) - { - rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]); - emit_move_insn (srcreg, postinc); - } - - /* If we're calling other functions, they won't save their call-clobbered - registers, so we must save (and restore) everything here. */ - if (!current_function_is_leaf) - all = true; - - expand_epilogue_reg_restore (spreg, all, true); - - /* Deallocate any space we left on the stack in case we needed to save the - argument registers. */ - if (fkind == EXCPT_HANDLER) - emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12))); - - emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind]))); -} - -/* Used while emitting the prologue to generate code to load the correct value - into the PIC register, which is passed in DEST. */ - -static rtx -bfin_load_pic_reg (rtx dest) -{ - struct cgraph_local_info *i = NULL; - rtx addr; - - i = cgraph_local_info (current_function_decl); - - /* Functions local to the translation unit don't need to reload the - pic reg, since the caller always passes a usable one. */ - if (i && i->local) - return pic_offset_table_rtx; - - if (global_options_set.x_bfin_library_id) - addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4); - else - addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, - gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), - UNSPEC_LIBRARY_OFFSET)); - emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr))); - return dest; -} - -/* Generate RTL for the prologue of the current function. */ - -void -bfin_expand_prologue (void) -{ - HOST_WIDE_INT frame_size = get_frame_size (); - rtx spreg = gen_rtx_REG (Pmode, REG_SP); - e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); - rtx pic_reg_loaded = NULL_RTX; - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - bool all = lookup_attribute ("saveall", attrs) != NULL_TREE; - - if (fkind != SUBROUTINE) - { - expand_interrupt_handler_prologue (spreg, fkind, all); - return; - } - - if (crtl->limit_stack - || (TARGET_STACK_CHECK_L1 - && !DECL_NO_LIMIT_STACK (current_function_decl))) - { - HOST_WIDE_INT offset - = bfin_initial_elimination_offset (ARG_POINTER_REGNUM, - STACK_POINTER_REGNUM); - rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX; - rtx tmp = gen_rtx_REG (Pmode, REG_R3); - rtx p2reg = gen_rtx_REG (Pmode, REG_P2); - - emit_move_insn (tmp, p2reg); - if (!lim) - { - emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode)); - emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg)); - lim = p2reg; - } - if (GET_CODE (lim) == SYMBOL_REF) - { - if (TARGET_ID_SHARED_LIBRARY) - { - rtx p1reg = gen_rtx_REG (Pmode, REG_P1); - rtx val; - pic_reg_loaded = bfin_load_pic_reg (p2reg); - val = legitimize_pic_address (stack_limit_rtx, p1reg, - pic_reg_loaded); - emit_move_insn (p1reg, val); - frame_related_constant_load (p2reg, offset, FALSE); - emit_insn (gen_addsi3 (p2reg, p2reg, p1reg)); - lim = p2reg; - } - else - { - rtx limit = plus_constant (lim, offset); - emit_move_insn (p2reg, limit); - lim = p2reg; - } - } - else - { - if (lim != p2reg) - emit_move_insn (p2reg, lim); - add_to_reg (p2reg, offset, 0, 0); - lim = p2reg; - } - emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); - emit_insn (gen_trapifcc ()); - emit_move_insn (p2reg, tmp); - } - expand_prologue_reg_save (spreg, all, false); - - do_link (spreg, frame_size, all); - - if (TARGET_ID_SHARED_LIBRARY - && !TARGET_SEP_DATA - && (crtl->uses_pic_offset_table - || !current_function_is_leaf)) - bfin_load_pic_reg (pic_offset_table_rtx); -} - -/* Generate RTL for the epilogue of the current function. NEED_RETURN is zero - if this is for a sibcall. EH_RETURN is nonzero if we're expanding an - eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue, - false otherwise. */ - -void -bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p) -{ - rtx spreg = gen_rtx_REG (Pmode, REG_SP); - e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); - int e = sibcall_p ? -1 : 1; - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - bool all = lookup_attribute ("saveall", attrs) != NULL_TREE; - - if (fkind != SUBROUTINE) - { - expand_interrupt_handler_epilogue (spreg, fkind, all); - return; - } - - do_unlink (spreg, get_frame_size (), all, e); - - expand_epilogue_reg_restore (spreg, all, false); - - /* Omit the return insn if this is for a sibcall. */ - if (! need_return) - return; - - if (eh_return) - emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2))); - - emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS))); -} - -/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */ - -int -bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, - unsigned int new_reg) -{ - /* Interrupt functions can only use registers that have already been - saved by the prologue, even if they would normally be - call-clobbered. */ - - if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE - && !df_regs_ever_live_p (new_reg)) - return 0; - - return 1; -} - -/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */ -static void -bfin_extra_live_on_entry (bitmap regs) -{ - if (TARGET_FDPIC) - bitmap_set_bit (regs, FDPIC_REGNO); -} - -/* Return the value of the return address for the frame COUNT steps up - from the current frame, after the prologue. - We punt for everything but the current frame by returning const0_rtx. */ - -rtx -bfin_return_addr_rtx (int count) -{ - if (count != 0) - return const0_rtx; - - return get_hard_reg_initial_val (Pmode, REG_RETS); -} - -static rtx -bfin_delegitimize_address (rtx orig_x) -{ - rtx x = orig_x; - - if (GET_CODE (x) != MEM) - return orig_x; - - x = XEXP (x, 0); - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 1)) == UNSPEC - && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC - && GET_CODE (XEXP (x, 0)) == REG - && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM) - return XVECEXP (XEXP (x, 1), 0, 0); - - return orig_x; -} - -/* This predicate is used to compute the length of a load/store insn. - OP is a MEM rtx, we return nonzero if its addressing mode requires a - 32-bit instruction. */ - -int -effective_address_32bit_p (rtx op, enum machine_mode mode) -{ - HOST_WIDE_INT offset; - - mode = GET_MODE (op); - op = XEXP (op, 0); - - if (GET_CODE (op) != PLUS) - { - gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC - || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC); - return 0; - } - - if (GET_CODE (XEXP (op, 1)) == UNSPEC) - return 1; - - offset = INTVAL (XEXP (op, 1)); - - /* All byte loads use a 16-bit offset. */ - if (GET_MODE_SIZE (mode) == 1) - return 1; - - if (GET_MODE_SIZE (mode) == 4) - { - /* Frame pointer relative loads can use a negative offset, all others - are restricted to a small positive one. */ - if (XEXP (op, 0) == frame_pointer_rtx) - return offset < -128 || offset > 60; - return offset < 0 || offset > 60; - } - - /* Must be HImode now. */ - return offset < 0 || offset > 30; -} - -/* Returns true if X is a memory reference using an I register. */ -bool -bfin_dsp_memref_p (rtx x) -{ - if (! MEM_P (x)) - return false; - x = XEXP (x, 0); - if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC - || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC) - x = XEXP (x, 0); - return IREG_P (x); -} - -/* Return cost of the memory address ADDR. - All addressing modes are equally cheap on the Blackfin. */ - -static int -bfin_address_cost (rtx addr ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED) -{ - return 1; -} - -/* Subroutine of print_operand; used to print a memory reference X to FILE. */ - -void -print_address_operand (FILE *file, rtx x) -{ - switch (GET_CODE (x)) - { - case PLUS: - output_address (XEXP (x, 0)); - fprintf (file, "+"); - output_address (XEXP (x, 1)); - break; - - case PRE_DEC: - fprintf (file, "--"); - output_address (XEXP (x, 0)); - break; - case POST_INC: - output_address (XEXP (x, 0)); - fprintf (file, "++"); - break; - case POST_DEC: - output_address (XEXP (x, 0)); - fprintf (file, "--"); - break; - - default: - gcc_assert (GET_CODE (x) != MEM); - print_operand (file, x, 0); - break; - } -} - -/* Adding intp DImode support by Tony - * -- Q: (low word) - * -- R: (high word) - */ - -void -print_operand (FILE *file, rtx x, char code) -{ - enum machine_mode mode; - - if (code == '!') - { - if (GET_MODE (current_output_insn) == SImode) - fprintf (file, " ||"); - else - fprintf (file, ";"); - return; - } - - mode = GET_MODE (x); - - switch (code) - { - case 'j': - switch (GET_CODE (x)) - { - case EQ: - fprintf (file, "e"); - break; - case NE: - fprintf (file, "ne"); - break; - case GT: - fprintf (file, "g"); - break; - case LT: - fprintf (file, "l"); - break; - case GE: - fprintf (file, "ge"); - break; - case LE: - fprintf (file, "le"); - break; - case GTU: - fprintf (file, "g"); - break; - case LTU: - fprintf (file, "l"); - break; - case GEU: - fprintf (file, "ge"); - break; - case LEU: - fprintf (file, "le"); - break; - default: - output_operand_lossage ("invalid %%j value"); - } - break; - - case 'J': /* reverse logic */ - switch (GET_CODE(x)) - { - case EQ: - fprintf (file, "ne"); - break; - case NE: - fprintf (file, "e"); - break; - case GT: - fprintf (file, "le"); - break; - case LT: - fprintf (file, "ge"); - break; - case GE: - fprintf (file, "l"); - break; - case LE: - fprintf (file, "g"); - break; - case GTU: - fprintf (file, "le"); - break; - case LTU: - fprintf (file, "ge"); - break; - case GEU: - fprintf (file, "l"); - break; - case LEU: - fprintf (file, "g"); - break; - default: - output_operand_lossage ("invalid %%J value"); - } - break; - - default: - switch (GET_CODE (x)) - { - case REG: - if (code == 'h') - { - if (REGNO (x) < 32) - fprintf (file, "%s", short_reg_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'd') - { - if (REGNO (x) < 32) - fprintf (file, "%s", high_reg_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'w') - { - if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1) - fprintf (file, "%s.w", reg_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'x') - { - if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1) - fprintf (file, "%s.x", reg_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'v') - { - if (REGNO (x) == REG_A0) - fprintf (file, "AV0"); - else if (REGNO (x) == REG_A1) - fprintf (file, "AV1"); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'D') - { - if (D_REGNO_P (REGNO (x))) - fprintf (file, "%s", dregs_pair_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'H') - { - if ((mode == DImode || mode == DFmode) && REG_P (x)) - fprintf (file, "%s", reg_names[REGNO (x) + 1]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else if (code == 'T') - { - if (D_REGNO_P (REGNO (x))) - fprintf (file, "%s", byte_reg_names[REGNO (x)]); - else - output_operand_lossage ("invalid operand for code '%c'", code); - } - else - fprintf (file, "%s", reg_names[REGNO (x)]); - break; - - case MEM: - fputc ('[', file); - x = XEXP (x,0); - print_address_operand (file, x); - fputc (']', file); - break; - - case CONST_INT: - if (code == 'M') - { - switch (INTVAL (x)) - { - case MACFLAG_NONE: - break; - case MACFLAG_FU: - fputs ("(FU)", file); - break; - case MACFLAG_T: - fputs ("(T)", file); - break; - case MACFLAG_TFU: - fputs ("(TFU)", file); - break; - case MACFLAG_W32: - fputs ("(W32)", file); - break; - case MACFLAG_IS: - fputs ("(IS)", file); - break; - case MACFLAG_IU: - fputs ("(IU)", file); - break; - case MACFLAG_IH: - fputs ("(IH)", file); - break; - case MACFLAG_M: - fputs ("(M)", file); - break; - case MACFLAG_IS_M: - fputs ("(IS,M)", file); - break; - case MACFLAG_ISS2: - fputs ("(ISS2)", file); - break; - case MACFLAG_S2RND: - fputs ("(S2RND)", file); - break; - default: - gcc_unreachable (); - } - break; - } - else if (code == 'b') - { - if (INTVAL (x) == 0) - fputs ("+=", file); - else if (INTVAL (x) == 1) - fputs ("-=", file); - else - gcc_unreachable (); - break; - } - /* Moves to half registers with d or h modifiers always use unsigned - constants. */ - else if (code == 'd') - x = GEN_INT ((INTVAL (x) >> 16) & 0xffff); - else if (code == 'h') - x = GEN_INT (INTVAL (x) & 0xffff); - else if (code == 'N') - x = GEN_INT (-INTVAL (x)); - else if (code == 'X') - x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x))); - else if (code == 'Y') - x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x))); - else if (code == 'Z') - /* Used for LINK insns. */ - x = GEN_INT (-8 - INTVAL (x)); - - /* fall through */ - - case SYMBOL_REF: - output_addr_const (file, x); - break; - - case CONST_DOUBLE: - output_operand_lossage ("invalid const_double operand"); - break; - - case UNSPEC: - switch (XINT (x, 1)) - { - case UNSPEC_MOVE_PIC: - output_addr_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@GOT"); - break; - - case UNSPEC_MOVE_FDPIC: - output_addr_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@GOT17M4"); - break; - - case UNSPEC_FUNCDESC_GOT17M4: - output_addr_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@FUNCDESC_GOT17M4"); - break; - - case UNSPEC_LIBRARY_OFFSET: - fprintf (file, "_current_shared_library_p5_offset_"); - break; - - default: - gcc_unreachable (); - } - break; - - default: - output_addr_const (file, x); - } - } -} - -/* Argument support functions. */ - -/* 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. - VDSP C Compiler manual, our ABI says that - first 3 words of arguments will use R0, R1 and R2. -*/ - -void -init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, - rtx libname ATTRIBUTE_UNUSED) -{ - static CUMULATIVE_ARGS zero_cum; - - *cum = zero_cum; - - /* Set up the number of registers to use for passing arguments. */ - - cum->nregs = max_arg_registers; - cum->arg_regs = arg_regs; - - cum->call_cookie = CALL_NORMAL; - /* Check for a longcall attribute. */ - if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))) - cum->call_cookie |= CALL_SHORT; - else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))) - cum->call_cookie |= CALL_LONG; - - return; -} - -/* 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.) */ - -static void -bfin_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, - const_tree type, bool named ATTRIBUTE_UNUSED) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - int count, bytes, words; - - bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); - words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - - cum->words += words; - cum->nregs -= words; - - if (cum->nregs <= 0) - { - cum->nregs = 0; - cum->arg_regs = NULL; - } - else - { - for (count = 1; count <= words; count++) - cum->arg_regs++; - } - - 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). */ - -static rtx -bfin_function_arg (cumulative_args_t cum_v, enum machine_mode mode, - const_tree type, bool named ATTRIBUTE_UNUSED) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - int bytes - = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); - - if (mode == VOIDmode) - /* Compute operand 2 of the call insn. */ - return GEN_INT (cum->call_cookie); - - if (bytes == -1) - return NULL_RTX; - - if (cum->nregs) - return gen_rtx_REG (mode, *(cum->arg_regs)); - - return NULL_RTX; -} - -/* For an arg passed partly in registers and partly in memory, - this is the number of bytes passed in registers. - For args passed entirely in registers or entirely in memory, zero. - - Refer VDSP C Compiler manual, our ABI. - First 3 words are in registers. So, if an argument is larger - than the registers available, it will span the register and - stack. */ - -static int -bfin_arg_partial_bytes (cumulative_args_t cum, enum machine_mode mode, - tree type ATTRIBUTE_UNUSED, - bool named ATTRIBUTE_UNUSED) -{ - int bytes - = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); - int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD; - - if (bytes == -1) - return 0; - - if (bytes_left == 0) - return 0; - if (bytes > bytes_left) - return bytes_left; - return 0; -} - -/* Variable sized types are passed by reference. */ - -static bool -bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, - const_tree type, bool named ATTRIBUTE_UNUSED) -{ - return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST; -} - -/* Decide whether a type should be returned in memory (true) - or in a register (false). This is called by the macro - TARGET_RETURN_IN_MEMORY. */ - -static bool -bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) -{ - int size = int_size_in_bytes (type); - return size > 2 * UNITS_PER_WORD || size == -1; -} - -/* Register in which address to store a structure value - is passed to a function. */ -static rtx -bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, - int incoming ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (Pmode, REG_P0); -} - -/* Return true when register may be used to pass function parameters. */ - -bool -function_arg_regno_p (int n) -{ - int i; - for (i = 0; arg_regs[i] != -1; i++) - if (n == arg_regs[i]) - return true; - return false; -} - -/* Returns 1 if OP contains a symbol reference */ - -int -symbolic_reference_mentioned_p (rtx op) -{ - register const char *fmt; - register int i; - - if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) - return 1; - - fmt = GET_RTX_FORMAT (GET_CODE (op)); - for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) - { - if (fmt[i] == 'E') - { - register int j; - - for (j = XVECLEN (op, i) - 1; j >= 0; j--) - if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) - return 1; - } - - else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) - return 1; - } - - return 0; -} - -/* Decide whether we can make a sibling call to a function. DECL is the - declaration of the function being targeted by the call and EXP is the - CALL_EXPR representing the call. */ - -static bool -bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, - tree exp ATTRIBUTE_UNUSED) -{ - struct cgraph_local_info *this_func, *called_func; - e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); - if (fkind != SUBROUTINE) - return false; - if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA) - return true; - - /* When compiling for ID shared libraries, can't sibcall a local function - from a non-local function, because the local function thinks it does - not need to reload P5 in the prologue, but the sibcall wil pop P5 in the - sibcall epilogue, and we end up with the wrong value in P5. */ - - if (!decl) - /* Not enough information. */ - return false; - - this_func = cgraph_local_info (current_function_decl); - called_func = cgraph_local_info (decl); - if (!called_func) - return false; - return !called_func->local || this_func->local; -} - -/* Write a template for a trampoline to F. */ - -static void -bfin_asm_trampoline_template (FILE *f) -{ - if (TARGET_FDPIC) - { - fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */ - fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */ - fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ - fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ - fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ - fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ - fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */ - fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */ - fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/ - } - else - { - fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ - fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ - fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ - fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ - fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/ - } -} - -/* Emit RTL insns to initialize the variable parts of a trampoline at - M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for - the static chain value for the function. */ - -static void -bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) -{ - rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0)); - rtx t2 = copy_to_reg (chain_value); - rtx mem; - int i = 0; - - emit_block_move (m_tramp, assemble_trampoline_template (), - GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); - - if (TARGET_FDPIC) - { - rtx a = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0), 8)); - mem = adjust_address (m_tramp, Pmode, 0); - emit_move_insn (mem, a); - i = 8; - } - - mem = adjust_address (m_tramp, HImode, i + 2); - emit_move_insn (mem, gen_lowpart (HImode, t1)); - emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16))); - mem = adjust_address (m_tramp, HImode, i + 6); - emit_move_insn (mem, gen_lowpart (HImode, t1)); - - mem = adjust_address (m_tramp, HImode, i + 10); - emit_move_insn (mem, gen_lowpart (HImode, t2)); - emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16))); - mem = adjust_address (m_tramp, HImode, i + 14); - emit_move_insn (mem, gen_lowpart (HImode, t2)); -} - -/* Emit insns to move operands[1] into operands[0]. */ - -void -emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); - - gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed)); - if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) - operands[1] = force_reg (SImode, operands[1]); - else - operands[1] = legitimize_pic_address (operands[1], temp, - TARGET_FDPIC ? OUR_FDPIC_REG - : pic_offset_table_rtx); -} - -/* Expand a move operation in mode MODE. The operands are in OPERANDS. - Returns true if no further code must be generated, false if the caller - should generate an insn to move OPERANDS[1] to OPERANDS[0]. */ - -bool -expand_move (rtx *operands, enum machine_mode mode) -{ - rtx op = operands[1]; - if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC) - && SYMBOLIC_CONST (op)) - emit_pic_move (operands, mode); - else if (mode == SImode && GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF - && !targetm.legitimate_constant_p (mode, op)) - { - rtx dest = operands[0]; - rtx op0, op1; - gcc_assert (!reload_in_progress && !reload_completed); - op = XEXP (op, 0); - op0 = force_reg (mode, XEXP (op, 0)); - op1 = XEXP (op, 1); - if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode)) - op1 = force_reg (mode, op1); - if (GET_CODE (dest) == MEM) - dest = gen_reg_rtx (mode); - emit_insn (gen_addsi3 (dest, op0, op1)); - if (dest == operands[0]) - return true; - operands[1] = dest; - } - /* Don't generate memory->memory or constant->memory moves, go through a - register */ - else if ((reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) != REG) - operands[1] = force_reg (mode, operands[1]); - return false; -} - -/* Split one or more DImode RTL references into pairs of SImode - references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to - split and "num" is its length. lo_half and hi_half are output arrays - that parallel "operands". */ - -void -split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) -{ - while (num--) - { - rtx op = operands[num]; - - /* simplify_subreg refuse to split volatile memory addresses, - but we still have to handle it. */ - if (GET_CODE (op) == MEM) - { - lo_half[num] = adjust_address (op, SImode, 0); - hi_half[num] = adjust_address (op, SImode, 4); - } - else - { - lo_half[num] = simplify_gen_subreg (SImode, op, - GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 0); - hi_half[num] = simplify_gen_subreg (SImode, op, - GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 4); - } - } -} - -bool -bfin_longcall_p (rtx op, int call_cookie) -{ - gcc_assert (GET_CODE (op) == SYMBOL_REF); - if (SYMBOL_REF_WEAK (op)) - return 1; - if (call_cookie & CALL_SHORT) - return 0; - if (call_cookie & CALL_LONG) - return 1; - if (TARGET_LONG_CALLS) - return 1; - return 0; -} - -/* Expand a call instruction. FNADDR is the call target, RETVAL the return value. - COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args. - SIBCALL is nonzero if this is a sibling call. */ - -void -bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall) -{ - rtx use = NULL, call; - rtx callee = XEXP (fnaddr, 0); - int nelts = 3; - rtx pat; - rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO); - rtx retsreg = gen_rtx_REG (Pmode, REG_RETS); - int n; - - /* In an untyped call, we can get NULL for operand 2. */ - if (cookie == NULL_RTX) - cookie = const0_rtx; - - /* Static functions and indirect calls don't need the pic register. */ - if (!TARGET_FDPIC && flag_pic - && GET_CODE (callee) == SYMBOL_REF - && !SYMBOL_REF_LOCAL_P (callee)) - use_reg (&use, pic_offset_table_rtx); - - if (TARGET_FDPIC) - { - int caller_in_sram, callee_in_sram; - - /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */ - caller_in_sram = callee_in_sram = 0; - - if (lookup_attribute ("l1_text", - DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE) - caller_in_sram = 1; - else if (lookup_attribute ("l2", - DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE) - caller_in_sram = 2; - - if (GET_CODE (callee) == SYMBOL_REF - && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))) - { - if (lookup_attribute - ("l1_text", - DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE) - callee_in_sram = 1; - else if (lookup_attribute - ("l2", - DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE) - callee_in_sram = 2; - } - - if (GET_CODE (callee) != SYMBOL_REF - || bfin_longcall_p (callee, INTVAL (cookie)) - || (GET_CODE (callee) == SYMBOL_REF - && !SYMBOL_REF_LOCAL_P (callee) - && TARGET_INLINE_PLT) - || caller_in_sram != callee_in_sram - || (caller_in_sram && callee_in_sram - && (GET_CODE (callee) != SYMBOL_REF - || !SYMBOL_REF_LOCAL_P (callee)))) - { - rtx addr = callee; - if (! address_operand (addr, Pmode)) - addr = force_reg (Pmode, addr); - - fnaddr = gen_reg_rtx (SImode); - emit_insn (gen_load_funcdescsi (fnaddr, addr)); - fnaddr = gen_rtx_MEM (Pmode, fnaddr); - - picreg = gen_reg_rtx (SImode); - emit_insn (gen_load_funcdescsi (picreg, - plus_constant (addr, 4))); - } - - nelts++; - } - else if ((!register_no_elim_operand (callee, Pmode) - && GET_CODE (callee) != SYMBOL_REF) - || (GET_CODE (callee) == SYMBOL_REF - && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY) - || bfin_longcall_p (callee, INTVAL (cookie))))) - { - callee = copy_to_mode_reg (Pmode, callee); - fnaddr = gen_rtx_MEM (Pmode, callee); - } - call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1); - - if (retval) - call = gen_rtx_SET (VOIDmode, retval, call); - - pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts)); - n = 0; - XVECEXP (pat, 0, n++) = call; - if (TARGET_FDPIC) - XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg); - XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie); - if (sibcall) - XVECEXP (pat, 0, n++) = ret_rtx; - else - XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg); - call = emit_call_insn (pat); - if (use) - CALL_INSN_FUNCTION_USAGE (call) = use; -} - -/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */ - -int -hard_regno_mode_ok (int regno, enum machine_mode mode) -{ - /* Allow only dregs to store value of mode HI or QI */ - enum reg_class rclass = REGNO_REG_CLASS (regno); - - if (mode == CCmode) - return 0; - - if (mode == V2HImode) - return D_REGNO_P (regno); - if (rclass == CCREGS) - return mode == BImode; - if (mode == PDImode || mode == V2PDImode) - return regno == REG_A0 || regno == REG_A1; - - /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes - up with a bad register class (such as ALL_REGS) for DImode. */ - if (mode == DImode) - return regno < REG_M3; - - if (mode == SImode - && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno)) - return 1; - - return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno); -} - -/* Implements target hook vector_mode_supported_p. */ - -static bool -bfin_vector_mode_supported_p (enum machine_mode mode) -{ - return mode == V2HImode; -} - -/* Worker function for TARGET_REGISTER_MOVE_COST. */ - -static int -bfin_register_move_cost (enum machine_mode mode, - reg_class_t class1, reg_class_t class2) -{ - /* These need secondary reloads, so they're more expensive. */ - if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS)) - || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS))) - return 4; - - /* If optimizing for size, always prefer reg-reg over reg-memory moves. */ - if (optimize_size) - return 2; - - if (GET_MODE_CLASS (mode) == MODE_INT) - { - /* Discourage trying to use the accumulators. */ - if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0) - || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1) - || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0) - || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1)) - return 20; - } - return 2; -} - -/* Worker function for TARGET_MEMORY_MOVE_COST. - - ??? In theory L1 memory has single-cycle latency. We should add a switch - that tells the compiler whether we expect to use only L1 memory for the - program; it'll make the costs more accurate. */ - -static int -bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, - reg_class_t rclass, - bool in ATTRIBUTE_UNUSED) -{ - /* Make memory accesses slightly more expensive than any register-register - move. Also, penalize non-DP registers, since they need secondary - reloads to load and store. */ - if (! reg_class_subset_p (rclass, DPREGS)) - return 10; - - return 8; -} - -/* Inform reload about cases where moving X with a mode MODE to a register in - RCLASS requires an extra scratch register. Return the class needed for the - scratch register. */ - -static reg_class_t -bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, - enum machine_mode mode, secondary_reload_info *sri) -{ - /* If we have HImode or QImode, we can only use DREGS as secondary registers; - in most other cases we can also use PREGS. */ - enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS; - enum reg_class x_class = NO_REGS; - enum rtx_code code = GET_CODE (x); - enum reg_class rclass = (enum reg_class) rclass_i; - - if (code == SUBREG) - x = SUBREG_REG (x), code = GET_CODE (x); - if (REG_P (x)) - { - int regno = REGNO (x); - if (regno >= FIRST_PSEUDO_REGISTER) - regno = reg_renumber[regno]; - - if (regno == -1) - code = MEM; - else - x_class = REGNO_REG_CLASS (regno); - } - - /* We can be asked to reload (plus (FP) (large_constant)) into a DREG. - This happens as a side effect of register elimination, and we need - a scratch register to do it. */ - if (fp_plus_const_operand (x, mode)) - { - rtx op2 = XEXP (x, 1); - int large_constant_p = ! satisfies_constraint_Ks7 (op2); - - if (rclass == PREGS || rclass == PREGS_CLOBBERED) - return NO_REGS; - /* If destination is a DREG, we can do this without a scratch register - if the constant is valid for an add instruction. */ - if ((rclass == DREGS || rclass == DPREGS) - && ! large_constant_p) - return NO_REGS; - /* Reloading to anything other than a DREG? Use a PREG scratch - register. */ - sri->icode = CODE_FOR_reload_insi; - return NO_REGS; - } - - /* Data can usually be moved freely between registers of most classes. - AREGS are an exception; they can only move to or from another register - in AREGS or one in DREGS. They can also be assigned the constant 0. */ - if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS) - return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS - || rclass == ODD_AREGS - ? NO_REGS : DREGS); - - if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS) - { - if (code == MEM) - { - sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi; - return NO_REGS; - } - - if (x != const0_rtx && x_class != DREGS) - { - return DREGS; - } - else - return NO_REGS; - } - - /* CCREGS can only be moved from/to DREGS. */ - if (rclass == CCREGS && x_class != DREGS) - return DREGS; - if (x_class == CCREGS && rclass != DREGS) - return DREGS; - - /* All registers other than AREGS can load arbitrary constants. The only - case that remains is MEM. */ - if (code == MEM) - if (! reg_class_subset_p (rclass, default_class)) - return default_class; - - return NO_REGS; -} - -/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ - -static bool -bfin_class_likely_spilled_p (reg_class_t rclass) -{ - switch (rclass) - { - case PREGS_CLOBBERED: - case PROLOGUE_REGS: - case P0REGS: - case D0REGS: - case D1REGS: - case D2REGS: - case CCREGS: - return true; - - default: - break; - } - - return false; -} - -static struct machine_function * -bfin_init_machine_status (void) -{ - return ggc_alloc_cleared_machine_function (); -} - -/* Implement the TARGET_OPTION_OVERRIDE hook. */ - -static void -bfin_option_override (void) -{ - /* If processor type is not specified, enable all workarounds. */ - if (bfin_cpu_type == BFIN_CPU_UNKNOWN) - { - int i; - - for (i = 0; bfin_cpus[i].name != NULL; i++) - bfin_workarounds |= bfin_cpus[i].workarounds; - - bfin_si_revision = 0xffff; - } - - if (bfin_csync_anomaly == 1) - bfin_workarounds |= WA_SPECULATIVE_SYNCS; - else if (bfin_csync_anomaly == 0) - bfin_workarounds &= ~WA_SPECULATIVE_SYNCS; - - if (bfin_specld_anomaly == 1) - bfin_workarounds |= WA_SPECULATIVE_LOADS; - else if (bfin_specld_anomaly == 0) - bfin_workarounds &= ~WA_SPECULATIVE_LOADS; - - if (TARGET_OMIT_LEAF_FRAME_POINTER) - flag_omit_frame_pointer = 1; - -#ifdef SUBTARGET_FDPIC_NOT_SUPPORTED - if (TARGET_FDPIC) - error ("-mfdpic is not supported, please use a bfin-linux-uclibc target"); -#endif - - /* Library identification */ - if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY) - error ("-mshared-library-id= specified without -mid-shared-library"); - - if (stack_limit_rtx && TARGET_FDPIC) - { - warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1"); - stack_limit_rtx = NULL_RTX; - } - - if (stack_limit_rtx && TARGET_STACK_CHECK_L1) - error ("can%'t use multiple stack checking methods together"); - - if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC) - error ("ID shared libraries and FD-PIC mode can%'t be used together"); - - /* Don't allow the user to specify -mid-shared-library and -msep-data - together, as it makes little sense from a user's point of view... */ - if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY) - error ("cannot specify both -msep-data and -mid-shared-library"); - /* ... internally, however, it's nearly the same. */ - if (TARGET_SEP_DATA) - target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY; - - if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0) - flag_pic = 1; - - /* There is no single unaligned SI op for PIC code. Sometimes we - need to use ".4byte" and sometimes we need to use ".picptr". - See bfin_assemble_integer for details. */ - if (TARGET_FDPIC) - targetm.asm_out.unaligned_op.si = 0; - - /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries, - since we don't support it and it'll just break. */ - if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY) - flag_pic = 0; - - if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561) - error ("-mmulticore can only be used with BF561"); - - if (TARGET_COREA && !TARGET_MULTICORE) - error ("-mcorea should be used with -mmulticore"); - - if (TARGET_COREB && !TARGET_MULTICORE) - error ("-mcoreb should be used with -mmulticore"); - - if (TARGET_COREA && TARGET_COREB) - error ("-mcorea and -mcoreb can%'t be used together"); - - flag_schedule_insns = 0; - - init_machine_status = bfin_init_machine_status; -} - -/* Return the destination address of BRANCH. - We need to use this instead of get_attr_length, because the - cbranch_with_nops pattern conservatively sets its length to 6, and - we still prefer to use shorter sequences. */ - -static int -branch_dest (rtx branch) -{ - rtx dest; - int dest_uid; - rtx pat = PATTERN (branch); - if (GET_CODE (pat) == PARALLEL) - pat = XVECEXP (pat, 0, 0); - dest = SET_SRC (pat); - if (GET_CODE (dest) == IF_THEN_ELSE) - dest = XEXP (dest, 1); - dest = XEXP (dest, 0); - dest_uid = INSN_UID (dest); - return INSN_ADDRESSES (dest_uid); -} - -/* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates - it's a branch that's predicted taken. */ - -static int -cbranch_predicted_taken_p (rtx insn) -{ - rtx x = find_reg_note (insn, REG_BR_PROB, 0); - - if (x) - { - int pred_val = INTVAL (XEXP (x, 0)); - - return pred_val >= REG_BR_PROB_BASE / 2; - } - - return 0; -} - -/* Templates for use by asm_conditional_branch. */ - -static const char *ccbranch_templates[][3] = { - { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" }, - { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" }, - { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" }, - { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" }, -}; - -/* Output INSN, which is a conditional branch instruction with operands - OPERANDS. - - We deal with the various forms of conditional branches that can be generated - by bfin_reorg to prevent the hardware from doing speculative loads, by - - emitting a sufficient number of nops, if N_NOPS is nonzero, or - - always emitting the branch as predicted taken, if PREDICT_TAKEN is true. - Either of these is only necessary if the branch is short, otherwise the - template we use ends in an unconditional jump which flushes the pipeline - anyway. */ - -void -asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken) -{ - int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn)); - /* Note : offset for instructions like if cc jmp; jump.[sl] offset - is to be taken from start of if cc rather than jump. - Range for jump.s is (-4094, 4096) instead of (-4096, 4094) - */ - int len = (offset >= -1024 && offset <= 1022 ? 0 - : offset >= -4094 && offset <= 4096 ? 1 - : 2); - int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn); - int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT); - output_asm_insn (ccbranch_templates[idx][len], operands); - gcc_assert (n_nops == 0 || !bp); - if (len == 0) - while (n_nops-- > 0) - output_asm_insn ("nop;", NULL); -} - -/* Emit rtl for a comparison operation CMP in mode MODE. Operands have been - stored in bfin_compare_op0 and bfin_compare_op1 already. */ - -rtx -bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - enum rtx_code code1, code2; - rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1); - rtx tem = bfin_cc_rtx; - enum rtx_code code = GET_CODE (cmp); - - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (op0) == BImode) - { - gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx); - tem = op0, code2 = code; - } - else - { - switch (code) { - /* bfin has these conditions */ - case EQ: - case LT: - case LE: - case LEU: - case LTU: - code1 = code; - code2 = NE; - break; - default: - code1 = reverse_condition (code); - code2 = EQ; - break; - } - emit_insn (gen_rtx_SET (VOIDmode, tem, - gen_rtx_fmt_ee (code1, BImode, op0, op1))); - } - - return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode)); -} - -/* Return nonzero iff C has exactly one bit set if it is interpreted - as a 32-bit constant. */ - -int -log2constp (unsigned HOST_WIDE_INT c) -{ - c &= 0xFFFFFFFF; - return c != 0 && (c & (c-1)) == 0; -} - -/* Returns the number of consecutive least significant zeros in the binary - representation of *V. - We modify *V to contain the original value arithmetically shifted right by - the number of zeroes. */ - -static int -shiftr_zero (HOST_WIDE_INT *v) -{ - unsigned HOST_WIDE_INT tmp = *v; - unsigned HOST_WIDE_INT sgn; - int n = 0; - - if (tmp == 0) - return 0; - - sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)); - while ((tmp & 0x1) == 0 && n <= 32) - { - tmp = (tmp >> 1) | sgn; - n++; - } - *v = tmp; - return n; -} - -/* After reload, split the load of an immediate constant. OPERANDS are the - operands of the movsi_insn pattern which we are splitting. We return - nonzero if we emitted a sequence to load the constant, zero if we emitted - nothing because we want to use the splitter's default sequence. */ - -int -split_load_immediate (rtx operands[]) -{ - HOST_WIDE_INT val = INTVAL (operands[1]); - HOST_WIDE_INT tmp; - HOST_WIDE_INT shifted = val; - HOST_WIDE_INT shifted_compl = ~val; - int num_zero = shiftr_zero (&shifted); - int num_compl_zero = shiftr_zero (&shifted_compl); - unsigned int regno = REGNO (operands[0]); - - /* This case takes care of single-bit set/clear constants, which we could - also implement with BITSET/BITCLR. */ - if (num_zero - && shifted >= -32768 && shifted < 65536 - && (D_REGNO_P (regno) - || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2))) - { - emit_insn (gen_movsi (operands[0], GEN_INT (shifted))); - emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero))); - return 1; - } - - tmp = val & 0xFFFF; - tmp |= -(tmp & 0x8000); - - /* If high word has one bit set or clear, try to use a bit operation. */ - if (D_REGNO_P (regno)) - { - if (log2constp (val & 0xFFFF0000)) - { - emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF))); - emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000))); - return 1; - } - else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0) - { - emit_insn (gen_movsi (operands[0], GEN_INT (tmp))); - emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF))); - } - } - - if (D_REGNO_P (regno)) - { - if (tmp >= -64 && tmp <= 63) - { - emit_insn (gen_movsi (operands[0], GEN_INT (tmp))); - emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536))); - return 1; - } - - if ((val & 0xFFFF0000) == 0) - { - emit_insn (gen_movsi (operands[0], const0_rtx)); - emit_insn (gen_movsi_low (operands[0], operands[0], operands[1])); - return 1; - } - - if ((val & 0xFFFF0000) == 0xFFFF0000) - { - emit_insn (gen_movsi (operands[0], constm1_rtx)); - emit_insn (gen_movsi_low (operands[0], operands[0], operands[1])); - return 1; - } - } - - /* Need DREGs for the remaining case. */ - if (regno > REG_R7) - return 0; - - if (optimize_size - && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63) - { - /* If optimizing for size, generate a sequence that has more instructions - but is shorter. */ - emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl))); - emit_insn (gen_ashlsi3 (operands[0], operands[0], - GEN_INT (num_compl_zero))); - emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); - return 1; - } - return 0; -} - -/* Return true if the legitimate memory address for a memory operand of mode - MODE. Return false if not. */ - -static bool -bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value) -{ - unsigned HOST_WIDE_INT v = value > 0 ? value : -value; - int sz = GET_MODE_SIZE (mode); - int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2; - /* The usual offsettable_memref machinery doesn't work so well for this - port, so we deal with the problem here. */ - if (value > 0 && sz == 8) - v += 4; - return (v & ~(0x7fff << shift)) == 0; -} - -static bool -bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode, - enum rtx_code outer_code) -{ - if (strict) - return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH); - else - return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH); -} - -/* Recognize an RTL expression that is a valid memory address for an - instruction. The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - Blackfin addressing modes are as follows: - - [preg] - [preg + imm16] - - B [ Preg + uimm15 ] - W [ Preg + uimm16m2 ] - [ Preg + uimm17m4 ] - - [preg++] - [preg--] - [--sp] -*/ - -static bool -bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) -{ - switch (GET_CODE (x)) { - case REG: - if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM)) - return true; - break; - case PLUS: - if (REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS) - && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode) - || (GET_CODE (XEXP (x, 1)) == CONST_INT - && bfin_valid_add (mode, INTVAL (XEXP (x, 1)))))) - return true; - break; - case POST_INC: - case POST_DEC: - if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode) - && REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC)) - return true; - case PRE_DEC: - if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode) - && XEXP (x, 0) == stack_pointer_rtx - && REG_P (XEXP (x, 0)) - && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC)) - return true; - break; - default: - break; - } - return false; -} - -/* Decide whether we can force certain constants to memory. If we - decide we can't, the caller should be able to cope with it in - another way. */ - -static bool -bfin_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, - rtx x ATTRIBUTE_UNUSED) -{ - /* We have only one class of non-legitimate constants, and our movsi - expander knows how to handle them. Dropping these constants into the - data section would only shift the problem - we'd still get relocs - outside the object, in the data section rather than the text section. */ - return true; -} - -/* Ensure that for any constant of the form symbol + offset, the offset - remains within the object. Any other constants are ok. - This ensures that flat binaries never have to deal with relocations - crossing section boundaries. */ - -static bool -bfin_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) -{ - rtx sym; - HOST_WIDE_INT offset; - - if (GET_CODE (x) != CONST) - return true; - - x = XEXP (x, 0); - gcc_assert (GET_CODE (x) == PLUS); - - sym = XEXP (x, 0); - x = XEXP (x, 1); - if (GET_CODE (sym) != SYMBOL_REF - || GET_CODE (x) != CONST_INT) - return true; - offset = INTVAL (x); - - if (SYMBOL_REF_DECL (sym) == 0) - return true; - if (offset < 0 - || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym)))) - return false; - - return true; -} - -static bool -bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total, - bool speed) -{ - enum rtx_code code = (enum rtx_code) code_i; - enum rtx_code outer_code = (enum rtx_code) outer_code_i; - int cost2 = COSTS_N_INSNS (1); - rtx op0, op1; - - switch (code) - { - case CONST_INT: - if (outer_code == SET || outer_code == PLUS) - *total = satisfies_constraint_Ks7 (x) ? 0 : cost2; - else if (outer_code == AND) - *total = log2constp (~INTVAL (x)) ? 0 : cost2; - else if (outer_code == LE || outer_code == LT || outer_code == EQ) - *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2; - else if (outer_code == LEU || outer_code == LTU) - *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2; - else if (outer_code == MULT) - *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2; - else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2)) - *total = 0; - else if (outer_code == ASHIFT || outer_code == ASHIFTRT - || outer_code == LSHIFTRT) - *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2; - else if (outer_code == IOR || outer_code == XOR) - *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2; - else - *total = cost2; - return true; - - case CONST: - case LABEL_REF: - case SYMBOL_REF: - case CONST_DOUBLE: - *total = COSTS_N_INSNS (2); - return true; - - case PLUS: - op0 = XEXP (x, 0); - op1 = XEXP (x, 1); - if (GET_MODE (x) == SImode) - { - if (GET_CODE (op0) == MULT - && GET_CODE (XEXP (op0, 1)) == CONST_INT) - { - HOST_WIDE_INT val = INTVAL (XEXP (op0, 1)); - if (val == 2 || val == 4) - { - *total = cost2; - *total += rtx_cost (XEXP (op0, 0), outer_code, opno, speed); - *total += rtx_cost (op1, outer_code, opno, speed); - return true; - } - } - *total = cost2; - if (GET_CODE (op0) != REG - && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG)) - *total += set_src_cost (op0, speed); -#if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer - towards creating too many induction variables. */ - if (!reg_or_7bit_operand (op1, SImode)) - *total += set_src_cost (op1, speed); -#endif - } - else if (GET_MODE (x) == DImode) - { - *total = 6 * cost2; - if (GET_CODE (op1) != CONST_INT - || !satisfies_constraint_Ks7 (op1)) - *total += rtx_cost (op1, PLUS, 1, speed); - if (GET_CODE (op0) != REG - && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG)) - *total += rtx_cost (op0, PLUS, 0, speed); - } - return true; - - case MINUS: - if (GET_MODE (x) == DImode) - *total = 6 * cost2; - else - *total = cost2; - return true; - - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - if (GET_MODE (x) == DImode) - *total = 6 * cost2; - else - *total = cost2; - - op0 = XEXP (x, 0); - op1 = XEXP (x, 1); - if (GET_CODE (op0) != REG - && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG)) - *total += rtx_cost (op0, code, 0, speed); - - return true; - - case IOR: - case AND: - case XOR: - op0 = XEXP (x, 0); - op1 = XEXP (x, 1); - - /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */ - if (code == IOR) - { - if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT) - || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND) - || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT) - || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT)) - { - *total = cost2; - return true; - } - } - - if (GET_CODE (op0) != REG - && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG)) - *total += rtx_cost (op0, code, 0, speed); - - if (GET_MODE (x) == DImode) - { - *total = 2 * cost2; - return true; - } - *total = cost2; - if (GET_MODE (x) != SImode) - return true; - - if (code == AND) - { - if (! rhs_andsi3_operand (XEXP (x, 1), SImode)) - *total += rtx_cost (XEXP (x, 1), code, 1, speed); - } - else - { - if (! regorlog2_operand (XEXP (x, 1), SImode)) - *total += rtx_cost (XEXP (x, 1), code, 1, speed); - } - - return true; - - case ZERO_EXTRACT: - case SIGN_EXTRACT: - if (outer_code == SET - && XEXP (x, 1) == const1_rtx - && GET_CODE (XEXP (x, 2)) == CONST_INT) - { - *total = 2 * cost2; - return true; - } - /* fall through */ - - case SIGN_EXTEND: - case ZERO_EXTEND: - *total = cost2; - return true; - - case MULT: - { - op0 = XEXP (x, 0); - op1 = XEXP (x, 1); - if (GET_CODE (op0) == GET_CODE (op1) - && (GET_CODE (op0) == ZERO_EXTEND - || GET_CODE (op0) == SIGN_EXTEND)) - { - *total = COSTS_N_INSNS (1); - op0 = XEXP (op0, 0); - op1 = XEXP (op1, 0); - } - else if (!speed) - *total = COSTS_N_INSNS (1); - else - *total = COSTS_N_INSNS (3); - - if (GET_CODE (op0) != REG - && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG)) - *total += rtx_cost (op0, MULT, 0, speed); - if (GET_CODE (op1) != REG - && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG)) - *total += rtx_cost (op1, MULT, 1, speed); - } - return true; - - case UDIV: - case UMOD: - *total = COSTS_N_INSNS (32); - return true; - - case VEC_CONCAT: - case VEC_SELECT: - if (outer_code == SET) - *total = cost2; - return true; - - default: - return false; - } -} - -/* Used for communication between {push,pop}_multiple_operation (which - we use not only as a predicate) and the corresponding output functions. */ -static int first_preg_to_save, first_dreg_to_save; -static int n_regs_to_save; - -int -push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int lastdreg = 8, lastpreg = 6; - int i, group; - - first_preg_to_save = lastpreg; - first_dreg_to_save = lastdreg; - for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++) - { - rtx t = XVECEXP (op, 0, i); - rtx src, dest; - int regno; - - if (GET_CODE (t) != SET) - return 0; - - src = SET_SRC (t); - dest = SET_DEST (t); - if (GET_CODE (dest) != MEM || ! REG_P (src)) - return 0; - dest = XEXP (dest, 0); - if (GET_CODE (dest) != PLUS - || ! REG_P (XEXP (dest, 0)) - || REGNO (XEXP (dest, 0)) != REG_SP - || GET_CODE (XEXP (dest, 1)) != CONST_INT - || INTVAL (XEXP (dest, 1)) != -i * 4) - return 0; - - regno = REGNO (src); - if (group == 0) - { - if (D_REGNO_P (regno)) - { - group = 1; - first_dreg_to_save = lastdreg = regno - REG_R0; - } - else if (regno >= REG_P0 && regno <= REG_P7) - { - group = 2; - first_preg_to_save = lastpreg = regno - REG_P0; - } - else - return 0; - - continue; - } - - if (group == 1) - { - if (regno >= REG_P0 && regno <= REG_P7) - { - group = 2; - first_preg_to_save = lastpreg = regno - REG_P0; - } - else if (regno != REG_R0 + lastdreg + 1) - return 0; - else - lastdreg++; - } - else if (group == 2) - { - if (regno != REG_P0 + lastpreg + 1) - return 0; - lastpreg++; - } - } - n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save; - return 1; -} - -int -pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int lastdreg = 8, lastpreg = 6; - int i, group; - - for (i = 1, group = 0; i < XVECLEN (op, 0); i++) - { - rtx t = XVECEXP (op, 0, i); - rtx src, dest; - int regno; - - if (GET_CODE (t) != SET) - return 0; - - src = SET_SRC (t); - dest = SET_DEST (t); - if (GET_CODE (src) != MEM || ! REG_P (dest)) - return 0; - src = XEXP (src, 0); - - if (i == 1) - { - if (! REG_P (src) || REGNO (src) != REG_SP) - return 0; - } - else if (GET_CODE (src) != PLUS - || ! REG_P (XEXP (src, 0)) - || REGNO (XEXP (src, 0)) != REG_SP - || GET_CODE (XEXP (src, 1)) != CONST_INT - || INTVAL (XEXP (src, 1)) != (i - 1) * 4) - return 0; - - regno = REGNO (dest); - if (group == 0) - { - if (regno == REG_R7) - { - group = 1; - lastdreg = 7; - } - else if (regno != REG_P0 + lastpreg - 1) - return 0; - else - lastpreg--; - } - else if (group == 1) - { - if (regno != REG_R0 + lastdreg - 1) - return 0; - else - lastdreg--; - } - } - first_dreg_to_save = lastdreg; - first_preg_to_save = lastpreg; - n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save; - return 1; -} - -/* Emit assembly code for one multi-register push described by INSN, with - operands in OPERANDS. */ - -void -output_push_multiple (rtx insn, rtx *operands) -{ - char buf[80]; - int ok; - - /* Validate the insn again, and compute first_[dp]reg_to_save. */ - ok = push_multiple_operation (PATTERN (insn), VOIDmode); - gcc_assert (ok); - - if (first_dreg_to_save == 8) - sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save); - else if (first_preg_to_save == 6) - sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save); - else - sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n", - first_dreg_to_save, first_preg_to_save); - - output_asm_insn (buf, operands); -} - -/* Emit assembly code for one multi-register pop described by INSN, with - operands in OPERANDS. */ - -void -output_pop_multiple (rtx insn, rtx *operands) -{ - char buf[80]; - int ok; - - /* Validate the insn again, and compute first_[dp]reg_to_save. */ - ok = pop_multiple_operation (PATTERN (insn), VOIDmode); - gcc_assert (ok); - - if (first_dreg_to_save == 8) - sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save); - else if (first_preg_to_save == 6) - sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save); - else - sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n", - first_dreg_to_save, first_preg_to_save); - - output_asm_insn (buf, operands); -} - -/* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */ - -static void -single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset) -{ - rtx scratch = gen_reg_rtx (mode); - rtx srcmem, dstmem; - - srcmem = adjust_address_nv (src, mode, offset); - dstmem = adjust_address_nv (dst, mode, offset); - emit_move_insn (scratch, srcmem); - emit_move_insn (dstmem, scratch); -} - -/* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with - alignment ALIGN_EXP. Return true if successful, false if we should fall - back on a different method. */ - -bool -bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp) -{ - rtx srcreg, destreg, countreg; - HOST_WIDE_INT align = 0; - unsigned HOST_WIDE_INT count = 0; - - if (GET_CODE (align_exp) == CONST_INT) - align = INTVAL (align_exp); - if (GET_CODE (count_exp) == CONST_INT) - { - count = INTVAL (count_exp); -#if 0 - if (!TARGET_INLINE_ALL_STRINGOPS && count > 64) - return false; -#endif - } - - /* If optimizing for size, only do single copies inline. */ - if (optimize_size) - { - if (count == 2 && align < 2) - return false; - if (count == 4 && align < 4) - return false; - if (count != 1 && count != 2 && count != 4) - return false; - } - if (align < 2 && count != 1) - return false; - - destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0)); - if (destreg != XEXP (dst, 0)) - dst = replace_equiv_address_nv (dst, destreg); - srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0)); - if (srcreg != XEXP (src, 0)) - src = replace_equiv_address_nv (src, srcreg); - - if (count != 0 && align >= 2) - { - unsigned HOST_WIDE_INT offset = 0; - - if (align >= 4) - { - if ((count & ~3) == 4) - { - single_move_for_movmem (dst, src, SImode, offset); - offset = 4; - } - else if (count & ~3) - { - HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1; - countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count)); - - emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg)); - cfun->machine->has_loopreg_clobber = true; - } - if (count & 2) - { - single_move_for_movmem (dst, src, HImode, offset); - offset += 2; - } - } - else - { - if ((count & ~1) == 2) - { - single_move_for_movmem (dst, src, HImode, offset); - offset = 2; - } - else if (count & ~1) - { - HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1; - countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count)); - - emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg)); - cfun->machine->has_loopreg_clobber = true; - } - } - if (count & 1) - { - single_move_for_movmem (dst, src, QImode, offset); - } - return true; - } - return false; -} - -/* Compute the alignment for a local variable. - TYPE is the data type, and ALIGN is the alignment that - the object would ordinarily have. The value of this macro is used - instead of that alignment to align the object. */ - -unsigned -bfin_local_alignment (tree type, unsigned align) -{ - /* Increasing alignment for (relatively) big types allows the builtin - memcpy can use 32 bit loads/stores. */ - if (TYPE_SIZE (type) - && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8 - || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32) - return 32; - return align; -} - -/* Implement TARGET_SCHED_ISSUE_RATE. */ - -static int -bfin_issue_rate (void) -{ - return 3; -} - -static int -bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost) -{ - enum attr_type dep_insn_type; - int dep_insn_code_number; - - /* Anti and output dependencies have zero cost. */ - if (REG_NOTE_KIND (link) != 0) - return 0; - - dep_insn_code_number = recog_memoized (dep_insn); - - /* If we can't recognize the insns, we can't really do anything. */ - if (dep_insn_code_number < 0 || recog_memoized (insn) < 0) - return cost; - - dep_insn_type = get_attr_type (dep_insn); - - if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD) - { - rtx pat = PATTERN (dep_insn); - rtx dest, src; - - if (GET_CODE (pat) == PARALLEL) - pat = XVECEXP (pat, 0, 0); - dest = SET_DEST (pat); - src = SET_SRC (pat); - if (! ADDRESS_REGNO_P (REGNO (dest)) - || ! (MEM_P (src) || D_REGNO_P (REGNO (src)))) - return cost; - return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3); - } - - return cost; -} - -/* This function acts like NEXT_INSN, but is aware of three-insn bundles and - skips all subsequent parallel instructions if INSN is the start of such - a group. */ -static rtx -find_next_insn_start (rtx insn) -{ - if (GET_MODE (insn) == SImode) - { - while (GET_MODE (insn) != QImode) - insn = NEXT_INSN (insn); - } - return NEXT_INSN (insn); -} - -/* This function acts like PREV_INSN, but is aware of three-insn bundles and - skips all subsequent parallel instructions if INSN is the start of such - a group. */ -static rtx -find_prev_insn_start (rtx insn) -{ - insn = PREV_INSN (insn); - gcc_assert (GET_MODE (insn) != SImode); - if (GET_MODE (insn) == QImode) - { - while (GET_MODE (PREV_INSN (insn)) == SImode) - insn = PREV_INSN (insn); - } - return insn; -} - -/* Increment the counter for the number of loop instructions in the - current function. */ - -void -bfin_hardware_loop (void) -{ - cfun->machine->has_hardware_loops++; -} - -/* Maximum loop nesting depth. */ -#define MAX_LOOP_DEPTH 2 - -/* Maximum size of a loop. */ -#define MAX_LOOP_LENGTH 2042 - -/* Maximum distance of the LSETUP instruction from the loop start. */ -#define MAX_LSETUP_DISTANCE 30 - -/* Estimate the length of INSN conservatively. */ - -static int -length_for_loop (rtx insn) -{ - int length = 0; - if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size) - { - if (ENABLE_WA_SPECULATIVE_SYNCS) - length = 8; - else if (ENABLE_WA_SPECULATIVE_LOADS) - length = 6; - } - else if (LABEL_P (insn)) - { - if (ENABLE_WA_SPECULATIVE_SYNCS) - length = 4; - } - - if (NONDEBUG_INSN_P (insn)) - length += get_attr_length (insn); - - return length; -} - -/* Optimize LOOP. */ - -static bool -hwloop_optimize (hwloop_info loop) -{ - basic_block bb; - hwloop_info inner; - rtx insn, last_insn; - rtx loop_init, start_label, end_label; - rtx iter_reg, scratchreg, scratch_init, scratch_init_insn; - rtx lc_reg, lt_reg, lb_reg; - rtx seq, seq_end; - int length; - unsigned ix; - bool clobber0, clobber1; - - if (loop->depth > MAX_LOOP_DEPTH) - { - if (dump_file) - fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no); - return false; - } - - /* Get the loop iteration register. */ - iter_reg = loop->iter_reg; - - gcc_assert (REG_P (iter_reg)); - - scratchreg = NULL_RTX; - scratch_init = iter_reg; - scratch_init_insn = NULL_RTX; - if (!PREG_P (iter_reg) && loop->incoming_src) - { - basic_block bb_in = loop->incoming_src; - int i; - for (i = REG_P0; i <= REG_P5; i++) - if ((df_regs_ever_live_p (i) - || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE - && call_used_regs[i])) - && !REGNO_REG_SET_P (df_get_live_out (bb_in), i)) - { - scratchreg = gen_rtx_REG (SImode, i); - break; - } - for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in); - insn = PREV_INSN (insn)) - { - rtx set; - if (NOTE_P (insn) || BARRIER_P (insn)) - continue; - set = single_set (insn); - if (set && rtx_equal_p (SET_DEST (set), iter_reg)) - { - if (CONSTANT_P (SET_SRC (set))) - { - scratch_init = SET_SRC (set); - scratch_init_insn = insn; - } - break; - } - else if (reg_mentioned_p (iter_reg, PATTERN (insn))) - break; - } - } - - if (loop->incoming_src) - { - /* Make sure the predecessor is before the loop start label, as required by - the LSETUP instruction. */ - length = 0; - insn = BB_END (loop->incoming_src); - /* If we have to insert the LSETUP before a jump, count that jump in the - length. */ - if (VEC_length (edge, loop->incoming) > 1 - || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU)) - { - gcc_assert (JUMP_P (insn)); - insn = PREV_INSN (insn); - } - - for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn)) - length += length_for_loop (insn); - - if (!insn) - { - if (dump_file) - fprintf (dump_file, ";; loop %d lsetup not before loop_start\n", - loop->loop_no); - return false; - } - - /* Account for the pop of a scratch register where necessary. */ - if (!PREG_P (iter_reg) && scratchreg == NULL_RTX - && ENABLE_WA_LOAD_LCREGS) - length += 2; - - if (length > MAX_LSETUP_DISTANCE) - { - if (dump_file) - fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no); - return false; - } - } - - /* Check if start_label appears before loop_end and calculate the - offset between them. We calculate the length of instructions - conservatively. */ - length = 0; - for (insn = loop->start_label; - insn && insn != loop->loop_end; - insn = NEXT_INSN (insn)) - length += length_for_loop (insn); - - if (!insn) - { - if (dump_file) - fprintf (dump_file, ";; loop %d start_label not before loop_end\n", - loop->loop_no); - return false; - } - - loop->length = length; - if (loop->length > MAX_LOOP_LENGTH) - { - if (dump_file) - fprintf (dump_file, ";; loop %d too long\n", loop->loop_no); - return false; - } - - /* Scan all the blocks to make sure they don't use iter_reg. */ - if (loop->iter_reg_used || loop->iter_reg_used_outside) - { - if (dump_file) - fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no); - return false; - } - - clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0) - || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0) - || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0)); - clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1) - || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1) - || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1)); - if (clobber0 && clobber1) - { - if (dump_file) - fprintf (dump_file, ";; loop %d no loop reg available\n", - loop->loop_no); - return false; - } - - /* There should be an instruction before the loop_end instruction - in the same basic block. And the instruction must not be - - JUMP - - CONDITIONAL BRANCH - - CALL - - CSYNC - - SSYNC - - Returns (RTS, RTN, etc.) */ - - bb = loop->tail; - last_insn = find_prev_insn_start (loop->loop_end); - - while (1) - { - for (; last_insn != BB_HEAD (bb); - last_insn = find_prev_insn_start (last_insn)) - if (NONDEBUG_INSN_P (last_insn)) - break; - - if (last_insn != BB_HEAD (bb)) - break; - - if (single_pred_p (bb) - && single_pred_edge (bb)->flags & EDGE_FALLTHRU - && single_pred (bb) != ENTRY_BLOCK_PTR) - { - bb = single_pred (bb); - last_insn = BB_END (bb); - continue; - } - else - { - last_insn = NULL_RTX; - break; - } - } - - if (!last_insn) - { - if (dump_file) - fprintf (dump_file, ";; loop %d has no last instruction\n", - loop->loop_no); - return false; - } - - if (JUMP_P (last_insn) && !any_condjump_p (last_insn)) - { - if (dump_file) - fprintf (dump_file, ";; loop %d has bad last instruction\n", - loop->loop_no); - return false; - } - /* In all other cases, try to replace a bad last insn with a nop. */ - else if (JUMP_P (last_insn) - || CALL_P (last_insn) - || get_attr_type (last_insn) == TYPE_SYNC - || get_attr_type (last_insn) == TYPE_CALL - || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI - || recog_memoized (last_insn) == CODE_FOR_return_internal - || GET_CODE (PATTERN (last_insn)) == ASM_INPUT - || asm_noperands (PATTERN (last_insn)) >= 0) - { - if (loop->length + 2 > MAX_LOOP_LENGTH) - { - if (dump_file) - fprintf (dump_file, ";; loop %d too long\n", loop->loop_no); - return false; - } - if (dump_file) - fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n", - loop->loop_no); - - last_insn = emit_insn_after (gen_forced_nop (), last_insn); - } - - loop->last_insn = last_insn; - - /* The loop is good for replacement. */ - start_label = loop->start_label; - end_label = gen_label_rtx (); - iter_reg = loop->iter_reg; - - if (loop->depth == 1 && !clobber1) - { - lc_reg = gen_rtx_REG (SImode, REG_LC1); - lb_reg = gen_rtx_REG (SImode, REG_LB1); - lt_reg = gen_rtx_REG (SImode, REG_LT1); - SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1); - } - else - { - lc_reg = gen_rtx_REG (SImode, REG_LC0); - lb_reg = gen_rtx_REG (SImode, REG_LB0); - lt_reg = gen_rtx_REG (SImode, REG_LT0); - SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0); - } - - loop->end_label = end_label; - - /* Create a sequence containing the loop setup. */ - start_sequence (); - - /* LSETUP only accepts P registers. If we have one, we can use it, - otherwise there are several ways of working around the problem. - If we're not affected by anomaly 312, we can load the LC register - from any iteration register, and use LSETUP without initialization. - If we've found a P scratch register that's not live here, we can - instead copy the iter_reg into that and use an initializing LSETUP. - If all else fails, push and pop P0 and use it as a scratch. */ - if (P_REGNO_P (REGNO (iter_reg))) - { - loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, - lb_reg, end_label, - lc_reg, iter_reg); - seq_end = emit_insn (loop_init); - } - else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg)) - { - emit_insn (gen_movsi (lc_reg, iter_reg)); - loop_init = gen_lsetup_without_autoinit (lt_reg, start_label, - lb_reg, end_label, - lc_reg); - seq_end = emit_insn (loop_init); - } - else if (scratchreg != NULL_RTX) - { - emit_insn (gen_movsi (scratchreg, scratch_init)); - loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, - lb_reg, end_label, - lc_reg, scratchreg); - seq_end = emit_insn (loop_init); - if (scratch_init_insn != NULL_RTX) - delete_insn (scratch_init_insn); - } - else - { - rtx p0reg = gen_rtx_REG (SImode, REG_P0); - rtx push = gen_frame_mem (SImode, - gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)); - rtx pop = gen_frame_mem (SImode, - gen_rtx_POST_INC (SImode, stack_pointer_rtx)); - emit_insn (gen_movsi (push, p0reg)); - emit_insn (gen_movsi (p0reg, scratch_init)); - loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, - lb_reg, end_label, - lc_reg, p0reg); - emit_insn (loop_init); - seq_end = emit_insn (gen_movsi (p0reg, pop)); - if (scratch_init_insn != NULL_RTX) - delete_insn (scratch_init_insn); - } - - if (dump_file) - { - fprintf (dump_file, ";; replacing loop %d initializer with\n", - loop->loop_no); - print_rtl_single (dump_file, loop_init); - fprintf (dump_file, ";; replacing loop %d terminator with\n", - loop->loop_no); - print_rtl_single (dump_file, loop->loop_end); - } - - /* If the loop isn't entered at the top, also create a jump to the entry - point. */ - if (!loop->incoming_src && loop->head != loop->incoming_dest) - { - rtx label = BB_HEAD (loop->incoming_dest); - /* If we're jumping to the final basic block in the loop, and there's - only one cheap instruction before the end (typically an increment of - an induction variable), we can just emit a copy here instead of a - jump. */ - if (loop->incoming_dest == loop->tail - && next_real_insn (label) == last_insn - && asm_noperands (last_insn) < 0 - && GET_CODE (PATTERN (last_insn)) == SET) - { - seq_end = emit_insn (copy_rtx (PATTERN (last_insn))); - } - else - { - emit_jump_insn (gen_jump (label)); - seq_end = emit_barrier (); - } - } - - seq = get_insns (); - end_sequence (); - - if (loop->incoming_src) - { - rtx prev = BB_END (loop->incoming_src); - if (VEC_length (edge, loop->incoming) > 1 - || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU)) - { - gcc_assert (JUMP_P (prev)); - prev = PREV_INSN (prev); - } - emit_insn_after (seq, prev); - } - else - { - basic_block new_bb; - edge e; - edge_iterator ei; - -#ifdef ENABLE_CHECKING - if (loop->head != loop->incoming_dest) - { - /* We aren't entering the loop at the top. Since we've established - that the loop is entered only at one point, this means there - can't be fallthru edges into the head. Any such fallthru edges - would become invalid when we insert the new block, so verify - that this does not in fact happen. */ - FOR_EACH_EDGE (e, ei, loop->head->preds) - gcc_assert (!(e->flags & EDGE_FALLTHRU)); - } -#endif - - emit_insn_before (seq, BB_HEAD (loop->head)); - seq = emit_label_before (gen_label_rtx (), seq); - - new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb); - FOR_EACH_EDGE (e, ei, loop->incoming) - { - if (!(e->flags & EDGE_FALLTHRU) - || e->dest != loop->head) - redirect_edge_and_branch_force (e, new_bb); - else - redirect_edge_succ (e, new_bb); - } - e = make_edge (new_bb, loop->head, 0); - } - - delete_insn (loop->loop_end); - /* Insert the loop end label before the last instruction of the loop. */ - emit_label_before (loop->end_label, loop->last_insn); - - return true; -} - -/* A callback for the hw-doloop pass. Called when a loop we have discovered - turns out not to be optimizable; we have to split the doloop_end pattern - into a subtract and a test. */ -static void -hwloop_fail (hwloop_info loop) -{ - rtx insn = loop->loop_end; - - if (DPREG_P (loop->iter_reg)) - { - /* If loop->iter_reg is a DREG or PREG, we can split it here - without scratch register. */ - rtx insn, test; - - emit_insn_before (gen_addsi3 (loop->iter_reg, - loop->iter_reg, - constm1_rtx), - loop->loop_end); - - test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx); - insn = emit_jump_insn_before (gen_cbranchsi4 (test, - loop->iter_reg, const0_rtx, - loop->start_label), - loop->loop_end); - - JUMP_LABEL (insn) = loop->start_label; - LABEL_NUSES (loop->start_label)++; - delete_insn (loop->loop_end); - } - else - { - splitting_loops = 1; - try_split (PATTERN (insn), insn, 1); - splitting_loops = 0; - } -} - -/* A callback for the hw-doloop pass. This function examines INSN; if - it is a loop_end pattern we recognize, return the reg rtx for the - loop counter. Otherwise, return NULL_RTX. */ - -static rtx -hwloop_pattern_reg (rtx insn) -{ - rtx pat, reg; - - if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end) - return NULL_RTX; - - pat = PATTERN (insn); - reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1)); - if (!REG_P (reg)) - return NULL_RTX; - return reg; -} - -static struct hw_doloop_hooks bfin_doloop_hooks = -{ - hwloop_pattern_reg, - hwloop_optimize, - hwloop_fail -}; - -/* Run from machine_dependent_reorg, this pass looks for doloop_end insns - and tries to rewrite the RTL of these loops so that proper Blackfin - hardware loops are generated. */ - -static void -bfin_reorg_loops (FILE *dump_file) -{ - reorg_loops (true, &bfin_doloop_hooks); -} - -/* Possibly generate a SEQUENCE out of three insns found in SLOT. - Returns true if we modified the insn chain, false otherwise. */ -static bool -gen_one_bundle (rtx slot[3]) -{ - gcc_assert (slot[1] != NULL_RTX); - - /* Don't add extra NOPs if optimizing for size. */ - if (optimize_size - && (slot[0] == NULL_RTX || slot[2] == NULL_RTX)) - return false; - - /* Verify that we really can do the multi-issue. */ - if (slot[0]) - { - rtx t = NEXT_INSN (slot[0]); - while (t != slot[1]) - { - if (GET_CODE (t) != NOTE - || NOTE_KIND (t) != NOTE_INSN_DELETED) - return false; - t = NEXT_INSN (t); - } - } - if (slot[2]) - { - rtx t = NEXT_INSN (slot[1]); - while (t != slot[2]) - { - if (GET_CODE (t) != NOTE - || NOTE_KIND (t) != NOTE_INSN_DELETED) - return false; - t = NEXT_INSN (t); - } - } - - if (slot[0] == NULL_RTX) - { - slot[0] = emit_insn_before (gen_mnop (), slot[1]); - df_insn_rescan (slot[0]); - } - if (slot[2] == NULL_RTX) - { - slot[2] = emit_insn_after (gen_forced_nop (), slot[1]); - df_insn_rescan (slot[2]); - } - - /* Avoid line number information being printed inside one bundle. */ - if (INSN_LOCATOR (slot[1]) - && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0])) - INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]); - if (INSN_LOCATOR (slot[2]) - && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0])) - INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]); - - /* Terminate them with "|| " instead of ";" in the output. */ - PUT_MODE (slot[0], SImode); - PUT_MODE (slot[1], SImode); - /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */ - PUT_MODE (slot[2], QImode); - return true; -} - -/* Go through all insns, and use the information generated during scheduling - to generate SEQUENCEs to represent bundles of instructions issued - simultaneously. */ - -static void -bfin_gen_bundles (void) -{ - basic_block bb; - FOR_EACH_BB (bb) - { - rtx insn, next; - rtx slot[3]; - int n_filled = 0; - - slot[0] = slot[1] = slot[2] = NULL_RTX; - for (insn = BB_HEAD (bb);; insn = next) - { - int at_end; - rtx delete_this = NULL_RTX; - - if (NONDEBUG_INSN_P (insn)) - { - enum attr_type type = get_attr_type (insn); - - if (type == TYPE_STALL) - { - gcc_assert (n_filled == 0); - delete_this = insn; - } - else - { - if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM) - slot[0] = insn; - else if (slot[1] == NULL_RTX) - slot[1] = insn; - else - slot[2] = insn; - n_filled++; - } - } - - next = NEXT_INSN (insn); - while (next && insn != BB_END (bb) - && !(INSN_P (next) - && GET_CODE (PATTERN (next)) != USE - && GET_CODE (PATTERN (next)) != CLOBBER)) - { - insn = next; - next = NEXT_INSN (insn); - } - - /* BB_END can change due to emitting extra NOPs, so check here. */ - at_end = insn == BB_END (bb); - if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode)) - { - if ((n_filled < 2 - || !gen_one_bundle (slot)) - && slot[0] != NULL_RTX) - { - rtx pat = PATTERN (slot[0]); - if (GET_CODE (pat) == SET - && GET_CODE (SET_SRC (pat)) == UNSPEC - && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT) - { - SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0); - INSN_CODE (slot[0]) = -1; - df_insn_rescan (slot[0]); - } - } - n_filled = 0; - slot[0] = slot[1] = slot[2] = NULL_RTX; - } - if (delete_this != NULL_RTX) - delete_insn (delete_this); - if (at_end) - break; - } - } -} - -/* Ensure that no var tracking notes are emitted in the middle of a - three-instruction bundle. */ - -static void -reorder_var_tracking_notes (void) -{ - basic_block bb; - FOR_EACH_BB (bb) - { - rtx insn, next; - rtx queue = NULL_RTX; - bool in_bundle = false; - - for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next) - { - next = NEXT_INSN (insn); - - if (INSN_P (insn)) - { - /* Emit queued up notes at the last instruction of a bundle. */ - if (GET_MODE (insn) == QImode) - { - while (queue) - { - rtx next_queue = PREV_INSN (queue); - PREV_INSN (NEXT_INSN (insn)) = queue; - NEXT_INSN (queue) = NEXT_INSN (insn); - NEXT_INSN (insn) = queue; - PREV_INSN (queue) = insn; - queue = next_queue; - } - in_bundle = false; - } - else if (GET_MODE (insn) == SImode) - in_bundle = true; - } - else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION) - { - if (in_bundle) - { - rtx prev = PREV_INSN (insn); - PREV_INSN (next) = prev; - NEXT_INSN (prev) = next; - - PREV_INSN (insn) = queue; - queue = insn; - } - } - } - } -} - -/* On some silicon revisions, functions shorter than a certain number of cycles - can cause unpredictable behaviour. Work around this by adding NOPs as - needed. */ -static void -workaround_rts_anomaly (void) -{ - rtx insn, first_insn = NULL_RTX; - int cycles = 4; - - if (! ENABLE_WA_RETS) - return; - - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - rtx pat; - - if (BARRIER_P (insn)) - return; - - if (NOTE_P (insn) || LABEL_P (insn)) - continue; - - if (first_insn == NULL_RTX) - first_insn = insn; - pat = PATTERN (insn); - if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER - || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC - || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) - continue; - - if (CALL_P (insn)) - return; - - if (JUMP_P (insn)) - { - if (recog_memoized (insn) == CODE_FOR_return_internal) - break; - - /* Nothing to worry about for direct jumps. */ - if (!any_condjump_p (insn)) - return; - if (cycles <= 1) - return; - cycles--; - } - else if (INSN_P (insn)) - { - rtx pat = PATTERN (insn); - int this_cycles = 1; - - if (GET_CODE (pat) == PARALLEL) - { - if (push_multiple_operation (pat, VOIDmode) - || pop_multiple_operation (pat, VOIDmode)) - this_cycles = n_regs_to_save; - } - else - { - int icode = recog_memoized (insn); - - if (icode == CODE_FOR_link) - this_cycles = 4; - else if (icode == CODE_FOR_unlink) - this_cycles = 3; - else if (icode == CODE_FOR_mulsi3) - this_cycles = 5; - } - if (this_cycles >= cycles) - return; - - cycles -= this_cycles; - } - } - while (cycles > 0) - { - emit_insn_before (gen_nop (), first_insn); - cycles--; - } -} - -/* Return an insn type for INSN that can be used by the caller for anomaly - workarounds. This differs from plain get_attr_type in that it handles - SEQUENCEs. */ - -static enum attr_type -type_for_anomaly (rtx insn) -{ - rtx pat = PATTERN (insn); - if (GET_CODE (pat) == SEQUENCE) - { - enum attr_type t; - t = get_attr_type (XVECEXP (pat, 0, 1)); - if (t == TYPE_MCLD) - return t; - t = get_attr_type (XVECEXP (pat, 0, 2)); - if (t == TYPE_MCLD) - return t; - return TYPE_MCST; - } - else - return get_attr_type (insn); -} - -/* Return true iff the address found in MEM is based on the register - NP_REG and optionally has a positive offset. */ -static bool -harmless_null_pointer_p (rtx mem, int np_reg) -{ - mem = XEXP (mem, 0); - if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC) - mem = XEXP (mem, 0); - if (REG_P (mem) && (int) REGNO (mem) == np_reg) - return true; - if (GET_CODE (mem) == PLUS - && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg) - { - mem = XEXP (mem, 1); - if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0) - return true; - } - return false; -} - -/* Return nonzero if INSN contains any loads that may trap. */ - -static bool -trapping_loads_p (rtx insn, int np_reg, bool after_np_branch) -{ - rtx mem = SET_SRC (single_set (insn)); - - if (!after_np_branch) - np_reg = -1; - return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg)) - && may_trap_p (mem)); -} - -/* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of - a three-insn bundle, see if one of them is a load and return that if so. - Return NULL_RTX if the insn does not contain loads. */ -static rtx -find_load (rtx insn) -{ - if (!NONDEBUG_INSN_P (insn)) - return NULL_RTX; - if (get_attr_type (insn) == TYPE_MCLD) - return insn; - if (GET_MODE (insn) != SImode) - return NULL_RTX; - do { - insn = NEXT_INSN (insn); - if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode) - && get_attr_type (insn) == TYPE_MCLD) - return insn; - } while (GET_MODE (insn) != QImode); - return NULL_RTX; -} - -/* Determine whether PAT is an indirect call pattern. */ -static bool -indirect_call_p (rtx pat) -{ - if (GET_CODE (pat) == PARALLEL) - pat = XVECEXP (pat, 0, 0); - if (GET_CODE (pat) == SET) - pat = SET_SRC (pat); - gcc_assert (GET_CODE (pat) == CALL); - pat = XEXP (pat, 0); - gcc_assert (GET_CODE (pat) == MEM); - pat = XEXP (pat, 0); - - return REG_P (pat); -} - -/* During workaround_speculation, track whether we're in the shadow of a - conditional branch that tests a P register for NULL. If so, we can omit - emitting NOPs if we see a load from that P register, since a speculative - access at address 0 isn't a problem, and the load is executed in all other - cases anyway. - Global for communication with note_np_check_stores through note_stores. - */ -int np_check_regno = -1; -bool np_after_branch = false; - -/* Subroutine of workaround_speculation, called through note_stores. */ -static void -note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno)) - np_check_regno = -1; -} - -static void -workaround_speculation (void) -{ - rtx insn, next; - rtx last_condjump = NULL_RTX; - int cycles_since_jump = INT_MAX; - int delay_added = 0; - - if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS - && ! ENABLE_WA_INDIRECT_CALLS) - return; - - /* First pass: find predicted-false branches; if something after them - needs nops, insert them or change the branch to predict true. */ - for (insn = get_insns (); insn; insn = next) - { - rtx pat; - int delay_needed = 0; - - next = find_next_insn_start (insn); - - if (NOTE_P (insn) || BARRIER_P (insn)) - continue; - - if (LABEL_P (insn)) - { - np_check_regno = -1; - continue; - } - - pat = PATTERN (insn); - if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER - || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC) - continue; - - if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0) - { - np_check_regno = -1; - continue; - } - - if (JUMP_P (insn)) - { - /* Is this a condjump based on a null pointer comparison we saw - earlier? */ - if (np_check_regno != -1 - && recog_memoized (insn) == CODE_FOR_cbranchbi4) - { - rtx op = XEXP (SET_SRC (PATTERN (insn)), 0); - gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE); - if (GET_CODE (op) == NE) - np_after_branch = true; - } - if (any_condjump_p (insn) - && ! cbranch_predicted_taken_p (insn)) - { - last_condjump = insn; - delay_added = 0; - cycles_since_jump = 0; - } - else - cycles_since_jump = INT_MAX; - } - else if (CALL_P (insn)) - { - np_check_regno = -1; - if (cycles_since_jump < INT_MAX) - cycles_since_jump++; - if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS) - { - delay_needed = 3; - } - } - else if (NONDEBUG_INSN_P (insn)) - { - rtx load_insn = find_load (insn); - enum attr_type type = type_for_anomaly (insn); - - if (cycles_since_jump < INT_MAX) - cycles_since_jump++; - - /* Detect a comparison of a P register with zero. If we later - see a condjump based on it, we have found a null pointer - check. */ - if (recog_memoized (insn) == CODE_FOR_compare_eq) - { - rtx src = SET_SRC (PATTERN (insn)); - if (REG_P (XEXP (src, 0)) - && P_REGNO_P (REGNO (XEXP (src, 0))) - && XEXP (src, 1) == const0_rtx) - { - np_check_regno = REGNO (XEXP (src, 0)); - np_after_branch = false; - } - else - np_check_regno = -1; - } - - if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) - { - if (trapping_loads_p (load_insn, np_check_regno, - np_after_branch)) - delay_needed = 4; - } - else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) - delay_needed = 3; - - /* See if we need to forget about a null pointer comparison - we found earlier. */ - if (recog_memoized (insn) != CODE_FOR_compare_eq) - { - note_stores (PATTERN (insn), note_np_check_stores, NULL); - if (np_check_regno != -1) - { - if (find_regno_note (insn, REG_INC, np_check_regno)) - np_check_regno = -1; - } - } - - } - - if (delay_needed > cycles_since_jump - && (delay_needed - cycles_since_jump) > delay_added) - { - rtx pat1; - int num_clobbers; - rtx *op = recog_data.operand; - - delay_needed -= cycles_since_jump; - - extract_insn (last_condjump); - if (optimize_size) - { - pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2], - op[3]); - cycles_since_jump = INT_MAX; - } - else - { - /* Do not adjust cycles_since_jump in this case, so that - we'll increase the number of NOPs for a subsequent insn - if necessary. */ - pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3], - GEN_INT (delay_needed)); - delay_added = delay_needed; - } - PATTERN (last_condjump) = pat1; - INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers); - } - if (CALL_P (insn)) - { - cycles_since_jump = INT_MAX; - delay_added = 0; - } - } - - /* Second pass: for predicted-true branches, see if anything at the - branch destination needs extra nops. */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - int cycles_since_jump; - if (JUMP_P (insn) - && any_condjump_p (insn) - && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken - || cbranch_predicted_taken_p (insn))) - { - rtx target = JUMP_LABEL (insn); - rtx label = target; - rtx next_tgt; - - cycles_since_jump = 0; - for (; target && cycles_since_jump < 3; target = next_tgt) - { - rtx pat; - - next_tgt = find_next_insn_start (target); - - if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target)) - continue; - - pat = PATTERN (target); - if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER - || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC - || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) - continue; - - if (NONDEBUG_INSN_P (target)) - { - rtx load_insn = find_load (target); - enum attr_type type = type_for_anomaly (target); - int delay_needed = 0; - if (cycles_since_jump < INT_MAX) - cycles_since_jump++; - - if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) - { - if (trapping_loads_p (load_insn, -1, false)) - delay_needed = 2; - } - else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) - delay_needed = 2; - - if (delay_needed > cycles_since_jump) - { - rtx prev = prev_real_insn (label); - delay_needed -= cycles_since_jump; - if (dump_file) - fprintf (dump_file, "Adding %d nops after %d\n", - delay_needed, INSN_UID (label)); - if (JUMP_P (prev) - && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops) - { - rtx x; - HOST_WIDE_INT v; - - if (dump_file) - fprintf (dump_file, - "Reducing nops on insn %d.\n", - INSN_UID (prev)); - x = PATTERN (prev); - x = XVECEXP (x, 0, 1); - v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed; - XVECEXP (x, 0, 0) = GEN_INT (v); - } - while (delay_needed-- > 0) - emit_insn_after (gen_nop (), label); - break; - } - } - } - } - } -} - -/* Called just before the final scheduling pass. If we need to insert NOPs - later on to work around speculative loads, insert special placeholder - insns that cause loads to be delayed for as many cycles as necessary - (and possible). This reduces the number of NOPs we need to add. - The dummy insns we generate are later removed by bfin_gen_bundles. */ -static void -add_sched_insns_for_speculation (void) -{ - rtx insn; - - if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS - && ! ENABLE_WA_INDIRECT_CALLS) - return; - - /* First pass: find predicted-false branches; if something after them - needs nops, insert them or change the branch to predict true. */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - rtx pat; - - if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn)) - continue; - - pat = PATTERN (insn); - if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER - || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC - || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) - continue; - - if (JUMP_P (insn)) - { - if (any_condjump_p (insn) - && !cbranch_predicted_taken_p (insn)) - { - rtx n = next_real_insn (insn); - emit_insn_before (gen_stall (GEN_INT (3)), n); - } - } - } - - /* Second pass: for predicted-true branches, see if anything at the - branch destination needs extra nops. */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - if (JUMP_P (insn) - && any_condjump_p (insn) - && (cbranch_predicted_taken_p (insn))) - { - rtx target = JUMP_LABEL (insn); - rtx next = next_real_insn (target); - - if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE - && get_attr_type (next) == TYPE_STALL) - continue; - emit_insn_before (gen_stall (GEN_INT (1)), next); - } - } -} - -/* We use the machine specific reorg pass for emitting CSYNC instructions - after conditional branches as needed. - - The Blackfin is unusual in that a code sequence like - if cc jump label - r0 = (p0) - may speculatively perform the load even if the condition isn't true. This - happens for a branch that is predicted not taken, because the pipeline - isn't flushed or stalled, so the early stages of the following instructions, - which perform the memory reference, are allowed to execute before the - jump condition is evaluated. - Therefore, we must insert additional instructions in all places where this - could lead to incorrect behavior. The manual recommends CSYNC, while - VDSP seems to use NOPs (even though its corresponding compiler option is - named CSYNC). - - When optimizing for speed, we emit NOPs, which seems faster than a CSYNC. - When optimizing for size, we turn the branch into a predicted taken one. - This may be slower due to mispredicts, but saves code size. */ - -static void -bfin_reorg (void) -{ - /* We are freeing block_for_insn in the toplev to keep compatibility - with old MDEP_REORGS that are not CFG based. Recompute it now. */ - compute_bb_for_insn (); - - if (flag_schedule_insns_after_reload) - { - splitting_for_sched = 1; - split_all_insns (); - splitting_for_sched = 0; - - add_sched_insns_for_speculation (); - - timevar_push (TV_SCHED2); - if (flag_selective_scheduling2 - && !maybe_skip_selective_scheduling ()) - run_selective_scheduling (); - else - schedule_insns (); - timevar_pop (TV_SCHED2); - - /* Examine the schedule and insert nops as necessary for 64-bit parallel - instructions. */ - bfin_gen_bundles (); - } - - df_analyze (); - - /* Doloop optimization */ - if (cfun->machine->has_hardware_loops) - bfin_reorg_loops (dump_file); - - workaround_speculation (); - - if (flag_var_tracking) - { - timevar_push (TV_VAR_TRACKING); - variable_tracking_main (); - reorder_var_tracking_notes (); - timevar_pop (TV_VAR_TRACKING); - } - - df_finish_pass (false); - - workaround_rts_anomaly (); -} - -/* Handle interrupt_handler, exception_handler and nmi_handler function - attributes; arguments as in struct attribute_spec.handler. */ - -static tree -handle_int_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - tree x = *node; - if (TREE_CODE (x) == FUNCTION_DECL) - x = TREE_TYPE (x); - - if (TREE_CODE (x) != FUNCTION_TYPE) - { - warning (OPT_Wattributes, "%qE attribute only applies to functions", - name); - *no_add_attrs = true; - } - else if (funkind (x) != SUBROUTINE) - error ("multiple function type attributes specified"); - - return NULL_TREE; -} - -/* Return 0 if the attributes for two types are incompatible, 1 if they - are compatible, and 2 if they are nearly compatible (which causes a - warning to be generated). */ - -static int -bfin_comp_type_attributes (const_tree type1, const_tree type2) -{ - e_funkind kind1, kind2; - - if (TREE_CODE (type1) != FUNCTION_TYPE) - return 1; - - kind1 = funkind (type1); - kind2 = funkind (type2); - - if (kind1 != kind2) - return 0; - - /* Check for mismatched modifiers */ - if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2))) - return 0; - - if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2))) - return 0; - - if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2))) - return 0; - - if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2))) - return 0; - - return 1; -} - -/* Handle a "longcall" or "shortcall" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -bfin_handle_longcall_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FUNCTION_TYPE - && TREE_CODE (*node) != FIELD_DECL - && TREE_CODE (*node) != TYPE_DECL) - { - warning (OPT_Wattributes, "%qE attribute only applies to functions", - name); - *no_add_attrs = true; - } - - if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0 - && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node))) - || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0 - && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node)))) - { - warning (OPT_Wattributes, - "can%'t apply both longcall and shortcall attributes to the same function"); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "l1_text" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - tree decl = *node; - - if (TREE_CODE (decl) != FUNCTION_DECL) - { - error ("%qE attribute only applies to functions", - name); - *no_add_attrs = true; - } - - /* The decl may have already been given a section attribute - from a previous declaration. Ensure they match. */ - else if (DECL_SECTION_NAME (decl) != NULL_TREE - && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), - ".l1.text") != 0) - { - error ("section of %q+D conflicts with previous declaration", - decl); - *no_add_attrs = true; - } - else - DECL_SECTION_NAME (decl) = build_string (9, ".l1.text"); - - return NULL_TREE; -} - -/* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute; - arguments as in struct attribute_spec.handler. */ - -static tree -bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - tree decl = *node; - - if (TREE_CODE (decl) != VAR_DECL) - { - error ("%qE attribute only applies to variables", - name); - *no_add_attrs = true; - } - else if (current_function_decl != NULL_TREE - && !TREE_STATIC (decl)) - { - error ("%qE attribute cannot be specified for local variables", - name); - *no_add_attrs = true; - } - else - { - const char *section_name; - - if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0) - section_name = ".l1.data"; - else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0) - section_name = ".l1.data.A"; - else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0) - section_name = ".l1.data.B"; - else - gcc_unreachable (); - - /* The decl may have already been given a section attribute - from a previous declaration. Ensure they match. */ - if (DECL_SECTION_NAME (decl) != NULL_TREE - && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), - section_name) != 0) - { - error ("section of %q+D conflicts with previous declaration", - decl); - *no_add_attrs = true; - } - else - DECL_SECTION_NAME (decl) - = build_string (strlen (section_name) + 1, section_name); - } - - return NULL_TREE; -} - -/* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */ - -static tree -bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name), - tree ARG_UNUSED (args), int ARG_UNUSED (flags), - bool *no_add_attrs) -{ - tree decl = *node; - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (DECL_SECTION_NAME (decl) != NULL_TREE - && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), - ".l2.text") != 0) - { - error ("section of %q+D conflicts with previous declaration", - decl); - *no_add_attrs = true; - } - else - DECL_SECTION_NAME (decl) = build_string (9, ".l2.text"); - } - else if (TREE_CODE (decl) == VAR_DECL) - { - if (DECL_SECTION_NAME (decl) != NULL_TREE - && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), - ".l2.data") != 0) - { - error ("section of %q+D conflicts with previous declaration", - decl); - *no_add_attrs = true; - } - else - DECL_SECTION_NAME (decl) = build_string (9, ".l2.data"); - } - - return NULL_TREE; -} - -/* Table of valid machine attributes. */ -static const struct attribute_spec bfin_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute, - false }, - { "exception_handler", 0, 0, false, true, true, handle_int_attribute, - false }, - { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false }, - { "nesting", 0, 0, false, true, true, NULL, false }, - { "kspisusp", 0, 0, false, true, true, NULL, false }, - { "saveall", 0, 0, false, true, true, NULL, false }, - { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute, - false }, - { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute, - false }, - { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute, - false }, - { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute, - false }, - { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute, - false }, - { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute, - false }, - { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } -}; - -/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to - tell the assembler to generate pointers to function descriptors in - some cases. */ - -static bool -bfin_assemble_integer (rtx value, unsigned int size, int aligned_p) -{ - if (TARGET_FDPIC && size == UNITS_PER_WORD) - { - if (GET_CODE (value) == SYMBOL_REF - && SYMBOL_REF_FUNCTION_P (value)) - { - fputs ("\t.picptr\tfuncdesc(", asm_out_file); - output_addr_const (asm_out_file, value); - fputs (")\n", asm_out_file); - return true; - } - if (!aligned_p) - { - /* We've set the unaligned SI op to NULL, so we always have to - handle the unaligned case here. */ - assemble_integer_with_op ("\t.4byte\t", value); - return true; - } - } - return default_assemble_integer (value, size, aligned_p); -} - -/* Output the assembler code for a thunk function. THUNK_DECL is the - declaration for the thunk function itself, FUNCTION is the decl for - the target function. DELTA is an immediate constant offset to be - added to THIS. If VCALL_OFFSET is nonzero, the word at - *(*this + vcall_offset) should be added to THIS. */ - -static void -bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED, - tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta, - HOST_WIDE_INT vcall_offset, tree function) -{ - rtx xops[3]; - /* The this parameter is passed as the first argument. */ - rtx this_rtx = gen_rtx_REG (Pmode, REG_R0); - - /* Adjust the this parameter by a fixed constant. */ - if (delta) - { - xops[1] = this_rtx; - if (delta >= -64 && delta <= 63) - { - xops[0] = GEN_INT (delta); - output_asm_insn ("%1 += %0;", xops); - } - else if (delta >= -128 && delta < -64) - { - xops[0] = GEN_INT (delta + 64); - output_asm_insn ("%1 += -64; %1 += %0;", xops); - } - else if (delta > 63 && delta <= 126) - { - xops[0] = GEN_INT (delta - 63); - output_asm_insn ("%1 += 63; %1 += %0;", xops); - } - else - { - xops[0] = GEN_INT (delta); - output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops); - } - } - - /* Adjust the this parameter by a value stored in the vtable. */ - if (vcall_offset) - { - rtx p2tmp = gen_rtx_REG (Pmode, REG_P2); - rtx tmp = gen_rtx_REG (Pmode, REG_R3); - - xops[1] = tmp; - xops[2] = p2tmp; - output_asm_insn ("%2 = r0; %2 = [%2];", xops); - - /* Adjust the this parameter. */ - xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset)); - if (!memory_operand (xops[0], Pmode)) - { - rtx tmp2 = gen_rtx_REG (Pmode, REG_P1); - xops[0] = GEN_INT (vcall_offset); - xops[1] = tmp2; - output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops); - xops[0] = gen_rtx_MEM (Pmode, p2tmp); - } - xops[2] = this_rtx; - output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops); - } - - xops[0] = XEXP (DECL_RTL (function), 0); - if (1 || !flag_pic || (*targetm.binds_local_p) (function)) - output_asm_insn ("jump.l\t%P0", xops); -} - -/* Codes for all the Blackfin builtins. */ -enum bfin_builtins -{ - BFIN_BUILTIN_CSYNC, - BFIN_BUILTIN_SSYNC, - BFIN_BUILTIN_ONES, - BFIN_BUILTIN_COMPOSE_2X16, - BFIN_BUILTIN_EXTRACTLO, - BFIN_BUILTIN_EXTRACTHI, - - BFIN_BUILTIN_SSADD_2X16, - BFIN_BUILTIN_SSSUB_2X16, - BFIN_BUILTIN_SSADDSUB_2X16, - BFIN_BUILTIN_SSSUBADD_2X16, - BFIN_BUILTIN_MULT_2X16, - BFIN_BUILTIN_MULTR_2X16, - BFIN_BUILTIN_NEG_2X16, - BFIN_BUILTIN_ABS_2X16, - BFIN_BUILTIN_MIN_2X16, - BFIN_BUILTIN_MAX_2X16, - - BFIN_BUILTIN_SSADD_1X16, - BFIN_BUILTIN_SSSUB_1X16, - BFIN_BUILTIN_MULT_1X16, - BFIN_BUILTIN_MULTR_1X16, - BFIN_BUILTIN_NORM_1X16, - BFIN_BUILTIN_NEG_1X16, - BFIN_BUILTIN_ABS_1X16, - BFIN_BUILTIN_MIN_1X16, - BFIN_BUILTIN_MAX_1X16, - - BFIN_BUILTIN_SUM_2X16, - BFIN_BUILTIN_DIFFHL_2X16, - BFIN_BUILTIN_DIFFLH_2X16, - - BFIN_BUILTIN_SSADD_1X32, - BFIN_BUILTIN_SSSUB_1X32, - BFIN_BUILTIN_NORM_1X32, - BFIN_BUILTIN_ROUND_1X32, - BFIN_BUILTIN_NEG_1X32, - BFIN_BUILTIN_ABS_1X32, - BFIN_BUILTIN_MIN_1X32, - BFIN_BUILTIN_MAX_1X32, - BFIN_BUILTIN_MULT_1X32, - BFIN_BUILTIN_MULT_1X32X32, - BFIN_BUILTIN_MULT_1X32X32NS, - - BFIN_BUILTIN_MULHISILL, - BFIN_BUILTIN_MULHISILH, - BFIN_BUILTIN_MULHISIHL, - BFIN_BUILTIN_MULHISIHH, - - BFIN_BUILTIN_LSHIFT_1X16, - BFIN_BUILTIN_LSHIFT_2X16, - BFIN_BUILTIN_SSASHIFT_1X16, - BFIN_BUILTIN_SSASHIFT_2X16, - BFIN_BUILTIN_SSASHIFT_1X32, - - BFIN_BUILTIN_CPLX_MUL_16, - BFIN_BUILTIN_CPLX_MAC_16, - BFIN_BUILTIN_CPLX_MSU_16, - - BFIN_BUILTIN_CPLX_MUL_16_S40, - BFIN_BUILTIN_CPLX_MAC_16_S40, - BFIN_BUILTIN_CPLX_MSU_16_S40, - - BFIN_BUILTIN_CPLX_SQU, - - BFIN_BUILTIN_LOADBYTES, - - BFIN_BUILTIN_MAX -}; - -#define def_builtin(NAME, TYPE, CODE) \ -do { \ - add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \ - NULL, NULL_TREE); \ -} while (0) - -/* Set up all builtin functions for this target. */ -static void -bfin_init_builtins (void) -{ - tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode); - tree void_ftype_void - = build_function_type_list (void_type_node, NULL_TREE); - tree short_ftype_short - = build_function_type_list (short_integer_type_node, short_integer_type_node, - NULL_TREE); - tree short_ftype_int_int - = build_function_type_list (short_integer_type_node, integer_type_node, - integer_type_node, NULL_TREE); - tree int_ftype_int_int - = build_function_type_list (integer_type_node, integer_type_node, - integer_type_node, NULL_TREE); - tree int_ftype_int - = build_function_type_list (integer_type_node, integer_type_node, - NULL_TREE); - tree short_ftype_int - = build_function_type_list (short_integer_type_node, integer_type_node, - NULL_TREE); - tree int_ftype_v2hi_v2hi - = build_function_type_list (integer_type_node, V2HI_type_node, - V2HI_type_node, NULL_TREE); - tree v2hi_ftype_v2hi_v2hi - = build_function_type_list (V2HI_type_node, V2HI_type_node, - V2HI_type_node, NULL_TREE); - tree v2hi_ftype_v2hi_v2hi_v2hi - = build_function_type_list (V2HI_type_node, V2HI_type_node, - V2HI_type_node, V2HI_type_node, NULL_TREE); - tree v2hi_ftype_int_int - = build_function_type_list (V2HI_type_node, integer_type_node, - integer_type_node, NULL_TREE); - tree v2hi_ftype_v2hi_int - = build_function_type_list (V2HI_type_node, V2HI_type_node, - integer_type_node, NULL_TREE); - tree int_ftype_short_short - = build_function_type_list (integer_type_node, short_integer_type_node, - short_integer_type_node, NULL_TREE); - tree v2hi_ftype_v2hi - = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE); - tree short_ftype_v2hi - = build_function_type_list (short_integer_type_node, V2HI_type_node, - NULL_TREE); - tree int_ftype_pint - = build_function_type_list (integer_type_node, - build_pointer_type (integer_type_node), - NULL_TREE); - - /* Add the remaining MMX insns with somewhat more complicated types. */ - def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC); - def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC); - - def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES); - - def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int, - BFIN_BUILTIN_COMPOSE_2X16); - def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi, - BFIN_BUILTIN_EXTRACTHI); - def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi, - BFIN_BUILTIN_EXTRACTLO); - - def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_MIN_2X16); - def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_MAX_2X16); - - def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSADD_2X16); - def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSSUB_2X16); - def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSADDSUB_2X16); - def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSSUBADD_2X16); - def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULT_2X16); - def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULTR_2X16); - def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi, - BFIN_BUILTIN_NEG_2X16); - def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi, - BFIN_BUILTIN_ABS_2X16); - - def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_MIN_1X16); - def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_MAX_1X16); - - def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_SSADD_1X16); - def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_SSSUB_1X16); - def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_MULT_1X16); - def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_MULTR_1X16); - def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short, - BFIN_BUILTIN_NEG_1X16); - def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short, - BFIN_BUILTIN_ABS_1X16); - def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int, - BFIN_BUILTIN_NORM_1X16); - - def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi, - BFIN_BUILTIN_SUM_2X16); - def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi, - BFIN_BUILTIN_DIFFHL_2X16); - def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi, - BFIN_BUILTIN_DIFFLH_2X16); - - def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULHISILL); - def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULHISIHL); - def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULHISILH); - def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi, - BFIN_BUILTIN_MULHISIHH); - - def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int, - BFIN_BUILTIN_MIN_1X32); - def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int, - BFIN_BUILTIN_MAX_1X32); - - def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int, - BFIN_BUILTIN_SSADD_1X32); - def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int, - BFIN_BUILTIN_SSSUB_1X32); - def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int, - BFIN_BUILTIN_NEG_1X32); - def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int, - BFIN_BUILTIN_ABS_1X32); - def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int, - BFIN_BUILTIN_NORM_1X32); - def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int, - BFIN_BUILTIN_ROUND_1X32); - def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short, - BFIN_BUILTIN_MULT_1X32); - def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int, - BFIN_BUILTIN_MULT_1X32X32); - def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int, - BFIN_BUILTIN_MULT_1X32X32NS); - - /* Shifts. */ - def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_SSASHIFT_1X16); - def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int, - BFIN_BUILTIN_SSASHIFT_2X16); - def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int, - BFIN_BUILTIN_LSHIFT_1X16); - def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int, - BFIN_BUILTIN_LSHIFT_2X16); - def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int, - BFIN_BUILTIN_SSASHIFT_1X32); - - /* Complex numbers. */ - def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSADD_2X16); - def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_SSSUB_2X16); - def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MUL_16); - def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MAC_16); - def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MSU_16); - def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MUL_16_S40); - def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MAC_16_S40); - def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi, - BFIN_BUILTIN_CPLX_MSU_16_S40); - def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi, - BFIN_BUILTIN_CPLX_SQU); - - /* "Unaligned" load. */ - def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint, - BFIN_BUILTIN_LOADBYTES); - -} - - -struct builtin_description -{ - const enum insn_code icode; - const char *const name; - const enum bfin_builtins code; - int macflag; -}; - -static const struct builtin_description bdesc_2arg[] = -{ - { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 }, - - { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 }, - { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 }, - { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 }, - { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 }, - { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 }, - - { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 }, - { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 }, - { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 }, - { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 }, - - { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 }, - { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 }, - { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 }, - { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 }, - - { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 }, - { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 }, - { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 }, - { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 }, - { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 }, - { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 }, - - { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE }, - { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T }, - { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE }, - { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T }, - { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }, - - { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 }, - { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 }, - { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 }, - { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 } - -}; - -static const struct builtin_description bdesc_1arg[] = -{ - { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 }, - - { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 }, - - { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 }, - { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 }, - { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 }, - - { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 }, - { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 }, - { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 }, - { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 }, - - { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 }, - { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 }, - { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 }, - { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 } -}; - -/* Errors in the source file can cause expand_expr to return const0_rtx - where we expect a vector. To avoid crashing, use one of the vector - clear instructions. */ -static rtx -safe_vector_operand (rtx x, enum machine_mode mode) -{ - if (x != const0_rtx) - return x; - x = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (x, CONST0_RTX (SImode))); - return gen_lowpart (mode, x); -} - -/* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1 - if this is a normal binary op, or one of the MACFLAG_xxx constants. */ - -static rtx -bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target, - int macflag) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - enum machine_mode op0mode = GET_MODE (op0); - enum machine_mode op1mode = GET_MODE (op1); - enum machine_mode tmode = insn_data[icode].operand[0].mode; - enum machine_mode mode0 = insn_data[icode].operand[1].mode; - enum machine_mode mode1 = insn_data[icode].operand[2].mode; - - if (VECTOR_MODE_P (mode0)) - op0 = safe_vector_operand (op0, mode0); - if (VECTOR_MODE_P (mode1)) - op1 = safe_vector_operand (op1, mode1); - - if (! target - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode) - { - op0mode = HImode; - op0 = gen_lowpart (HImode, op0); - } - if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode) - { - op1mode = HImode; - op1 = gen_lowpart (HImode, op1); - } - /* In case the insn wants input operands in modes different from - the result, abort. */ - gcc_assert ((op0mode == mode0 || op0mode == VOIDmode) - && (op1mode == mode1 || op1mode == VOIDmode)); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - - if (macflag == -1) - pat = GEN_FCN (icode) (target, op0, op1); - else - pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag)); - if (! pat) - return 0; - - emit_insn (pat); - return target; -} - -/* Subroutine of bfin_expand_builtin to take care of unop insns. */ - -static rtx -bfin_expand_unop_builtin (enum insn_code icode, tree exp, - rtx target) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - enum machine_mode op0mode = GET_MODE (op0); - enum machine_mode tmode = insn_data[icode].operand[0].mode; - enum machine_mode mode0 = insn_data[icode].operand[1].mode; - - if (! target - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (VECTOR_MODE_P (mode0)) - op0 = safe_vector_operand (op0, mode0); - - if (op0mode == SImode && mode0 == HImode) - { - op0mode = HImode; - op0 = gen_lowpart (HImode, op0); - } - gcc_assert (op0mode == mode0 || op0mode == VOIDmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (target, op0); - if (! pat) - return 0; - emit_insn (pat); - return target; -} - -/* Expand an expression EXP that calls a built-in function, - with result going to TARGET if that's convenient - (and in mode MODE if that's convenient). - SUBTARGET may be used as the target for computing one of EXP's operands. - IGNORE is nonzero if the value is to be ignored. */ - -static rtx -bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, - rtx subtarget ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, - int ignore ATTRIBUTE_UNUSED) -{ - size_t i; - enum insn_code icode; - const struct builtin_description *d; - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - tree arg0, arg1, arg2; - rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg; - enum machine_mode tmode, mode0; - - switch (fcode) - { - case BFIN_BUILTIN_CSYNC: - emit_insn (gen_csync ()); - return 0; - case BFIN_BUILTIN_SSYNC: - emit_insn (gen_ssync ()); - return 0; - - case BFIN_BUILTIN_DIFFHL_2X16: - case BFIN_BUILTIN_DIFFLH_2X16: - case BFIN_BUILTIN_SUM_2X16: - arg0 = CALL_EXPR_ARG (exp, 0); - op0 = expand_normal (arg0); - icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3 - : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3 - : CODE_FOR_ssaddhilov2hi3); - tmode = insn_data[icode].operand[0].mode; - mode0 = insn_data[icode].operand[1].mode; - - if (! target - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (VECTOR_MODE_P (mode0)) - op0 = safe_vector_operand (op0, mode0); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (target, op0, op0); - if (! pat) - return 0; - emit_insn (pat); - return target; - - case BFIN_BUILTIN_MULT_1X32X32: - case BFIN_BUILTIN_MULT_1X32X32NS: - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - op0 = expand_normal (arg0); - op1 = expand_normal (arg1); - if (! target - || !register_operand (target, SImode)) - target = gen_reg_rtx (SImode); - if (! register_operand (op0, SImode)) - op0 = copy_to_mode_reg (SImode, op0); - if (! register_operand (op1, SImode)) - op1 = copy_to_mode_reg (SImode, op1); - - a1reg = gen_rtx_REG (PDImode, REG_A1); - a0reg = gen_rtx_REG (PDImode, REG_A0); - tmp1 = gen_lowpart (V2HImode, op0); - tmp2 = gen_lowpart (V2HImode, op1); - emit_insn (gen_flag_macinit1hi (a1reg, - gen_lowpart (HImode, op0), - gen_lowpart (HImode, op1), - GEN_INT (MACFLAG_FU))); - emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16))); - - if (fcode == BFIN_BUILTIN_MULT_1X32X32) - emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2, - const1_rtx, const1_rtx, - const1_rtx, const0_rtx, a1reg, - const0_rtx, GEN_INT (MACFLAG_NONE), - GEN_INT (MACFLAG_M))); - else - { - /* For saturating multiplication, there's exactly one special case - to be handled: multiplying the smallest negative value with - itself. Due to shift correction in fractional multiplies, this - can overflow. Iff this happens, OP2 will contain 1, which, when - added in 32 bits to the smallest negative, wraps to the largest - positive, which is the result we want. */ - op2 = gen_reg_rtx (V2HImode); - emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx)); - emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC), - gen_lowpart (SImode, op2))); - emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2, - const1_rtx, const1_rtx, - const1_rtx, const0_rtx, a1reg, - const0_rtx, GEN_INT (MACFLAG_NONE), - GEN_INT (MACFLAG_M))); - op2 = gen_reg_rtx (SImode); - emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC))); - } - emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1, - const1_rtx, const0_rtx, - a1reg, const0_rtx, GEN_INT (MACFLAG_M))); - emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15))); - emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg)); - if (fcode == BFIN_BUILTIN_MULT_1X32X32NS) - emit_insn (gen_addsi3 (target, target, op2)); - return target; - - case BFIN_BUILTIN_CPLX_MUL_16: - case BFIN_BUILTIN_CPLX_MUL_16_S40: - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - op0 = expand_normal (arg0); - op1 = expand_normal (arg1); - accvec = gen_reg_rtx (V2PDImode); - icode = CODE_FOR_flag_macv2hi_parts; - tmode = insn_data[icode].operand[0].mode; - - if (! target - || GET_MODE (target) != V2HImode - || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) - target = gen_reg_rtx (tmode); - if (! register_operand (op0, GET_MODE (op0))) - op0 = copy_to_mode_reg (GET_MODE (op0), op0); - if (! register_operand (op1, GET_MODE (op1))) - op1 = copy_to_mode_reg (GET_MODE (op1), op1); - - if (fcode == BFIN_BUILTIN_CPLX_MUL_16) - emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx, - const0_rtx, const0_rtx, - const1_rtx, GEN_INT (MACFLAG_W32))); - else - emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx, - const0_rtx, const0_rtx, - const1_rtx, GEN_INT (MACFLAG_NONE))); - emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx, - const1_rtx, const1_rtx, - const0_rtx, accvec, const1_rtx, const0_rtx, - GEN_INT (MACFLAG_NONE), accvec)); - - return target; - - case BFIN_BUILTIN_CPLX_MAC_16: - case BFIN_BUILTIN_CPLX_MSU_16: - case BFIN_BUILTIN_CPLX_MAC_16_S40: - case BFIN_BUILTIN_CPLX_MSU_16_S40: - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - arg2 = CALL_EXPR_ARG (exp, 2); - op0 = expand_normal (arg0); - op1 = expand_normal (arg1); - op2 = expand_normal (arg2); - accvec = gen_reg_rtx (V2PDImode); - icode = CODE_FOR_flag_macv2hi_parts; - tmode = insn_data[icode].operand[0].mode; - - if (! target - || GET_MODE (target) != V2HImode - || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) - target = gen_reg_rtx (tmode); - if (! register_operand (op1, GET_MODE (op1))) - op1 = copy_to_mode_reg (GET_MODE (op1), op1); - if (! register_operand (op2, GET_MODE (op2))) - op2 = copy_to_mode_reg (GET_MODE (op2), op2); - - tmp1 = gen_reg_rtx (SImode); - tmp2 = gen_reg_rtx (SImode); - emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16))); - emit_move_insn (tmp2, gen_lowpart (SImode, op0)); - emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx)); - emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2)); - if (fcode == BFIN_BUILTIN_CPLX_MAC_16 - || fcode == BFIN_BUILTIN_CPLX_MSU_16) - emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx, - const0_rtx, const0_rtx, - const1_rtx, accvec, const0_rtx, - const0_rtx, - GEN_INT (MACFLAG_W32))); - else - emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx, - const0_rtx, const0_rtx, - const1_rtx, accvec, const0_rtx, - const0_rtx, - GEN_INT (MACFLAG_NONE))); - if (fcode == BFIN_BUILTIN_CPLX_MAC_16 - || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40) - { - tmp1 = const1_rtx; - tmp2 = const0_rtx; - } - else - { - tmp1 = const0_rtx; - tmp2 = const1_rtx; - } - emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx, - const1_rtx, const1_rtx, - const0_rtx, accvec, tmp1, tmp2, - GEN_INT (MACFLAG_NONE), accvec)); - - return target; - - case BFIN_BUILTIN_CPLX_SQU: - arg0 = CALL_EXPR_ARG (exp, 0); - op0 = expand_normal (arg0); - accvec = gen_reg_rtx (V2PDImode); - icode = CODE_FOR_flag_mulv2hi; - tmp1 = gen_reg_rtx (V2HImode); - tmp2 = gen_reg_rtx (V2HImode); - - if (! target - || GET_MODE (target) != V2HImode - || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) - target = gen_reg_rtx (V2HImode); - if (! register_operand (op0, GET_MODE (op0))) - op0 = copy_to_mode_reg (GET_MODE (op0), op0); - - emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE))); - - emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0, - const0_rtx, const1_rtx, - GEN_INT (MACFLAG_NONE))); - - emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx, - const0_rtx)); - emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1, - const0_rtx, const1_rtx)); - - return target; - - default: - break; - } - - for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) - if (d->code == fcode) - return bfin_expand_binop_builtin (d->icode, exp, target, - d->macflag); - - for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) - if (d->code == fcode) - return bfin_expand_unop_builtin (d->icode, exp, target); - - gcc_unreachable (); -} - -static void -bfin_conditional_register_usage (void) -{ - /* initialize condition code flag register rtx */ - bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC); - bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS); - if (TARGET_FDPIC) - call_used_regs[FDPIC_REGNO] = 1; - if (!TARGET_FDPIC && flag_pic) - { - fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; - call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; - } -} - -#undef TARGET_INIT_BUILTINS -#define TARGET_INIT_BUILTINS bfin_init_builtins - -#undef TARGET_EXPAND_BUILTIN -#define TARGET_EXPAND_BUILTIN bfin_expand_builtin - -#undef TARGET_ASM_GLOBALIZE_LABEL -#define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label - -#undef TARGET_ASM_FILE_START -#define TARGET_ASM_FILE_START output_file_start - -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE bfin_attribute_table - -#undef TARGET_COMP_TYPE_ATTRIBUTES -#define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS bfin_rtx_costs - -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST bfin_address_cost - -#undef TARGET_REGISTER_MOVE_COST -#define TARGET_REGISTER_MOVE_COST bfin_register_move_cost - -#undef TARGET_MEMORY_MOVE_COST -#define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost - -#undef TARGET_ASM_INTEGER -#define TARGET_ASM_INTEGER bfin_assemble_integer - -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg - -#undef TARGET_FUNCTION_OK_FOR_SIBCALL -#define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall - -#undef TARGET_ASM_OUTPUT_MI_THUNK -#define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk -#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK -#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true - -#undef TARGET_SCHED_ADJUST_COST -#define TARGET_SCHED_ADJUST_COST bfin_adjust_cost - -#undef TARGET_SCHED_ISSUE_RATE -#define TARGET_SCHED_ISSUE_RATE bfin_issue_rate - -#undef TARGET_PROMOTE_FUNCTION_MODE -#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote - -#undef TARGET_ARG_PARTIAL_BYTES -#define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes - -#undef TARGET_FUNCTION_ARG -#define TARGET_FUNCTION_ARG bfin_function_arg - -#undef TARGET_FUNCTION_ARG_ADVANCE -#define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance - -#undef TARGET_PASS_BY_REFERENCE -#define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference - -#undef TARGET_SETUP_INCOMING_VARARGS -#define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs - -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx - -#undef TARGET_VECTOR_MODE_SUPPORTED_P -#define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p - -#undef TARGET_OPTION_OVERRIDE -#define TARGET_OPTION_OVERRIDE bfin_option_override - -#undef TARGET_SECONDARY_RELOAD -#define TARGET_SECONDARY_RELOAD bfin_secondary_reload - -#undef TARGET_CLASS_LIKELY_SPILLED_P -#define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p - -#undef TARGET_DELEGITIMIZE_ADDRESS -#define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address - -#undef TARGET_LEGITIMATE_CONSTANT_P -#define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p - -#undef TARGET_CANNOT_FORCE_CONST_MEM -#define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem - -#undef TARGET_RETURN_IN_MEMORY -#define TARGET_RETURN_IN_MEMORY bfin_return_in_memory - -#undef TARGET_LEGITIMATE_ADDRESS_P -#define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p - -#undef TARGET_FRAME_POINTER_REQUIRED -#define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required - -#undef TARGET_CAN_ELIMINATE -#define TARGET_CAN_ELIMINATE bfin_can_eliminate - -#undef TARGET_CONDITIONAL_REGISTER_USAGE -#define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage - -#undef TARGET_ASM_TRAMPOLINE_TEMPLATE -#define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template -#undef TARGET_TRAMPOLINE_INIT -#define TARGET_TRAMPOLINE_INIT bfin_trampoline_init - -#undef TARGET_EXTRA_LIVE_ON_ENTRY -#define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry - -/* Passes after sched2 can break the helpful TImode annotations that - haifa-sched puts on every insn. Just do scheduling in reorg. */ -#undef TARGET_DELAY_SCHED2 -#define TARGET_DELAY_SCHED2 true - -/* Variable tracking should be run after all optimizations which - change order of insns. It also needs a valid CFG. */ -#undef TARGET_DELAY_VARTRACK -#define TARGET_DELAY_VARTRACK true - -struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc-4.7/gcc/config/bfin/bfin.h b/gcc-4.7/gcc/config/bfin/bfin.h deleted file mode 100644 index cc3b14f50..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin.h +++ /dev/null @@ -1,1159 +0,0 @@ -/* Definitions for the Blackfin port. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - Contributed by Analog Devices. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef _BFIN_CONFIG -#define _BFIN_CONFIG - -#ifndef BFIN_OPTS_H -#include "config/bfin/bfin-opts.h" -#endif - -#define OBJECT_FORMAT_ELF - -#define BRT 1 -#define BRF 0 - -/* Predefinition in the preprocessor for this target machine */ -#ifndef TARGET_CPU_CPP_BUILTINS -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("bfin"); \ - builtin_define_std ("BFIN"); \ - builtin_define ("__ADSPBLACKFIN__"); \ - builtin_define ("__ADSPLPBLACKFIN__"); \ - \ - switch (bfin_cpu_type) \ - { \ - case BFIN_CPU_BF512: \ - builtin_define ("__ADSPBF512__"); \ - builtin_define ("__ADSPBF51x__"); \ - break; \ - case BFIN_CPU_BF514: \ - builtin_define ("__ADSPBF514__"); \ - builtin_define ("__ADSPBF51x__"); \ - break; \ - case BFIN_CPU_BF516: \ - builtin_define ("__ADSPBF516__"); \ - builtin_define ("__ADSPBF51x__"); \ - break; \ - case BFIN_CPU_BF518: \ - builtin_define ("__ADSPBF518__"); \ - builtin_define ("__ADSPBF51x__"); \ - break; \ - case BFIN_CPU_BF522: \ - builtin_define ("__ADSPBF522__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF523: \ - builtin_define ("__ADSPBF523__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF524: \ - builtin_define ("__ADSPBF524__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF525: \ - builtin_define ("__ADSPBF525__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF526: \ - builtin_define ("__ADSPBF526__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF527: \ - builtin_define ("__ADSPBF527__"); \ - builtin_define ("__ADSPBF52x__"); \ - break; \ - case BFIN_CPU_BF531: \ - builtin_define ("__ADSPBF531__"); \ - break; \ - case BFIN_CPU_BF532: \ - builtin_define ("__ADSPBF532__"); \ - break; \ - case BFIN_CPU_BF533: \ - builtin_define ("__ADSPBF533__"); \ - break; \ - case BFIN_CPU_BF534: \ - builtin_define ("__ADSPBF534__"); \ - break; \ - case BFIN_CPU_BF536: \ - builtin_define ("__ADSPBF536__"); \ - break; \ - case BFIN_CPU_BF537: \ - builtin_define ("__ADSPBF537__"); \ - break; \ - case BFIN_CPU_BF538: \ - builtin_define ("__ADSPBF538__"); \ - break; \ - case BFIN_CPU_BF539: \ - builtin_define ("__ADSPBF539__"); \ - break; \ - case BFIN_CPU_BF542M: \ - builtin_define ("__ADSPBF542M__"); \ - case BFIN_CPU_BF542: \ - builtin_define ("__ADSPBF542__"); \ - builtin_define ("__ADSPBF54x__"); \ - break; \ - case BFIN_CPU_BF544M: \ - builtin_define ("__ADSPBF544M__"); \ - case BFIN_CPU_BF544: \ - builtin_define ("__ADSPBF544__"); \ - builtin_define ("__ADSPBF54x__"); \ - break; \ - case BFIN_CPU_BF547M: \ - builtin_define ("__ADSPBF547M__"); \ - case BFIN_CPU_BF547: \ - builtin_define ("__ADSPBF547__"); \ - builtin_define ("__ADSPBF54x__"); \ - break; \ - case BFIN_CPU_BF548M: \ - builtin_define ("__ADSPBF548M__"); \ - case BFIN_CPU_BF548: \ - builtin_define ("__ADSPBF548__"); \ - builtin_define ("__ADSPBF54x__"); \ - break; \ - case BFIN_CPU_BF549M: \ - builtin_define ("__ADSPBF549M__"); \ - case BFIN_CPU_BF549: \ - builtin_define ("__ADSPBF549__"); \ - builtin_define ("__ADSPBF54x__"); \ - break; \ - case BFIN_CPU_BF561: \ - builtin_define ("__ADSPBF561__"); \ - break; \ - case BFIN_CPU_BF592: \ - builtin_define ("__ADSPBF592__"); \ - builtin_define ("__ADSPBF59x__"); \ - break; \ - } \ - \ - if (bfin_si_revision != -1) \ - { \ - /* space of 0xnnnn and a NUL */ \ - char *buf = XALLOCAVEC (char, 7); \ - \ - sprintf (buf, "0x%04x", bfin_si_revision); \ - builtin_define_with_value ("__SILICON_REVISION__", buf, 0); \ - } \ - \ - if (bfin_workarounds) \ - builtin_define ("__WORKAROUNDS_ENABLED"); \ - if (ENABLE_WA_SPECULATIVE_LOADS) \ - builtin_define ("__WORKAROUND_SPECULATIVE_LOADS"); \ - if (ENABLE_WA_SPECULATIVE_SYNCS) \ - builtin_define ("__WORKAROUND_SPECULATIVE_SYNCS"); \ - if (ENABLE_WA_INDIRECT_CALLS) \ - builtin_define ("__WORKAROUND_INDIRECT_CALLS"); \ - if (ENABLE_WA_RETS) \ - builtin_define ("__WORKAROUND_RETS"); \ - \ - if (TARGET_FDPIC) \ - { \ - builtin_define ("__BFIN_FDPIC__"); \ - builtin_define ("__FDPIC__"); \ - } \ - if (TARGET_ID_SHARED_LIBRARY \ - && !TARGET_SEP_DATA) \ - builtin_define ("__ID_SHARED_LIB__"); \ - if (flag_no_builtin) \ - builtin_define ("__NO_BUILTIN"); \ - if (TARGET_MULTICORE) \ - builtin_define ("__BFIN_MULTICORE"); \ - if (TARGET_COREA) \ - builtin_define ("__BFIN_COREA"); \ - if (TARGET_COREB) \ - builtin_define ("__BFIN_COREB"); \ - if (TARGET_SDRAM) \ - builtin_define ("__BFIN_SDRAM"); \ - } \ - while (0) -#endif - -#define DRIVER_SELF_SPECS SUBTARGET_DRIVER_SELF_SPECS "\ - %{mleaf-id-shared-library:%{!mid-shared-library:-mid-shared-library}} \ - %{mfdpic:%{!fpic:%{!fpie:%{!fPIC:%{!fPIE:\ - %{!fno-pic:%{!fno-pie:%{!fno-PIC:%{!fno-PIE:-fpie}}}}}}}}} \ -" -#ifndef SUBTARGET_DRIVER_SELF_SPECS -# define SUBTARGET_DRIVER_SELF_SPECS -#endif - -#define LINK_GCC_C_SEQUENCE_SPEC "\ - %{mfast-fp:-lbffastfp} %G %L %{mfast-fp:-lbffastfp} %G \ -" - -#undef ASM_SPEC -#define ASM_SPEC "\ - %{mno-fdpic:-mnopic} %{mfdpic}" - -#define LINK_SPEC "\ -%{h*} %{v:-V} \ -%{mfdpic:-melf32bfinfd -z text} \ -%{static:-dn -Bstatic} \ -%{shared:-G -Bdynamic} \ -%{symbolic:-Bsymbolic} \ --init __init -fini __fini " - -/* Generate DSP instructions, like DSP halfword loads */ -#define TARGET_DSP (1) - -#define TARGET_DEFAULT 0 - -/* Maximum number of library ids we permit */ -#define MAX_LIBRARY_ID 255 - -extern const char *bfin_library_id_string; - -#define FUNCTION_MODE SImode -#define Pmode SImode - -/* store-condition-codes instructions store 0 for false - This is the value stored for true. */ -#define STORE_FLAG_VALUE 1 - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -#define STACK_PUSH_CODE PRE_DEC - -/* Define this to nonzero if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD 1 - -/* We define a dummy ARGP register; the parameters start at offset 0 from - it. */ -#define FIRST_PARM_OFFSET(DECL) 0 - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM REG_P6 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM REG_P7 - -/* A dummy register that will be eliminated to either FP or SP. */ -#define ARG_POINTER_REGNUM REG_ARGP - -/* `PIC_OFFSET_TABLE_REGNUM' - The register number of the register used to address a table of - static data addresses in memory. In some cases this register is - defined by a processor's "application binary interface" (ABI). - When this macro is defined, RTL is generated for this register - once, as with the stack pointer and frame pointer registers. If - this macro is not defined, it is up to the machine-dependent files - to allocate such a register (if necessary). */ -#define PIC_OFFSET_TABLE_REGNUM (REG_P5) - -#define FDPIC_FPTR_REGNO REG_P1 -#define FDPIC_REGNO REG_P3 -#define OUR_FDPIC_REG get_hard_reg_initial_val (SImode, FDPIC_REGNO) - -/* A static chain register for nested functions. We need to use a - call-clobbered register for this. */ -#define STATIC_CHAIN_REGNUM REG_P2 - -/* Define this if functions should assume that stack space has been - allocated for arguments even when their values are passed in - registers. - - The value of this macro is the size, in bytes, of the area reserved for - arguments passed in registers. - - This space can either be allocated by the caller or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' - says which. */ -#define FIXED_STACK_AREA 12 -#define REG_PARM_STACK_SPACE(FNDECL) FIXED_STACK_AREA - -/* Define this if the above stack space is to be considered part of the - * space allocated by the caller. */ -#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 - -/* Define this if the maximum size of all the outgoing args is to be - accumulated and pushed during the prologue. The amount can be - found in the variable crtl->outgoing_args_size. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/*#define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) for arrays.. */ - -/* If defined, a C expression to compute the alignment for a local - variable. TYPE is the data type, and ALIGN is the alignment that - the object would ordinarily have. The value of this macro is used - instead of that alignment to align the object. - - If this macro is not defined, then ALIGN is used. - - One use of this macro is to increase alignment of medium-size - data to make it all fit in fewer cache lines. */ - -#define LOCAL_ALIGNMENT(TYPE, ALIGN) bfin_local_alignment ((TYPE), (ALIGN)) - -/* Make strings word-aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -#define TRAMPOLINE_SIZE (TARGET_FDPIC ? 30 : 18) - -/* Definitions for register eliminations. - - This is an array of structures. Each structure initializes one pair - of eliminable registers. The "from" register number is given first, - followed by "to". Eliminations of the same "from" register are listed - in order of preference. - - There are two registers that can always be eliminated on the i386. - The frame pointer and the arg pointer can be replaced by either the - hard frame pointer or to the stack pointer, depending upon the - circumstances. The hard frame pointer is not used before reload and - so it is not eligible for elimination. */ - -#define ELIMINABLE_REGS \ -{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} \ - -/* Define the offset between two registers, one to be eliminated, and the other - its replacement, at the start of a routine. */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - ((OFFSET) = bfin_initial_elimination_offset ((FROM), (TO))) - -/* This processor has - 8 data register for doing arithmetic - 8 pointer register for doing addressing, including - 1 stack pointer P6 - 1 frame pointer P7 - 4 sets of indexing registers (I0-3, B0-3, L0-3, M0-3) - 1 condition code flag register CC - 5 return address registers RETS/I/X/N/E - 1 arithmetic status register (ASTAT). */ - -#define FIRST_PSEUDO_REGISTER 50 - -#define D_REGNO_P(X) ((X) <= REG_R7) -#define P_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_P7) -#define I_REGNO_P(X) ((X) >= REG_I0 && (X) <= REG_I3) -#define DP_REGNO_P(X) (D_REGNO_P (X) || P_REGNO_P (X)) -#define ADDRESS_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_M3) -#define DREG_P(X) (REG_P (X) && D_REGNO_P (REGNO (X))) -#define PREG_P(X) (REG_P (X) && P_REGNO_P (REGNO (X))) -#define IREG_P(X) (REG_P (X) && I_REGNO_P (REGNO (X))) -#define DPREG_P(X) (REG_P (X) && DP_REGNO_P (REGNO (X))) - -#define REGISTER_NAMES { \ - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", \ - "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP", \ - "I0", "I1", "I2", "I3", "B0", "B1", "B2", "B3", \ - "L0", "L1", "L2", "L3", "M0", "M1", "M2", "M3", \ - "A0", "A1", \ - "CC", \ - "RETS", "RETI", "RETX", "RETN", "RETE", "ASTAT", "SEQSTAT", "USP", \ - "ARGP", \ - "LT0", "LT1", "LC0", "LC1", "LB0", "LB1" \ -} - -#define SHORT_REGISTER_NAMES { \ - "R0.L", "R1.L", "R2.L", "R3.L", "R4.L", "R5.L", "R6.L", "R7.L", \ - "P0.L", "P1.L", "P2.L", "P3.L", "P4.L", "P5.L", "SP.L", "FP.L", \ - "I0.L", "I1.L", "I2.L", "I3.L", "B0.L", "B1.L", "B2.L", "B3.L", \ - "L0.L", "L1.L", "L2.L", "L3.L", "M0.L", "M1.L", "M2.L", "M3.L", } - -#define HIGH_REGISTER_NAMES { \ - "R0.H", "R1.H", "R2.H", "R3.H", "R4.H", "R5.H", "R6.H", "R7.H", \ - "P0.H", "P1.H", "P2.H", "P3.H", "P4.H", "P5.H", "SP.H", "FP.H", \ - "I0.H", "I1.H", "I2.H", "I3.H", "B0.H", "B1.H", "B2.H", "B3.H", \ - "L0.H", "L1.H", "L2.H", "L3.H", "M0.H", "M1.H", "M2.H", "M3.H", } - -#define DREGS_PAIR_NAMES { \ - "R1:0.p", 0, "R3:2.p", 0, "R5:4.p", 0, "R7:6.p", 0, } - -#define BYTE_REGISTER_NAMES { \ - "R0.B", "R1.B", "R2.B", "R3.B", "R4.B", "R5.B", "R6.B", "R7.B", } - - -/* 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 p0 p1 p2 p3 p4 p5 p6 p7 */ \ -{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, \ -/*i0 i1 i2 i3 b0 b1 b2 b3 l0 l1 l2 l3 m0 m1 m2 m3 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, \ -/*a0 a1 cc rets/i/x/n/e astat seqstat usp argp lt0/1 lc0/1 */ \ - 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -/*lb0/1 */ \ - 1, 1 \ -} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ - -#define CALL_USED_REGISTERS \ -/*r0 r1 r2 r3 r4 r5 r6 r7 p0 p1 p2 p3 p4 p5 p6 p7 */ \ -{ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, \ -/*i0 i1 i2 i3 b0 b1 b2 b3 l0 l1 l2 l3 m0 m1 m2 m3 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -/*a0 a1 cc rets/i/x/n/e astat seqstat usp argp lt0/1 lc0/1 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -/*lb0/1 */ \ - 1, 1 \ -} - -/* Order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. List frame pointer - late and fixed registers last. Note that, in general, we prefer - registers listed in CALL_USED_REGISTERS, keeping the others - available for storage of persistent values. */ - -#define REG_ALLOC_ORDER \ -{ REG_R0, REG_R1, REG_R2, REG_R3, REG_R7, REG_R6, REG_R5, REG_R4, \ - REG_P2, REG_P1, REG_P0, REG_P5, REG_P4, REG_P3, REG_P6, REG_P7, \ - REG_A0, REG_A1, \ - REG_I0, REG_I1, REG_I2, REG_I3, REG_B0, REG_B1, REG_B2, REG_B3, \ - REG_L0, REG_L1, REG_L2, REG_L3, REG_M0, REG_M1, REG_M2, REG_M3, \ - REG_RETS, REG_RETI, REG_RETX, REG_RETN, REG_RETE, \ - REG_ASTAT, REG_SEQSTAT, REG_USP, \ - REG_CC, REG_ARGP, \ - REG_LT0, REG_LT1, REG_LC0, REG_LC1, REG_LB0, REG_LB1 \ -} - -/* 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, - IREGS, - BREGS, - LREGS, - MREGS, - CIRCREGS, /* Circular buffering registers, Ix, Bx, Lx together form. See Automatic Circular Buffering. */ - DAGREGS, - EVEN_AREGS, - ODD_AREGS, - AREGS, - CCREGS, - EVEN_DREGS, - ODD_DREGS, - D0REGS, - D1REGS, - D2REGS, - D3REGS, - D4REGS, - D5REGS, - D6REGS, - D7REGS, - DREGS, - P0REGS, - FDPIC_REGS, - FDPIC_FPTR_REGS, - PREGS_CLOBBERED, - PREGS, - IPREGS, - DPREGS, - MOST_REGS, - LT_REGS, - LC_REGS, - LB_REGS, - PROLOGUE_REGS, - NON_A_CC_REGS, - ALL_REGS, LIM_REG_CLASSES -}; - -#define N_REG_CLASSES ((int)LIM_REG_CLASSES) - -#define GENERAL_REGS DPREGS - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ -{ "NO_REGS", \ - "IREGS", \ - "BREGS", \ - "LREGS", \ - "MREGS", \ - "CIRCREGS", \ - "DAGREGS", \ - "EVEN_AREGS", \ - "ODD_AREGS", \ - "AREGS", \ - "CCREGS", \ - "EVEN_DREGS", \ - "ODD_DREGS", \ - "D0REGS", \ - "D1REGS", \ - "D2REGS", \ - "D3REGS", \ - "D4REGS", \ - "D5REGS", \ - "D6REGS", \ - "D7REGS", \ - "DREGS", \ - "P0REGS", \ - "FDPIC_REGS", \ - "FDPIC_FPTR_REGS", \ - "PREGS_CLOBBERED", \ - "PREGS", \ - "IPREGS", \ - "DPREGS", \ - "MOST_REGS", \ - "LT_REGS", \ - "LC_REGS", \ - "LB_REGS", \ - "PROLOGUE_REGS", \ - "NON_A_CC_REGS", \ - "ALL_REGS" } - -/* An initializer containing the contents of the register classes, as integers - which are bit masks. The Nth integer specifies the contents of class N. - The way the integer MASK is interpreted is that register R is in the class - if `MASK & (1 << R)' is 1. - - When the machine has more than 32 registers, an integer does not suffice. - Then the integers are replaced by sub-initializers, braced groupings - containing several integers. Each sub-initializer must be suitable as an - initializer for the type `HARD_REG_SET' which is defined in - `hard-reg-set.h'. */ - -/* NOTE: DSP registers, IREGS - AREGS, are not GENERAL_REGS. We use - MOST_REGS as the union of DPREGS and DAGREGS. */ - -#define REG_CLASS_CONTENTS \ - /* 31 - 0 63-32 */ \ -{ { 0x00000000, 0 }, /* NO_REGS */ \ - { 0x000f0000, 0 }, /* IREGS */ \ - { 0x00f00000, 0 }, /* BREGS */ \ - { 0x0f000000, 0 }, /* LREGS */ \ - { 0xf0000000, 0 }, /* MREGS */ \ - { 0x0fff0000, 0 }, /* CIRCREGS */ \ - { 0xffff0000, 0 }, /* DAGREGS */ \ - { 0x00000000, 0x1 }, /* EVEN_AREGS */ \ - { 0x00000000, 0x2 }, /* ODD_AREGS */ \ - { 0x00000000, 0x3 }, /* AREGS */ \ - { 0x00000000, 0x4 }, /* CCREGS */ \ - { 0x00000055, 0 }, /* EVEN_DREGS */ \ - { 0x000000aa, 0 }, /* ODD_DREGS */ \ - { 0x00000001, 0 }, /* D0REGS */ \ - { 0x00000002, 0 }, /* D1REGS */ \ - { 0x00000004, 0 }, /* D2REGS */ \ - { 0x00000008, 0 }, /* D3REGS */ \ - { 0x00000010, 0 }, /* D4REGS */ \ - { 0x00000020, 0 }, /* D5REGS */ \ - { 0x00000040, 0 }, /* D6REGS */ \ - { 0x00000080, 0 }, /* D7REGS */ \ - { 0x000000ff, 0 }, /* DREGS */ \ - { 0x00000100, 0x000 }, /* P0REGS */ \ - { 0x00000800, 0x000 }, /* FDPIC_REGS */ \ - { 0x00000200, 0x000 }, /* FDPIC_FPTR_REGS */ \ - { 0x00004700, 0x800 }, /* PREGS_CLOBBERED */ \ - { 0x0000ff00, 0x800 }, /* PREGS */ \ - { 0x000fff00, 0x800 }, /* IPREGS */ \ - { 0x0000ffff, 0x800 }, /* DPREGS */ \ - { 0xffffffff, 0x800 }, /* MOST_REGS */\ - { 0x00000000, 0x3000 }, /* LT_REGS */\ - { 0x00000000, 0xc000 }, /* LC_REGS */\ - { 0x00000000, 0x30000 }, /* LB_REGS */\ - { 0x00000000, 0x3f7f8 }, /* PROLOGUE_REGS */\ - { 0xffffffff, 0x3fff8 }, /* NON_A_CC_REGS */\ - { 0xffffffff, 0x3ffff }} /* ALL_REGS */ - -#define IREG_POSSIBLE_P(OUTER) \ - ((OUTER) == POST_INC || (OUTER) == PRE_INC \ - || (OUTER) == POST_DEC || (OUTER) == PRE_DEC \ - || (OUTER) == MEM || (OUTER) == ADDRESS) - -#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX) \ - ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS) - -#define INDEX_REG_CLASS PREGS - -#define REGNO_OK_FOR_BASE_STRICT_P(X, MODE, OUTER, INDEX) \ - (P_REGNO_P (X) || (X) == REG_ARGP \ - || (IREG_POSSIBLE_P (OUTER) && (MODE) == HImode \ - && I_REGNO_P (X))) - -#define REGNO_OK_FOR_BASE_NONSTRICT_P(X, MODE, OUTER, INDEX) \ - ((X) >= FIRST_PSEUDO_REGISTER \ - || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)) - -#ifdef REG_OK_STRICT -#define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \ - REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX) -#else -#define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \ - REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX) -#endif - -#define REGNO_OK_FOR_INDEX_P(X) 0 - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ -((REGNO) == REG_R0 ? D0REGS \ - : (REGNO) == REG_R1 ? D1REGS \ - : (REGNO) == REG_R2 ? D2REGS \ - : (REGNO) == REG_R3 ? D3REGS \ - : (REGNO) == REG_R4 ? D4REGS \ - : (REGNO) == REG_R5 ? D5REGS \ - : (REGNO) == REG_R6 ? D6REGS \ - : (REGNO) == REG_R7 ? D7REGS \ - : (REGNO) == REG_P0 ? P0REGS \ - : (REGNO) < REG_I0 ? PREGS \ - : (REGNO) == REG_ARGP ? PREGS \ - : (REGNO) >= REG_I0 && (REGNO) <= REG_I3 ? IREGS \ - : (REGNO) >= REG_L0 && (REGNO) <= REG_L3 ? LREGS \ - : (REGNO) >= REG_B0 && (REGNO) <= REG_B3 ? BREGS \ - : (REGNO) >= REG_M0 && (REGNO) <= REG_M3 ? MREGS \ - : (REGNO) == REG_A0 || (REGNO) == REG_A1 ? AREGS \ - : (REGNO) == REG_LT0 || (REGNO) == REG_LT1 ? LT_REGS \ - : (REGNO) == REG_LC0 || (REGNO) == REG_LC1 ? LC_REGS \ - : (REGNO) == REG_LB0 || (REGNO) == REG_LB1 ? LB_REGS \ - : (REGNO) == REG_CC ? CCREGS \ - : (REGNO) >= REG_RETS ? PROLOGUE_REGS \ - : NO_REGS) - -/* When this hook returns true for MODE, the compiler allows - registers explicitly used in the rtl to be used as spill registers - but prevents the compiler from extending the lifetime of these - registers. */ -#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true - -/* Do not allow to store a value in REG_CC for any mode */ -/* Do not allow to store value in pregs if mode is not SI*/ -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok((REGNO), (MODE)) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((MODE) == V2PDImode && (CLASS) == AREGS ? 2 \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((MODE) == PDImode && ((REGNO) == REG_A0 || (REGNO) == REG_A1) ? 1 \ - : (MODE) == V2PDImode && ((REGNO) == REG_A0 || (REGNO) == REG_A1) ? 2 \ - : CLASS_MAX_NREGS (GENERAL_REGS, MODE)) - -/* A C expression that is nonzero if hard register TO can be - considered for use as a rename register for FROM register */ -#define HARD_REGNO_RENAME_OK(FROM, TO) bfin_hard_regno_rename_ok (FROM, TO) - -/* 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. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((MODE1) == (MODE2) \ - || ((GET_MODE_CLASS (MODE1) == MODE_INT \ - || GET_MODE_CLASS (MODE1) == MODE_FLOAT) \ - && (GET_MODE_CLASS (MODE2) == MODE_INT \ - || GET_MODE_CLASS (MODE2) == MODE_FLOAT) \ - && (MODE1) != BImode && (MODE2) != BImode \ - && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ - && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)) - -/* `PREFERRED_RELOAD_CLASS (X, CLASS)' - A C expression that places additional restrictions on the register - class to use when it is necessary to copy value X into a register - in class CLASS. The value is a register class; perhaps CLASS, or - perhaps another, smaller class. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (GET_CODE (X) == POST_INC \ - || GET_CODE (X) == POST_DEC \ - || GET_CODE (X) == PRE_DEC ? PREGS : (CLASS)) - -/* Function Calling Conventions. */ - -/* The type of the current function; normal functions are of type - SUBROUTINE. */ -typedef enum { - SUBROUTINE, INTERRUPT_HANDLER, EXCPT_HANDLER, NMI_HANDLER -} e_funkind; -#define FUNCTION_RETURN_REGISTERS { REG_RETS, REG_RETI, REG_RETX, REG_RETN } - -#define FUNCTION_ARG_REGISTERS { REG_R0, REG_R1, REG_R2, -1 } - -/* Flags for the call/call_value rtl operations set up by function_arg */ -#define CALL_NORMAL 0x00000000 /* no special processing */ -#define CALL_LONG 0x00000001 /* always call indirect */ -#define CALL_SHORT 0x00000002 /* always call by symbol */ - -typedef struct { - int words; /* # words passed so far */ - int nregs; /* # registers available for passing */ - int *arg_regs; /* array of register -1 terminated */ - int call_cookie; /* Do special things for this call */ -} CUMULATIVE_ARGS; - -#define FUNCTION_ARG_REGNO_P(REGNO) function_arg_regno_p (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. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, N_NAMED_ARGS) \ - (init_cumulative_args (&CUM, FNTYPE, LIBNAME)) - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. -*/ - -#define VALUE_REGNO(MODE) (REG_R0) - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), \ - VALUE_REGNO(TYPE_MODE(VALTYPE))) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, VALUE_REGNO(MODE)) - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == REG_R0) - -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Before the prologue, the return address is in the RETS register. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, REG_RETS) - -#define RETURN_ADDR_RTX(COUNT, FRAME) bfin_return_addr_rtx (COUNT) - -#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (REG_RETS) - -/* Call instructions don't modify the stack pointer on the Blackfin. */ -#define INCOMING_FRAME_SP_OFFSET 0 - -/* Describe how we implement __builtin_eh_return. */ -#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) : INVALID_REGNUM) -#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, REG_P2) -#define EH_RETURN_HANDLER_RTX \ - gen_frame_mem (Pmode, plus_constant (frame_pointer_rtx, UNITS_PER_WORD)) - -/* Addressing Modes */ - -/* A number, the maximum number of registers that can appear in a - valid memory address. Note that it is up to you to specify a - value equal to the maximum number that `TARGET_LEGITIMATE_ADDRESS_P' - would ever accept. */ -#define MAX_REGS_PER_ADDRESS 1 - -#define LEGITIMATE_MODE_FOR_AUTOINC_P(MODE) \ - (GET_MODE_SIZE (MODE) <= 4 || (MODE) == PDImode) - -#define HAVE_POST_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_DECREMENT 1 - -/* `LEGITIMATE_PIC_OPERAND_P (X)' - A C expression that is nonzero if X is a legitimate immediate - operand on the target machine when generating position independent - code. You can assume that X satisfies `CONSTANT_P', so you need - not check this. You can also assume FLAG_PIC is true, so you need - not check it either. You need not define this macro if all - constants (including `SYMBOL_REF') can be immediate operands when - generating position independent code. */ -#define LEGITIMATE_PIC_OPERAND_P(X) ! SYMBOLIC_CONST (X) - -#define SYMBOLIC_CONST(X) \ -(GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == LABEL_REF \ - || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X))) - -#define NOTICE_UPDATE_CC(EXPR, INSN) 0 - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX UNITS_PER_WORD - -/* If a memory-to-memory move would take MOVE_RATIO or more simple - move-instruction pairs, we will do a movmem or libcall instead. */ - -#define MOVE_RATIO(speed) 5 - -/* STORAGE LAYOUT: target machine storage layout - Define this macro as a C expression which is nonzero if accessing - less than a word of memory (i.e. a `char' or a `short') is no - faster than accessing a word of memory, i.e., if such access - require more than one instruction or if there is no difference in - cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by - finding the smallest containing object; when it is defined, a - fullword load will be used if alignment permits. Unless bytes - accesses are faster than word accesses, using word accesses is - preferable since it may eliminate subsequent memory access if - subsequent accesses occur to other fields in the same word of the - structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 0 -#define SLOW_SHORT_ACCESS 0 - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. - We can't access bytes but if we could we would in the Big Endian order. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is numbered. */ -#define WORDS_BIG_ENDIAN 0 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Width in bits of a pointer. - See also the macro `Pmode1' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY BITS_PER_WORD - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 32 - -/* Define this if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* (shell-command "rm c-decl.o stor-layout.o") - * never define PCC_BITFIELD_TYPE_MATTERS - * really cause some alignment problem - */ - -#define UNITS_PER_FLOAT ((FLOAT_TYPE_SIZE + BITS_PER_UNIT - 1) / \ - BITS_PER_UNIT) - -#define UNITS_PER_DOUBLE ((DOUBLE_TYPE_SIZE + BITS_PER_UNIT - 1) / \ - BITS_PER_UNIT) - - -/* what is the 'type' of size_t */ -#define SIZE_TYPE "long unsigned int" - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 -#define FLOAT_TYPE_SIZE BITS_PER_WORD -#define SHORT_TYPE_SIZE 16 -#define CHAR_TYPE_SIZE 8 -#define INT_TYPE_SIZE 32 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 - -/* Note: Fix this to depend on target switch. -- lev */ - -/* Note: Try to implement double and force long double. -- tonyko - * #define __DOUBLES_ARE_FLOATS__ - * #define DOUBLE_TYPE_SIZE FLOAT_TYPE_SIZE - * #define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE - * #define DOUBLES_ARE_FLOATS 1 - */ - -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* `PROMOTE_MODE (M, UNSIGNEDP, TYPE)' - A macro to update M and UNSIGNEDP when an object whose type is - TYPE and which has the specified mode and signedness is to be - stored in a register. This macro is only called when TYPE is a - scalar type. - - On most RISC machines, which only have operations that operate on - a full register, define this macro to set M to `word_mode' if M is - an integer mode narrower than `BITS_PER_WORD'. In most cases, - only integer modes should be widened because wider-precision - floating-point operations are usually more expensive than their - narrower counterparts. - - For most machines, the macro definition does not change UNSIGNEDP. - However, some machines, have instructions that preferentially - handle either signed or unsigned quantities of certain modes. For - example, on the DEC Alpha, 32-bit loads from memory and 32-bit add - instructions sign-extend the result to 64 bits. On such machines, - set UNSIGNEDP according to which kind of extension is more - efficient. - - Do not define this macro if it would never modify M.*/ - -#define BFIN_PROMOTE_MODE_P(MODE) \ - (!TARGET_DSP && GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) - -#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ - if (BFIN_PROMOTE_MODE_P(MODE)) \ - { \ - if (MODE == QImode) \ - UNSIGNEDP = 1; \ - else if (MODE == HImode) \ - UNSIGNEDP = 0; \ - (MODE) = SImode; \ - } - -/* Describing Relative Costs of Operations */ - -/* Do not put function addr into constant pool */ -#define NO_FUNCTION_CSE 1 - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -#define JUMP_TABLES_IN_TEXT_SECTION flag_pic - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. -#define WORD_REGISTER_OPERATIONS -*/ - -/* Evaluates to true if A and B are mac flags that can be used - together in a single multiply insn. That is the case if they are - both the same flag not involving M, or if one is a combination of - the other with M. */ -#define MACFLAGS_MATCH_P(A, B) \ - ((A) == (B) \ - || ((A) == MACFLAG_NONE && (B) == MACFLAG_M) \ - || ((A) == MACFLAG_M && (B) == MACFLAG_NONE) \ - || ((A) == MACFLAG_IS && (B) == MACFLAG_IS_M) \ - || ((A) == MACFLAG_IS_M && (B) == MACFLAG_IS)) - -/* Switch into a generic section. */ -#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section - -#define PRINT_OPERAND(FILE, RTX, CODE) print_operand (FILE, RTX, CODE) -#define PRINT_OPERAND_ADDRESS(FILE, RTX) print_address_operand (FILE, RTX) - -typedef enum sections { - CODE_DIR, - DATA_DIR, - LAST_SECT_NM -} SECT_ENUM_T; - -typedef enum directives { - LONG_CONST_DIR, - SHORT_CONST_DIR, - BYTE_CONST_DIR, - SPACE_DIR, - INIT_DIR, - LAST_DIR_NM -} DIR_ENUM_T; - -#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) \ - ((C) == ';' \ - || ((C) == '|' && (STR)[1] == '|')) - -#define TEXT_SECTION_ASM_OP ".text;" -#define DATA_SECTION_ASM_OP ".data;" - -#define ASM_APP_ON "" -#define ASM_APP_OFF "" - -#define ASM_GLOBALIZE_LABEL1(FILE, NAME) \ - do { fputs (".global ", FILE); \ - assemble_name (FILE, NAME); \ - fputc (';',FILE); \ - fputc ('\n',FILE); \ - } while (0) - -#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - do { \ - fputs (".type ", FILE); \ - assemble_name (FILE, NAME); \ - fputs (", STT_FUNC", FILE); \ - fputc (';',FILE); \ - fputc ('\n',FILE); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -#define ASM_OUTPUT_LABEL(FILE, NAME) \ - do { assemble_name (FILE, NAME); \ - fputs (":\n",FILE); \ - } while (0) - -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - do { fprintf (FILE, "_%s", NAME); \ - } while (0) - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ -do { char __buf[256]; \ - fprintf (FILE, "\t.dd\t"); \ - ASM_GENERATE_INTERNAL_LABEL (__buf, "L", VALUE); \ - assemble_name (FILE, __buf); \ - fputc (';', FILE); \ - fputc ('\n', FILE); \ - } while (0) - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - MY_ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) - -#define MY_ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ - do { \ - char __buf[256]; \ - fprintf (FILE, "\t.dd\t"); \ - ASM_GENERATE_INTERNAL_LABEL (__buf, "L", VALUE); \ - assemble_name (FILE, __buf); \ - fputs (" - ", FILE); \ - ASM_GENERATE_INTERNAL_LABEL (__buf, "L", REL); \ - assemble_name (FILE, __buf); \ - fputc (';', FILE); \ - fputc ('\n', FILE); \ - } while (0) - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - do { \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align %d\n", 1 << (LOG)); \ - } while (0) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - do { \ - asm_output_skip (FILE, SIZE); \ - } while (0) - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -do { \ - switch_to_section (data_section); \ - if ((SIZE) >= (unsigned int) 4 ) ASM_OUTPUT_ALIGN(FILE,2); \ - ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \ - ASM_OUTPUT_LABEL (FILE, NAME); \ - fprintf (FILE, "%s %ld;\n", ASM_SPACE, \ - (ROUNDED) > (unsigned int) 1 ? (ROUNDED) : 1); \ -} while (0) - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ - do { \ - ASM_GLOBALIZE_LABEL1(FILE,NAME); \ - ASM_OUTPUT_LOCAL (FILE, NAME, SIZE, ROUNDED); } while(0) - -#define ASM_COMMENT_START "//" - -#define PROFILE_BEFORE_PROLOGUE -#define FUNCTION_PROFILER(FILE, LABELNO) \ - do { \ - fprintf (FILE, "\t[--SP] = RETS;\n"); \ - if (TARGET_LONG_CALLS) \ - { \ - fprintf (FILE, "\tP2.h = __mcount;\n"); \ - fprintf (FILE, "\tP2.l = __mcount;\n"); \ - fprintf (FILE, "\tCALL (P2);\n"); \ - } \ - else \ - fprintf (FILE, "\tCALL __mcount;\n"); \ - fprintf (FILE, "\tRETS = [SP++];\n"); \ - } while(0) - -#undef NO_PROFILE_COUNTERS -#define NO_PROFILE_COUNTERS 1 - -#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) fprintf (FILE, "\t[--SP] = %s;\n", reg_names[REGNO]) -#define ASM_OUTPUT_REG_POP(FILE, REGNO) fprintf (FILE, "\t%s = [SP++];\n", reg_names[REGNO]) - -extern rtx bfin_cc_rtx, bfin_rets_rtx; - -/* This works for GAS and some other assemblers. */ -#define SET_ASM_OP ".set " - -/* DBX register number for a given compiler register number */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -#define SIZE_ASM_OP "\t.size\t" - -extern int splitting_for_sched, splitting_loops; - -#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) ((CHAR) == '!') - -#ifndef TARGET_SUPPORTS_SYNC_CALLS -#define TARGET_SUPPORTS_SYNC_CALLS 0 -#endif - -struct bfin_cpu -{ - const char *name; - bfin_cpu_t type; - int si_revision; - unsigned int workarounds; -}; - -extern const struct bfin_cpu bfin_cpus[]; - -#endif /* _BFIN_CONFIG */ diff --git a/gcc-4.7/gcc/config/bfin/bfin.md b/gcc-4.7/gcc/config/bfin/bfin.md deleted file mode 100644 index 1774d3adf..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin.md +++ /dev/null @@ -1,4210 +0,0 @@ -;;- Machine description for Blackfin for GNU compiler -;; Copyright 2005, 2006, 2007, 2008, 2011 Free Software Foundation, Inc. -;; Contributed by Analog Devices. - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published -;; by the Free Software Foundation; either version 3, or (at your -;; option) any later version. - -;; GCC is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -; operand punctuation marks: -; -; X -- integer value printed as log2 -; Y -- integer value printed as log2(~value) - for bitclear -; h -- print half word register, low part -; d -- print half word register, high part -; D -- print operand as dregs pairs -; w -- print operand as accumulator register word (a0w, a1w) -; H -- high part of double mode operand -; T -- byte register representation Oct. 02 2001 - -; constant operand classes -; -; J 2**N 5bit imm scaled -; Ks7 -64 .. 63 signed 7bit imm -; Ku5 0..31 unsigned 5bit imm -; Ks4 -8 .. 7 signed 4bit imm -; Ks3 -4 .. 3 signed 3bit imm -; Ku3 0 .. 7 unsigned 3bit imm -; Pn 0, 1, 2 constants 0, 1 or 2, corresponding to n -; -; register operands -; d (r0..r7) -; a (p0..p5,fp,sp) -; e (a0, a1) -; b (i0..i3) -; f (m0..m3) -; v (b0..b3) -; c (i0..i3,m0..m3) CIRCREGS -; C (CC) CCREGS -; t (lt0,lt1) -; k (lc0,lc1) -; u (lb0,lb1) -; - -;; Define constants for hard registers. - -(define_constants - [(REG_R0 0) - (REG_R1 1) - (REG_R2 2) - (REG_R3 3) - (REG_R4 4) - (REG_R5 5) - (REG_R6 6) - (REG_R7 7) - - (REG_P0 8) - (REG_P1 9) - (REG_P2 10) - (REG_P3 11) - (REG_P4 12) - (REG_P5 13) - (REG_P6 14) - (REG_P7 15) - - (REG_SP 14) - (REG_FP 15) - - (REG_I0 16) - (REG_I1 17) - (REG_I2 18) - (REG_I3 19) - - (REG_B0 20) - (REG_B1 21) - (REG_B2 22) - (REG_B3 23) - - (REG_L0 24) - (REG_L1 25) - (REG_L2 26) - (REG_L3 27) - - (REG_M0 28) - (REG_M1 29) - (REG_M2 30) - (REG_M3 31) - - (REG_A0 32) - (REG_A1 33) - - (REG_CC 34) - (REG_RETS 35) - (REG_RETI 36) - (REG_RETX 37) - (REG_RETN 38) - (REG_RETE 39) - - (REG_ASTAT 40) - (REG_SEQSTAT 41) - (REG_USP 42) - - (REG_ARGP 43) - - (REG_LT0 44) - (REG_LT1 45) - (REG_LC0 46) - (REG_LC1 47) - (REG_LB0 48) - (REG_LB1 49)]) - -;; Constants used in UNSPECs and UNSPEC_VOLATILEs. - -(define_constants - [(UNSPEC_CBRANCH_TAKEN 0) - (UNSPEC_CBRANCH_NOPS 1) - (UNSPEC_RETURN 2) - (UNSPEC_MOVE_PIC 3) - (UNSPEC_LIBRARY_OFFSET 4) - (UNSPEC_PUSH_MULTIPLE 5) - ;; Multiply or MAC with extra CONST_INT operand specifying the macflag - (UNSPEC_MUL_WITH_FLAG 6) - (UNSPEC_MAC_WITH_FLAG 7) - (UNSPEC_MOVE_FDPIC 8) - (UNSPEC_FUNCDESC_GOT17M4 9) - (UNSPEC_LSETUP_END 10) - ;; Distinguish a 32-bit version of an insn from a 16-bit version. - (UNSPEC_32BIT 11) - (UNSPEC_NOP 12) - (UNSPEC_ONES 13) - (UNSPEC_ATOMIC 14)]) - -(define_constants - [(UNSPEC_VOLATILE_CSYNC 1) - (UNSPEC_VOLATILE_SSYNC 2) - (UNSPEC_VOLATILE_LOAD_FUNCDESC 3) - (UNSPEC_VOLATILE_STORE_EH_HANDLER 4) - (UNSPEC_VOLATILE_DUMMY 5) - (UNSPEC_VOLATILE_STALL 6)]) - -(define_constants - [(MACFLAG_NONE 0) - (MACFLAG_T 1) - (MACFLAG_FU 2) - (MACFLAG_TFU 3) - (MACFLAG_IS 4) - (MACFLAG_IU 5) - (MACFLAG_W32 6) - (MACFLAG_M 7) - (MACFLAG_IS_M 8) - (MACFLAG_S2RND 9) - (MACFLAG_ISS2 10) - (MACFLAG_IH 11)]) - -(define_attr "type" - "move,movcc,mvi,mcld,mcst,dsp32,dsp32shiftimm,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy,stall" - (const_string "misc")) - -(define_attr "addrtype" "32bit,preg,spreg,ireg" - (cond [(and (eq_attr "type" "mcld") - (and (match_operand 0 "dp_register_operand" "") - (match_operand 1 "mem_p_address_operand" ""))) - (const_string "preg") - (and (eq_attr "type" "mcld") - (and (match_operand 0 "dp_register_operand" "") - (match_operand 1 "mem_spfp_address_operand" ""))) - (const_string "spreg") - (and (eq_attr "type" "mcld") - (and (match_operand 0 "dp_register_operand" "") - (match_operand 1 "mem_i_address_operand" ""))) - (const_string "ireg") - (and (eq_attr "type" "mcst") - (and (match_operand 1 "dp_register_operand" "") - (match_operand 0 "mem_p_address_operand" ""))) - (const_string "preg") - (and (eq_attr "type" "mcst") - (and (match_operand 1 "dp_register_operand" "") - (match_operand 0 "mem_spfp_address_operand" ""))) - (const_string "spreg") - (and (eq_attr "type" "mcst") - (and (match_operand 1 "dp_register_operand" "") - (match_operand 0 "mem_i_address_operand" ""))) - (const_string "ireg")] - (const_string "32bit"))) - -(define_attr "storereg" "preg,other" - (cond [(and (eq_attr "type" "mcst") - (match_operand 1 "p_register_operand" "")) - (const_string "preg")] - (const_string "other"))) - -;; Scheduling definitions - -(define_automaton "bfin") - -(define_cpu_unit "slot0" "bfin") -(define_cpu_unit "slot1" "bfin") -(define_cpu_unit "slot2" "bfin") - -;; Three units used to enforce parallel issue restrictions: -;; only one of the 16-bit slots can use a P register in an address, -;; and only one them can be a store. -(define_cpu_unit "store" "bfin") -(define_cpu_unit "pregs" "bfin") - -;; A dummy unit used to delay scheduling of loads after a conditional -;; branch. -(define_cpu_unit "load" "bfin") - -;; A logical unit used to work around anomaly 05000074. -(define_cpu_unit "anomaly_05000074" "bfin") - -(define_reservation "core" "slot0+slot1+slot2") - -(define_insn_reservation "alu" 1 - (eq_attr "type" "move,movcc,mvi,alu0,shft,brcc,br,call,misc,sync,compare") - "core") - -(define_insn_reservation "imul" 3 - (eq_attr "type" "mult") - "core*3") - -(define_insn_reservation "dsp32" 1 - (eq_attr "type" "dsp32") - "slot0") - -(define_insn_reservation "dsp32shiftimm" 1 - (and (eq_attr "type" "dsp32shiftimm") - (not (match_test "ENABLE_WA_05000074"))) - "slot0") - -(define_insn_reservation "dsp32shiftimm_anomaly_05000074" 1 - (and (eq_attr "type" "dsp32shiftimm") - (match_test "ENABLE_WA_05000074")) - "slot0+anomaly_05000074") - -(define_insn_reservation "load32" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcld") (eq_attr "addrtype" "32bit"))) - "core+load") - -(define_insn_reservation "loadp" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcld") (eq_attr "addrtype" "preg"))) - "slot1+pregs+load") - -(define_insn_reservation "loadsp" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcld") (eq_attr "addrtype" "spreg"))) - "slot1+pregs") - -(define_insn_reservation "loadi" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcld") (eq_attr "addrtype" "ireg"))) - "(slot1|slot2)+load") - -(define_insn_reservation "store32" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") (eq_attr "addrtype" "32bit"))) - "core") - -(define_insn_reservation "storep" 1 - (and (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") - (ior (eq_attr "addrtype" "preg") - (eq_attr "addrtype" "spreg")))) - (ior (not (match_test "ENABLE_WA_05000074")) - (eq_attr "storereg" "other"))) - "slot1+pregs+store") - -(define_insn_reservation "storep_anomaly_05000074" 1 - (and (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") - (ior (eq_attr "addrtype" "preg") - (eq_attr "addrtype" "spreg")))) - (and (match_test "ENABLE_WA_05000074") - (eq_attr "storereg" "preg"))) - "slot1+anomaly_05000074+pregs+store") - -(define_insn_reservation "storei" 1 - (and (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg"))) - (ior (not (match_test "ENABLE_WA_05000074")) - (eq_attr "storereg" "other"))) - "(slot1|slot2)+store") - -(define_insn_reservation "storei_anomaly_05000074" 1 - (and (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg"))) - (and (match_test "ENABLE_WA_05000074") - (eq_attr "storereg" "preg"))) - "((slot1+anomaly_05000074)|slot2)+store") - -(define_insn_reservation "multi" 2 - (eq_attr "seq_insns" "multi") - "core") - -(define_insn_reservation "load_stall1" 1 - (and (eq_attr "type" "stall") - (match_operand 0 "const1_operand" "")) - "core+load*2") - -(define_insn_reservation "load_stall3" 1 - (and (eq_attr "type" "stall") - (match_operand 0 "const3_operand" "")) - "core+load*4") - -(absence_set "slot0" "slot1,slot2") -(absence_set "slot1" "slot2") - -;; Make sure genautomata knows about the maximum latency that can be produced -;; by the adjust_cost function. -(define_insn_reservation "dummy" 5 - (eq_attr "type" "dummy") - "core") - -;; Operand and operator predicates - -(include "predicates.md") -(include "constraints.md") - -;;; FRIO branches have been optimized for code density -;;; this comes at a slight cost of complexity when -;;; a compiler needs to generate branches in the general -;;; case. In order to generate the correct branching -;;; mechanisms the compiler needs keep track of instruction -;;; lengths. The follow table describes how to count instructions -;;; for the FRIO architecture. -;;; -;;; unconditional br are 12-bit imm pcrelative branches *2 -;;; conditional br are 10-bit imm pcrelative branches *2 -;;; brcc 10-bit: -;;; 1024 10-bit imm *2 is 2048 (-1024..1022) -;;; br 12-bit : -;;; 4096 12-bit imm *2 is 8192 (-4096..4094) -;;; NOTE : For brcc we generate instructions such as -;;; if cc jmp; jump.[sl] offset -;;; offset of jump.[sl] is from the jump instruction but -;;; gcc calculates length from the if cc jmp instruction -;;; furthermore gcc takes the end address of the branch instruction -;;; as (pc) for a forward branch -;;; hence our range is (-4094, 4092) instead of (-4096, 4094) for a br -;;; -;;; The way the (pc) rtx works in these calculations is somewhat odd; -;;; for backward branches it's the address of the current instruction, -;;; for forward branches it's the previously known address of the following -;;; instruction - we have to take this into account by reducing the range -;;; for a forward branch. - -;; Lengths for type "mvi" insns are always defined by the instructions -;; themselves. -(define_attr "length" "" - (cond [(eq_attr "type" "mcld") - (if_then_else (match_operand 1 "effective_address_32bit_p" "") - (const_int 4) (const_int 2)) - - (eq_attr "type" "mcst") - (if_then_else (match_operand 0 "effective_address_32bit_p" "") - (const_int 4) (const_int 2)) - - (eq_attr "type" "move") (const_int 2) - - (eq_attr "type" "dsp32") (const_int 4) - (eq_attr "type" "dsp32shiftimm") (const_int 4) - (eq_attr "type" "call") (const_int 4) - - (eq_attr "type" "br") - (if_then_else (and - (le (minus (match_dup 0) (pc)) (const_int 4092)) - (ge (minus (match_dup 0) (pc)) (const_int -4096))) - (const_int 2) - (const_int 4)) - - (eq_attr "type" "brcc") - (cond [(and - (le (minus (match_dup 3) (pc)) (const_int 1020)) - (ge (minus (match_dup 3) (pc)) (const_int -1024))) - (const_int 2) - (and - (le (minus (match_dup 3) (pc)) (const_int 4092)) - (ge (minus (match_dup 3) (pc)) (const_int -4094))) - (const_int 4)] - (const_int 6)) - ] - - (const_int 2))) - -;; Classify the insns into those that are one instruction and those that -;; are more than one in sequence. -(define_attr "seq_insns" "single,multi" - (const_string "single")) - -;; Describe a user's asm statement. -(define_asm_attributes - [(set_attr "type" "misc") - (set_attr "seq_insns" "multi") - (set_attr "length" "4")]) - -;; Conditional moves - -(define_mode_iterator CCMOV [QI HI SI]) - -(define_expand "mov<mode>cc" - [(set (match_operand:CCMOV 0 "register_operand" "") - (if_then_else:CCMOV (match_operand 1 "comparison_operator" "") - (match_operand:CCMOV 2 "register_operand" "") - (match_operand:CCMOV 3 "register_operand" "")))] - "" -{ - operands[1] = bfin_gen_compare (operands[1], <MODE>mode); -}) - -(define_insn "*mov<mode>cc_insn1" - [(set (match_operand:CCMOV 0 "register_operand" "=da,da,da") - (if_then_else:CCMOV - (eq:BI (match_operand:BI 3 "register_operand" "C,C,C") - (const_int 0)) - (match_operand:CCMOV 1 "register_operand" "da,0,da") - (match_operand:CCMOV 2 "register_operand" "0,da,da")))] - "" - "@ - if !cc %0 = %1; - if cc %0 = %2; - if !cc %0 = %1; if cc %0 = %2;" - [(set_attr "length" "2,2,4") - (set_attr "type" "movcc") - (set_attr "seq_insns" "*,*,multi")]) - -(define_insn "*mov<mode>cc_insn2" - [(set (match_operand:CCMOV 0 "register_operand" "=da,da,da") - (if_then_else:CCMOV - (ne:BI (match_operand:BI 3 "register_operand" "C,C,C") - (const_int 0)) - (match_operand:CCMOV 1 "register_operand" "0,da,da") - (match_operand:CCMOV 2 "register_operand" "da,0,da")))] - "" - "@ - if !cc %0 = %2; - if cc %0 = %1; - if cc %0 = %1; if !cc %0 = %2;" - [(set_attr "length" "2,2,4") - (set_attr "type" "movcc") - (set_attr "seq_insns" "*,*,multi")]) - -;; Insns to load HIGH and LO_SUM - -(define_insn "movsi_high" - [(set (match_operand:SI 0 "register_operand" "=x") - (high:SI (match_operand:SI 1 "immediate_operand" "i")))] - "reload_completed" - "%d0 = %d1;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -(define_insn "movstricthi_high" - [(set (match_operand:SI 0 "register_operand" "+x") - (ior:SI (and:SI (match_dup 0) (const_int 65535)) - (match_operand:SI 1 "immediate_operand" "i")))] - "reload_completed" - "%d0 = %d1;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -(define_insn "movsi_low" - [(set (match_operand:SI 0 "register_operand" "=x") - (lo_sum:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "reload_completed" - "%h0 = %h2;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -(define_insn "movsi_high_pic" - [(set (match_operand:SI 0 "register_operand" "=x") - (high:SI (unspec:SI [(match_operand:SI 1 "" "")] - UNSPEC_MOVE_PIC)))] - "" - "%d0 = %1@GOT_LOW;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -(define_insn "movsi_low_pic" - [(set (match_operand:SI 0 "register_operand" "=x") - (lo_sum:SI (match_operand:SI 1 "register_operand" "0") - (unspec:SI [(match_operand:SI 2 "" "")] - UNSPEC_MOVE_PIC)))] - "" - "%h0 = %h2@GOT_HIGH;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -;;; Move instructions - -(define_insn_and_split "movdi_insn" - [(set (match_operand:DI 0 "nonimmediate_operand" "=x,mx,r") - (match_operand:DI 1 "general_operand" "iFx,r,mx"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] -{ - rtx lo_half[2], hi_half[2]; - split_di (operands, 2, lo_half, hi_half); - - if (reg_overlap_mentioned_p (lo_half[0], hi_half[1])) - { - operands[2] = hi_half[0]; - operands[3] = hi_half[1]; - operands[4] = lo_half[0]; - operands[5] = lo_half[1]; - } - else - { - operands[2] = lo_half[0]; - operands[3] = lo_half[1]; - operands[4] = hi_half[0]; - operands[5] = hi_half[1]; - } -}) - -(define_insn "movbi" - [(set (match_operand:BI 0 "nonimmediate_operand" "=x,x,d,md,C,d,C,P1") - (match_operand:BI 1 "general_operand" "x,xKs3,md,d,d,C,P0,P1"))] - - "" - "@ - %0 = %1; - %0 = %1 (X); - %0 = B %1 (Z)%! - B %0 = %1; - CC = %1; - %0 = CC; - CC = R0 < R0; - CC = R0 == R0;" - [(set_attr "type" "move,mvi,mcld,mcst,compare,compare,compare,compare") - (set_attr "length" "2,2,*,*,2,2,2,2") - (set_attr "seq_insns" "*,*,*,*,*,*,*,*")]) - -(define_insn "movpdi" - [(set (match_operand:PDI 0 "nonimmediate_operand" "=e,<,e") - (match_operand:PDI 1 "general_operand" " e,e,>"))] - "" - "@ - %0 = %1; - %0 = %x1; %0 = %w1; - %w0 = %1; %x0 = %1;" - [(set_attr "type" "move,mcst,mcld") - (set_attr "seq_insns" "*,multi,multi")]) - -(define_insn "load_accumulator" - [(set (match_operand:PDI 0 "register_operand" "=e") - (sign_extend:PDI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = %1;" - [(set_attr "type" "move")]) - -(define_insn_and_split "load_accumulator_pair" - [(set (match_operand:V2PDI 0 "register_operand" "=e") - (sign_extend:V2PDI (vec_concat:V2SI - (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))))] - "" - "#" - "reload_completed" - [(set (match_dup 3) (sign_extend:PDI (match_dup 1))) - (set (match_dup 4) (sign_extend:PDI (match_dup 2)))] -{ - operands[3] = gen_rtx_REG (PDImode, REGNO (operands[0])); - operands[4] = gen_rtx_REG (PDImode, REGNO (operands[0]) + 1); -}) - -(define_insn "*pushsi_insn" - [(set (mem:SI (pre_dec:SI (reg:SI REG_SP))) - (match_operand:SI 0 "register_operand" "xy"))] - "" - "[--SP] = %0;" - [(set_attr "type" "mcst") - (set_attr "addrtype" "32bit") - (set_attr "length" "2")]) - -(define_insn "*popsi_insn" - [(set (match_operand:SI 0 "register_operand" "=d,xy") - (mem:SI (post_inc:SI (reg:SI REG_SP))))] - "" - "%0 = [SP++]%!" - [(set_attr "type" "mcld") - (set_attr "addrtype" "preg,32bit") - (set_attr "length" "2")]) - -;; The first alternative is used to make reload choose a limited register -;; class when faced with a movsi_insn that had its input operand replaced -;; with a PLUS. We generally require fewer secondary reloads this way. - -(define_insn "*movsi_insn" - [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x,da,y,da,x,x,x,da,mr") - (match_operand:SI 1 "general_operand" "da,x,y,da,xKs7,xKsh,xKuh,ix,mr,da"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "@ - %0 = %1; - %0 = %1; - %0 = %1; - %0 = %1; - %0 = %1 (X); - %0 = %1 (X); - %0 = %1 (Z); - # - %0 = %1%! - %0 = %1%!" - [(set_attr "type" "move,move,move,move,mvi,mvi,mvi,*,mcld,mcst") - (set_attr "length" "2,2,2,2,2,4,4,*,*,*")]) - -(define_insn "*movsi_insn32" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "d,P0")] UNSPEC_32BIT))] - "" - "@ - %0 = ROT %1 BY 0%! - %0 = %0 -|- %0%!" - [(set_attr "type" "dsp32shiftimm,dsp32")]) - -(define_split - [(set (match_operand:SI 0 "d_register_operand" "") - (const_int 0))] - "splitting_for_sched && !optimize_size" - [(set (match_dup 0) (unspec:SI [(const_int 0)] UNSPEC_32BIT))]) - -(define_split - [(set (match_operand:SI 0 "d_register_operand" "") - (match_operand:SI 1 "d_register_operand" ""))] - "splitting_for_sched && !optimize_size" - [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_32BIT))]) - -(define_insn_and_split "*movv2hi_insn" - [(set (match_operand:V2HI 0 "nonimmediate_operand" "=da,da,d,dm") - (match_operand:V2HI 1 "general_operand" "i,di,md,d"))] - - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "@ - # - %0 = %1; - %0 = %1%! - %0 = %1%!" - "reload_completed && GET_CODE (operands[1]) == CONST_VECTOR" - [(set (match_dup 0) (high:SI (match_dup 2))) - (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 3)))] -{ - HOST_WIDE_INT intval = INTVAL (XVECEXP (operands[1], 0, 1)) << 16; - intval |= INTVAL (XVECEXP (operands[1], 0, 0)) & 0xFFFF; - - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - operands[2] = operands[3] = GEN_INT (trunc_int_for_mode (intval, SImode)); -} - [(set_attr "type" "move,move,mcld,mcst") - (set_attr "length" "2,2,*,*")]) - -(define_insn "*movhi_insn" - [(set (match_operand:HI 0 "nonimmediate_operand" "=x,da,x,d,mr") - (match_operand:HI 1 "general_operand" "x,xKs7,xKsh,mr,d"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" -{ - static const char *templates[] = { - "%0 = %1;", - "%0 = %1 (X);", - "%0 = %1 (X);", - "%0 = W %1 (X)%!", - "W %0 = %1%!", - "%h0 = W %1%!", - "W %0 = %h1%!" - }; - int alt = which_alternative; - rtx mem = (MEM_P (operands[0]) ? operands[0] - : MEM_P (operands[1]) ? operands[1] : NULL_RTX); - if (mem && bfin_dsp_memref_p (mem)) - alt += 2; - return templates[alt]; -} - [(set_attr "type" "move,mvi,mvi,mcld,mcst") - (set_attr "length" "2,2,4,*,*")]) - -(define_insn "*movqi_insn" - [(set (match_operand:QI 0 "nonimmediate_operand" "=x,da,x,d,mr") - (match_operand:QI 1 "general_operand" "x,xKs7,xKsh,mr,d"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "@ - %0 = %1; - %0 = %1 (X); - %0 = %1 (X); - %0 = B %1 (X)%! - B %0 = %1%!" - [(set_attr "type" "move,mvi,mvi,mcld,mcst") - (set_attr "length" "2,2,4,*,*")]) - -(define_insn "*movsf_insn" - [(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,da,mr") - (match_operand:SF 1 "general_operand" "x,Fx,mr,da"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "@ - %0 = %1; - # - %0 = %1%! - %0 = %1%!" - [(set_attr "type" "move,*,mcld,mcst")]) - -(define_insn_and_split "movdf_insn" - [(set (match_operand:DF 0 "nonimmediate_operand" "=x,mx,r") - (match_operand:DF 1 "general_operand" "iFx,r,mx"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] -{ - rtx lo_half[2], hi_half[2]; - split_di (operands, 2, lo_half, hi_half); - - if (reg_overlap_mentioned_p (lo_half[0], hi_half[1])) - { - operands[2] = hi_half[0]; - operands[3] = hi_half[1]; - operands[4] = lo_half[0]; - operands[5] = lo_half[1]; - } - else - { - operands[2] = lo_half[0]; - operands[3] = lo_half[1]; - operands[4] = hi_half[0]; - operands[5] = hi_half[1]; - } -}) - -;; Storing halfwords. -(define_insn "*movsi_insv" - [(set (zero_extract:SI (match_operand 0 "register_operand" "+d,x") - (const_int 16) - (const_int 16)) - (match_operand:SI 1 "nonmemory_operand" "d,n"))] - "" - "@ - %d0 = %h1 << 0%! - %d0 = %1;" - [(set_attr "type" "dsp32shiftimm,mvi")]) - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "immediate_operand" "") - (match_operand:SI 2 "immediate_operand" "")) - (match_operand:SI 3 "nonmemory_operand" ""))] - "" -{ - if (INTVAL (operands[1]) != 16 || INTVAL (operands[2]) != 16) - FAIL; - - /* From mips.md: insert_bit_field doesn't verify that our source - matches the predicate, so check it again here. */ - if (! register_operand (operands[0], VOIDmode)) - FAIL; -}) - -;; This is the main "hook" for PIC code. When generating -;; PIC, movsi is responsible for determining when the source address -;; needs PIC relocation and appropriately calling legitimize_pic_address -;; to perform the actual relocation. - -(define_expand "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" -{ - if (expand_move (operands, SImode)) - DONE; -}) - -(define_expand "movv2hi" - [(set (match_operand:V2HI 0 "nonimmediate_operand" "") - (match_operand:V2HI 1 "general_operand" ""))] - "" - "expand_move (operands, V2HImode);") - -(define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - "expand_move (operands, DImode);") - -(define_expand "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - "expand_move (operands, SFmode);") - -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - "expand_move (operands, DFmode);") - -(define_expand "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - "expand_move (operands, HImode);") - -(define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " expand_move (operands, QImode); ") - -;; Some define_splits to break up SI/SFmode loads of immediate constants. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "symbolic_or_const_operand" ""))] - "reload_completed - /* Always split symbolic operands; split integer constants that are - too large for a single instruction. */ - && (GET_CODE (operands[1]) != CONST_INT - || (INTVAL (operands[1]) < -32768 - || INTVAL (operands[1]) >= 65536 - || (INTVAL (operands[1]) >= 32768 && PREG_P (operands[0]))))" - [(set (match_dup 0) (high:SI (match_dup 1))) - (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))] -{ - if (GET_CODE (operands[1]) == CONST_INT - && split_load_immediate (operands)) - DONE; - /* ??? Do something about TARGET_LOW_64K. */ -}) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "immediate_operand" ""))] - "reload_completed" - [(set (match_dup 2) (high:SI (match_dup 3))) - (set (match_dup 2) (lo_sum:SI (match_dup 2) (match_dup 3)))] -{ - long values; - REAL_VALUE_TYPE value; - - gcc_assert (GET_CODE (operands[1]) == CONST_DOUBLE); - - REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (value, values); - - operands[2] = gen_rtx_REG (SImode, true_regnum (operands[0])); - operands[3] = GEN_INT (trunc_int_for_mode (values, SImode)); - if (values >= -32768 && values < 65536) - { - emit_move_insn (operands[2], operands[3]); - DONE; - } - if (split_load_immediate (operands + 2)) - DONE; -}) - -;; Sadly, this can't be a proper named movstrict pattern, since the compiler -;; expects to be able to use registers for operand 1. -;; Note that the asm instruction is defined by the manual to take an unsigned -;; constant, but it doesn't matter to the assembler, and the compiler only -;; deals with sign-extended constants. Hence "Ksh". -(define_insn "movstricthi_1" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+x")) - (match_operand:HI 1 "immediate_operand" "Ksh"))] - "" - "%h0 = %1;" - [(set_attr "type" "mvi") - (set_attr "length" "4")]) - -;; Sign and zero extensions - -(define_insn_and_split "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=d, d") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d, m")))] - "" - "@ - %0 = %h1 (X); - %0 = W %h1 (X)%!" - "reload_completed && bfin_dsp_memref_p (operands[1])" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (sign_extend:SI (match_dup 2)))] -{ - operands[2] = gen_lowpart (HImode, operands[0]); -} - [(set_attr "type" "alu0,mcld")]) - -(define_insn_and_split "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=d, d") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d, m")))] - "" - "@ - %0 = %h1 (Z); - %0 = W %h1 (Z)%!" - "reload_completed && bfin_dsp_memref_p (operands[1])" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (zero_extend:SI (match_dup 2)))] -{ - operands[2] = gen_lowpart (HImode, operands[0]); -} - [(set_attr "type" "alu0,mcld")]) - -(define_insn "zero_extendbisi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI (match_operand:BI 1 "nonimmediate_operand" "C")))] - "" - "%0 = %1;" - [(set_attr "type" "compare")]) - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=d, d") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m, d")))] - "" - "@ - %0 = B %1 (X)%! - %0 = %T1 (X);" - [(set_attr "type" "mcld,alu0")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=d, d") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m, d")))] - "" - "@ - %0 = B %1 (X)%! - %0 = %T1 (X);" - [(set_attr "type" "mcld,alu0")]) - - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=d, d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m, d")))] - "" - "@ - %0 = B %1 (Z)%! - %0 = %T1 (Z);" - [(set_attr "type" "mcld,alu0")]) - - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=d, d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m, d")))] - "" - "@ - %0 = B %1 (Z)%! - %0 = %T1 (Z);" - [(set_attr "type" "mcld,alu0")]) - -;; DImode logical operations - -(define_code_iterator any_logical [and ior xor]) -(define_code_attr optab [(and "and") - (ior "ior") - (xor "xor")]) -(define_code_attr op [(and "&") - (ior "|") - (xor "^")]) -(define_code_attr high_result [(and "0") - (ior "%H1") - (xor "%H1")]) - -;; Keep this pattern around to avoid generating NO_CONFLICT blocks. -(define_expand "<optab>di3" - [(set (match_operand:DI 0 "register_operand" "=d") - (any_logical:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "general_operand" "d")))] - "" -{ - rtx hi_half[3], lo_half[3]; - enum insn_code icode = CODE_FOR_<optab>si3; - if (!reg_overlap_mentioned_p (operands[0], operands[1]) - && !reg_overlap_mentioned_p (operands[0], operands[2])) - emit_clobber (operands[0]); - split_di (operands, 3, lo_half, hi_half); - if (!(*insn_data[icode].operand[2].predicate) (lo_half[2], SImode)) - lo_half[2] = force_reg (SImode, lo_half[2]); - emit_insn (GEN_FCN (icode) (lo_half[0], lo_half[1], lo_half[2])); - if (!(*insn_data[icode].operand[2].predicate) (hi_half[2], SImode)) - hi_half[2] = force_reg (SImode, hi_half[2]); - emit_insn (GEN_FCN (icode) (hi_half[0], hi_half[1], hi_half[2])); - DONE; -}) - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (match_operand:QI 1 "register_operand" "d")))] - "" - "%0 = %T1 (Z);\\n\\t%H0 = 0;" - [(set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -(define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (match_operand:HI 1 "register_operand" "d")))] - "" - "%0 = %h1 (Z);\\n\\t%H0 = 0;" - [(set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -(define_insn_and_split "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (match_operand:SI 1 "register_operand" "d")))] - "" - "#" - "reload_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 3) (ashiftrt:SI (match_dup 3) (const_int 31)))] -{ - split_di (operands, 1, operands + 2, operands + 3); - if (REGNO (operands[0]) != REGNO (operands[1])) - emit_move_insn (operands[2], operands[1]); -}) - -(define_insn_and_split "extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 3) (const_int 31)))] -{ - split_di (operands, 1, operands + 2, operands + 3); -}) - -(define_insn_and_split "extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 3) (const_int 31)))] -{ - split_di (operands, 1, operands + 2, operands + 3); -}) - -;; DImode arithmetic operations - -(define_insn "add_with_carry" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (plus:SI (match_operand:SI 1 "register_operand" "%0,d") - (match_operand:SI 2 "nonmemory_operand" "Ks7,d"))) - (set (match_operand:BI 3 "register_operand" "=C,C") - (ltu:BI (not:SI (match_dup 1)) (match_dup 2)))] - "" - "@ - %0 += %2; cc = ac0; - %0 = %1 + %2; cc = ac0;" - [(set_attr "type" "alu0") - (set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -(define_insn "sub_with_carry" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (match_operand:SI 1 "register_operand" "%d") - (match_operand:SI 2 "nonmemory_operand" "d"))) - (set (match_operand:BI 3 "register_operand" "=C") - (leu:BI (match_dup 2) (match_dup 1)))] - "" - "%0 = %1 - %2; cc = ac0;" - [(set_attr "type" "alu0") - (set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -(define_expand "adddi3" - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:SI 3 "")) - (clobber (reg:CC 34))] - "" -{ - rtx xops[8]; - xops[0] = gen_lowpart (SImode, operands[0]); - xops[1] = simplify_gen_subreg (SImode, operands[0], DImode, 4); - xops[2] = gen_lowpart (SImode, operands[1]); - xops[3] = simplify_gen_subreg (SImode, operands[1], DImode, 4); - xops[4] = gen_lowpart (SImode, operands[2]); - xops[5] = simplify_gen_subreg (SImode, operands[2], DImode, 4); - xops[6] = gen_reg_rtx (SImode); - xops[7] = gen_rtx_REG (BImode, REG_CC); - if (!register_operand (xops[4], SImode) - && (GET_CODE (xops[4]) != CONST_INT - || !satisfies_constraint_Ks7 (xops[4]))) - xops[4] = force_reg (SImode, xops[4]); - if (!reg_overlap_mentioned_p (operands[0], operands[1]) - && !reg_overlap_mentioned_p (operands[0], operands[2])) - emit_clobber (operands[0]); - emit_insn (gen_add_with_carry (xops[0], xops[2], xops[4], xops[7])); - emit_insn (gen_movbisi (xops[6], xops[7])); - if (!register_operand (xops[5], SImode) - && (GET_CODE (xops[5]) != CONST_INT - || !satisfies_constraint_Ks7 (xops[5]))) - xops[5] = force_reg (SImode, xops[5]); - if (xops[5] != const0_rtx) - emit_insn (gen_addsi3 (xops[1], xops[3], xops[5])); - else - emit_move_insn (xops[1], xops[3]); - emit_insn (gen_addsi3 (xops[1], xops[1], xops[6])); - DONE; -}) - -(define_expand "subdi3" - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (clobber (reg:CC 34))] - "" -{ - rtx xops[8]; - xops[0] = gen_lowpart (SImode, operands[0]); - xops[1] = simplify_gen_subreg (SImode, operands[0], DImode, 4); - xops[2] = gen_lowpart (SImode, operands[1]); - xops[3] = simplify_gen_subreg (SImode, operands[1], DImode, 4); - xops[4] = gen_lowpart (SImode, operands[2]); - xops[5] = simplify_gen_subreg (SImode, operands[2], DImode, 4); - xops[6] = gen_reg_rtx (SImode); - xops[7] = gen_rtx_REG (BImode, REG_CC); - if (!reg_overlap_mentioned_p (operands[0], operands[1]) - && !reg_overlap_mentioned_p (operands[0], operands[2])) - emit_clobber (operands[0]); - emit_insn (gen_sub_with_carry (xops[0], xops[2], xops[4], xops[7])); - emit_insn (gen_notbi (xops[7], xops[7])); - emit_insn (gen_movbisi (xops[6], xops[7])); - emit_insn (gen_subsi3 (xops[1], xops[3], xops[5])); - emit_insn (gen_subsi3 (xops[1], xops[1], xops[6])); - DONE; -}) - -;; Combined shift/add instructions - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a,d") - (ashift:SI (plus:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "register_operand" "a,d")) - (match_operand:SI 3 "pos_scale_operand" "P1P2,P1P2")))] - "" - "%0 = (%0 + %2) << %3;" /* "shadd %0,%2,%3;" */ - [(set_attr "type" "alu0")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 1 "register_operand" "a") - (mult:SI (match_operand:SI 2 "register_operand" "a") - (match_operand:SI 3 "scale_by_operand" "i"))))] - "" - "%0 = %1 + (%2 << %X3);" - [(set_attr "type" "alu0")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 1 "register_operand" "a") - (ashift:SI (match_operand:SI 2 "register_operand" "a") - (match_operand:SI 3 "pos_scale_operand" "i"))))] - "" - "%0 = %1 + (%2 << %3);" - [(set_attr "type" "alu0")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "a") - (match_operand:SI 2 "scale_by_operand" "i")) - (match_operand:SI 3 "register_operand" "a")))] - "" - "%0 = %3 + (%1 << %X2);" - [(set_attr "type" "alu0")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "a") - (match_operand:SI 2 "pos_scale_operand" "i")) - (match_operand:SI 3 "register_operand" "a")))] - "" - "%0 = %3 + (%1 << %2);" - [(set_attr "type" "alu0")]) - -(define_insn "mulhisi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%d")) - (sign_extend:SI (match_operand:HI 2 "register_operand" "d"))))] - "" - "%0 = %h1 * %h2 (IS)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "umulhisi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%d")) - (zero_extend:SI (match_operand:HI 2 "register_operand" "d"))))] - "" - "%0 = %h1 * %h2 (FU)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi3" - [(set (match_operand:SI 0 "register_operand" "=W") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "W")) - (sign_extend:SI (match_operand:HI 2 "register_operand" "W"))))] - "" - "%0 = %h2 * %h1 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -;; The alternative involving IREGS requires that the corresponding L register -;; is zero. - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=ad,a,d,b") - (plus:SI (match_operand:SI 1 "register_operand" "%0, a,d,0") - (match_operand:SI 2 "reg_or_7bit_operand" "Ks7, a,d,fP2P4")))] - "" - "@ - %0 += %2; - %0 = %1 + %2; - %0 = %1 + %2; - %0 += %2;" - [(set_attr "type" "alu0") - (set_attr "length" "2,2,2,2")]) - -(define_insn "ssaddsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ss_plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "%0 = %1 + %2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=da,d,a") - (minus:SI (match_operand:SI 1 "register_operand" "0,d,0") - (match_operand:SI 2 "reg_or_neg7bit_operand" "KN7,d,a")))] - "" -{ - static const char *const strings_subsi3[] = { - "%0 += -%2;", - "%0 = %1 - %2;", - "%0 -= %2;", - }; - - if (CONSTANT_P (operands[2]) && INTVAL (operands[2]) < 0) { - rtx tmp_op = operands[2]; - operands[2] = GEN_INT (-INTVAL (operands[2])); - output_asm_insn ("%0 += %2;", operands); - operands[2] = tmp_op; - return ""; - } - - return strings_subsi3[which_alternative]; -} - [(set_attr "type" "alu0")]) - -(define_insn "sssubsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ss_minus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "%0 = %1 - %2 (S)%!" - [(set_attr "type" "dsp32")]) - -;; Accumulator addition - -(define_insn "addpdi3" - [(set (match_operand:PDI 0 "register_operand" "=A") - (ss_plus:PDI (match_operand:PDI 1 "register_operand" "%0") - (match_operand:PDI 2 "nonmemory_operand" "B")))] - "" - "A0 += A1%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sum_of_accumulators" - [(set (match_operand:SI 0 "register_operand" "=d") - (ss_truncate:SI - (ss_plus:PDI (match_operand:PDI 2 "register_operand" "1") - (match_operand:PDI 3 "register_operand" "B")))) - (set (match_operand:PDI 1 "register_operand" "=A") - (ss_plus:PDI (match_dup 2) (match_dup 3)))] - "" - "%0 = (A0 += A1)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "us_truncpdisi2" - [(set (match_operand:SI 0 "register_operand" "=D,W") - (us_truncate:SI (match_operand:PDI 1 "register_operand" "A,B")))] - "" - "%0 = %1 (FU)%!" - [(set_attr "type" "dsp32")]) - -;; Bit test instructions - -(define_insn "*not_bittst" - [(set (match_operand:BI 0 "register_operand" "=C") - (eq:BI (zero_extract:SI (match_operand:SI 1 "register_operand" "d") - (const_int 1) - (match_operand:SI 2 "immediate_operand" "Ku5")) - (const_int 0)))] - "" - "cc = !BITTST (%1,%2);" - [(set_attr "type" "alu0")]) - -(define_insn "*bittst" - [(set (match_operand:BI 0 "register_operand" "=C") - (ne:BI (zero_extract:SI (match_operand:SI 1 "register_operand" "d") - (const_int 1) - (match_operand:SI 2 "immediate_operand" "Ku5")) - (const_int 0)))] - "" - "cc = BITTST (%1,%2);" - [(set_attr "type" "alu0")]) - -(define_insn_and_split "*bit_extract" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extract:SI (match_operand:SI 1 "register_operand" "d") - (const_int 1) - (match_operand:SI 2 "immediate_operand" "Ku5"))) - (clobber (reg:BI REG_CC))] - "" - "#" - "" - [(set (reg:BI REG_CC) - (ne:BI (zero_extract:SI (match_dup 1) (const_int 1) (match_dup 2)) - (const_int 0))) - (set (match_dup 0) - (ne:SI (reg:BI REG_CC) (const_int 0)))]) - -(define_insn_and_split "*not_bit_extract" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extract:SI (not:SI (match_operand:SI 1 "register_operand" "d")) - (const_int 1) - (match_operand:SI 2 "immediate_operand" "Ku5"))) - (clobber (reg:BI REG_CC))] - "" - "#" - "" - [(set (reg:BI REG_CC) - (eq:BI (zero_extract:SI (match_dup 1) (const_int 1) (match_dup 2)) - (const_int 0))) - (set (match_dup 0) - (ne:SI (reg:BI REG_CC) (const_int 0)))]) - -(define_insn "*andsi_insn" - [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") - (and:SI (match_operand:SI 1 "register_operand" "%0,d,d,d") - (match_operand:SI 2 "rhs_andsi3_operand" "L,M1,M2,d")))] - "" - "@ - BITCLR (%0,%Y2); - %0 = %T1 (Z); - %0 = %h1 (Z); - %0 = %1 & %2;" - [(set_attr "type" "alu0")]) - -(define_expand "andsi3" - [(set (match_operand:SI 0 "register_operand" "") - (and:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" -{ - if (highbits_operand (operands[2], SImode)) - { - operands[2] = GEN_INT (exact_log2 (-INTVAL (operands[2]))); - emit_insn (gen_ashrsi3 (operands[0], operands[1], operands[2])); - emit_insn (gen_ashlsi3 (operands[0], operands[0], operands[2])); - DONE; - } - if (! rhs_andsi3_operand (operands[2], SImode)) - operands[2] = force_reg (SImode, operands[2]); -}) - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ior:SI (match_operand:SI 1 "register_operand" "%0,d") - (match_operand:SI 2 "regorlog2_operand" "J,d")))] - "" - "@ - BITSET (%0, %X2); - %0 = %1 | %2;" - [(set_attr "type" "alu0")]) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (xor:SI (match_operand:SI 1 "register_operand" "%0,d") - (match_operand:SI 2 "regorlog2_operand" "J,d")))] - "" - "@ - BITTGL (%0, %X2); - %0 = %1 ^ %2;" - [(set_attr "type" "alu0")]) - -(define_insn "ones" - [(set (match_operand:HI 0 "register_operand" "=d") - (unspec:HI [(match_operand:SI 1 "register_operand" "d")] - UNSPEC_ONES))] - "" - "%h0 = ONES %1;" - [(set_attr "type" "alu0")]) - -(define_insn "smaxsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (smax:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "%0 = max(%1,%2)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sminsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (smin:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "%0 = min(%1,%2)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "abssi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (abs:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = abs %1%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssabssi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (ss_abs:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = abs %1%!" - [(set_attr "type" "dsp32")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (neg:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = -%1;" - [(set_attr "type" "alu0")]) - -(define_insn "ssnegsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (ss_neg:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = -%1 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (not:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "%0 = ~%1;" - [(set_attr "type" "alu0")]) - -(define_expand "clrsbsi2" - [(set (match_dup 2) - (truncate:HI (clrsb:SI (match_operand:SI 1 "register_operand" "d")))) - (set (match_operand:SI 0 "register_operand") - (zero_extend:SI (match_dup 2)))] - "" -{ - operands[2] = gen_reg_rtx (HImode); -}) - -(define_insn "signbitssi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (truncate:HI (clrsb:SI (match_operand:SI 1 "register_operand" "d"))))] - "" - "%h0 = signbits %1%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssroundsi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (truncate:HI - (lshiftrt:SI (ss_plus:SI (match_operand:SI 1 "register_operand" "d") - (const_int 32768)) - (const_int 16))))] - "" - "%h0 = %1 (RND)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "smaxhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (smax:HI (match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d")))] - "" - "%0 = max(%1,%2) (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sminhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (smin:HI (match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d")))] - "" - "%0 = min(%1,%2) (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "abshi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (abs:HI (match_operand:HI 1 "register_operand" "d")))] - "" - "%0 = abs %1 (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (neg:HI (match_operand:HI 1 "register_operand" "d")))] - "" - "%0 = -%1;" - [(set_attr "type" "alu0")]) - -(define_insn "ssneghi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_neg:HI (match_operand:HI 1 "register_operand" "d")))] - "" - "%0 = -%1 (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "clrsbhi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (clrsb:HI (match_operand:HI 1 "register_operand" "d")))] - "" - "%h0 = signbits %h1%!" - [(set_attr "type" "dsp32")]) - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "d")))] - "" - "%0 *= %2;" - [(set_attr "type" "mult")]) - -(define_expand "umulsi3_highpart" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (zero_extend:DI - (match_operand:SI 2 "register_operand" ""))) - (const_int 32)))) - (clobber (reg:PDI REG_A0)) - (clobber (reg:PDI REG_A1))])] - "" -{ - if (!optimize_size) - { - rtx a1reg = gen_rtx_REG (PDImode, REG_A1); - rtx a0reg = gen_rtx_REG (PDImode, REG_A0); - emit_insn (gen_flag_macinit1hi (a1reg, - gen_lowpart (HImode, operands[1]), - gen_lowpart (HImode, operands[2]), - GEN_INT (MACFLAG_FU))); - emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16))); - emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, - gen_lowpart (V2HImode, operands[1]), - gen_lowpart (V2HImode, operands[2]), - const1_rtx, const1_rtx, - const1_rtx, const0_rtx, a1reg, - const0_rtx, GEN_INT (MACFLAG_FU), - GEN_INT (MACFLAG_FU))); - emit_insn (gen_flag_machi_parts_acconly (a1reg, - gen_lowpart (V2HImode, operands[2]), - gen_lowpart (V2HImode, operands[1]), - const1_rtx, const0_rtx, - a1reg, const0_rtx, GEN_INT (MACFLAG_FU))); - emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16))); - emit_insn (gen_addpdi3 (a0reg, a0reg, a1reg)); - emit_insn (gen_us_truncpdisi2 (operands[0], a0reg)); - } - else - { - rtx umulsi3_highpart_libfunc - = init_one_libfunc ("__umulsi3_highpart"); - - emit_library_call_value (umulsi3_highpart_libfunc, - operands[0], LCT_NORMAL, SImode, - 2, operands[1], SImode, operands[2], SImode); - } - DONE; -}) - -(define_expand "smulsi3_highpart" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (truncate:SI - (lshiftrt:DI - (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "")) - (sign_extend:DI - (match_operand:SI 2 "register_operand" ""))) - (const_int 32)))) - (clobber (reg:PDI REG_A0)) - (clobber (reg:PDI REG_A1))])] - "" -{ - if (!optimize_size) - { - rtx a1reg = gen_rtx_REG (PDImode, REG_A1); - rtx a0reg = gen_rtx_REG (PDImode, REG_A0); - emit_insn (gen_flag_macinit1hi (a1reg, - gen_lowpart (HImode, operands[1]), - gen_lowpart (HImode, operands[2]), - GEN_INT (MACFLAG_FU))); - emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16))); - emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, - gen_lowpart (V2HImode, operands[1]), - gen_lowpart (V2HImode, operands[2]), - const1_rtx, const1_rtx, - const1_rtx, const0_rtx, a1reg, - const0_rtx, GEN_INT (MACFLAG_IS), - GEN_INT (MACFLAG_IS_M))); - emit_insn (gen_flag_machi_parts_acconly (a1reg, - gen_lowpart (V2HImode, operands[2]), - gen_lowpart (V2HImode, operands[1]), - const1_rtx, const0_rtx, - a1reg, const0_rtx, GEN_INT (MACFLAG_IS_M))); - emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (16))); - emit_insn (gen_sum_of_accumulators (operands[0], a0reg, a0reg, a1reg)); - } - else - { - rtx smulsi3_highpart_libfunc - = init_one_libfunc ("__smulsi3_highpart"); - - emit_library_call_value (smulsi3_highpart_libfunc, - operands[0], LCT_NORMAL, SImode, - 2, operands[1], SImode, operands[2], SImode); - } - DONE; -}) - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" -{ - if (GET_CODE (operands[2]) == CONST_INT - && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) - { - emit_insn (gen_movsi (operands[0], const0_rtx)); - DONE; - } -}) - -(define_insn_and_split "*ashlsi3_insn" - [(set (match_operand:SI 0 "register_operand" "=d,d,a,a,a") - (ashift:SI (match_operand:SI 1 "register_operand" "0,d,a,a,a") - (match_operand:SI 2 "nonmemory_operand" "dKu5,Ku5,P1,P2,?P3P4")))] - "" - "@ - %0 <<= %2; - %0 = %1 << %2%! - %0 = %1 + %1; - %0 = %1 << %2; - #" - "PREG_P (operands[0]) && INTVAL (operands[2]) > 2" - [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 2))) - (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3)))] - "operands[3] = GEN_INT (INTVAL (operands[2]) - 2);" - [(set_attr "type" "shft,dsp32shiftimm,shft,shft,*")]) - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,d") - (match_operand:SI 2 "nonmemory_operand" "dKu5,Ku5")))] - "" - "@ - %0 >>>= %2; - %0 = %1 >>> %2%!" - [(set_attr "type" "shft,dsp32shiftimm")]) - -(define_insn "rotl16" - [(set (match_operand:SI 0 "register_operand" "=d") - (rotate:SI (match_operand:SI 1 "register_operand" "d") - (const_int 16)))] - "" - "%0 = PACK (%h1, %d1)%!" - [(set_attr "type" "dsp32")]) - -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (rotate:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "" -{ - if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 16) - FAIL; -}) - -(define_expand "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (rotatert:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "" -{ - if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 16) - FAIL; - emit_insn (gen_rotl16 (operands[0], operands[1])); - DONE; -}) - - -(define_insn "ror_one" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") (const_int 1)) - (ashift:SI (zero_extend:SI (reg:BI REG_CC)) (const_int 31)))) - (set (reg:BI REG_CC) - (zero_extract:BI (match_dup 1) (const_int 1) (const_int 0)))] - "" - "%0 = ROT %1 BY -1%!" - [(set_attr "type" "dsp32shiftimm")]) - -(define_insn "rol_one" - [(set (match_operand:SI 0 "register_operand" "+d") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 1)) - (zero_extend:SI (reg:BI REG_CC)))) - (set (reg:BI REG_CC) - (zero_extract:BI (match_dup 1) (const_int 31) (const_int 0)))] - "" - "%0 = ROT %1 BY 1%!" - [(set_attr "type" "dsp32shiftimm")]) - -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "" -{ - rtx lo_half[2], hi_half[2]; - - if (operands[2] != const1_rtx) - FAIL; - if (! rtx_equal_p (operands[0], operands[1])) - emit_move_insn (operands[0], operands[1]); - - split_di (operands, 2, lo_half, hi_half); - - emit_move_insn (bfin_cc_rtx, const0_rtx); - emit_insn (gen_ror_one (hi_half[0], hi_half[0])); - emit_insn (gen_ror_one (lo_half[0], lo_half[0])); - DONE; -}) - -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "" -{ - rtx lo_half[2], hi_half[2]; - - if (operands[2] != const1_rtx) - FAIL; - if (! rtx_equal_p (operands[0], operands[1])) - emit_move_insn (operands[0], operands[1]); - - split_di (operands, 2, lo_half, hi_half); - - emit_insn (gen_compare_lt (gen_rtx_REG (BImode, REG_CC), - hi_half[1], const0_rtx)); - emit_insn (gen_ror_one (hi_half[0], hi_half[0])); - emit_insn (gen_ror_one (lo_half[0], lo_half[0])); - DONE; -}) - -(define_expand "ashldi3" - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "" -{ - rtx lo_half[2], hi_half[2]; - - if (operands[2] != const1_rtx) - FAIL; - if (! rtx_equal_p (operands[0], operands[1])) - emit_move_insn (operands[0], operands[1]); - - split_di (operands, 2, lo_half, hi_half); - - emit_move_insn (bfin_cc_rtx, const0_rtx); - emit_insn (gen_rol_one (lo_half[0], lo_half[0])); - emit_insn (gen_rol_one (hi_half[0], hi_half[0])); - DONE; -}) - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,a") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,d,a") - (match_operand:SI 2 "nonmemory_operand" "dKu5,Ku5,P1P2")))] - "" - "@ - %0 >>= %2; - %0 = %1 >> %2%! - %0 = %1 >> %2;" - [(set_attr "type" "shft,dsp32shiftimm,shft")]) - -(define_insn "lshrpdi3" - [(set (match_operand:PDI 0 "register_operand" "=e") - (lshiftrt:PDI (match_operand:PDI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "Ku5")))] - "" - "%0 = %1 >> %2%!" - [(set_attr "type" "dsp32shiftimm")]) - -(define_insn "ashrpdi3" - [(set (match_operand:PDI 0 "register_operand" "=e") - (ashiftrt:PDI (match_operand:PDI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "Ku5")))] - "" - "%0 = %1 >>> %2%!" - [(set_attr "type" "dsp32shiftimm")]) - -;; A pattern to reload the equivalent of -;; (set (Dreg) (plus (FP) (large_constant))) -;; or -;; (set (dagreg) (plus (FP) (arbitrary_constant))) -;; using a scratch register -(define_expand "reload_insi" - [(parallel [(set (match_operand:SI 0 "register_operand" "=w") - (match_operand:SI 1 "fp_plus_const_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&a"))])] - "" -{ - rtx fp_op = XEXP (operands[1], 0); - rtx const_op = XEXP (operands[1], 1); - rtx primary = operands[0]; - rtx scratch = operands[2]; - - emit_move_insn (scratch, const_op); - emit_insn (gen_addsi3 (scratch, scratch, fp_op)); - emit_move_insn (primary, scratch); - DONE; -}) - -(define_mode_iterator AREG [PDI V2PDI]) - -(define_insn "reload_in<mode>" - [(set (match_operand:AREG 0 "register_operand" "=e") - (match_operand:AREG 1 "memory_operand" "m")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "" -{ - rtx xops[4]; - xops[0] = operands[0]; - xops[1] = operands[2]; - split_di (operands + 1, 1, xops + 2, xops + 3); - output_asm_insn ("%1 = %2;", xops); - output_asm_insn ("%w0 = %1;", xops); - output_asm_insn ("%1 = %3;", xops); - output_asm_insn ("%x0 = %1;", xops); - return ""; -} - [(set_attr "seq_insns" "multi") - (set_attr "type" "mcld") - (set_attr "length" "12")]) - -(define_insn "reload_out<mode>" - [(set (match_operand:AREG 0 "memory_operand" "=m") - (match_operand:AREG 1 "register_operand" "e")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "" -{ - rtx xops[4]; - xops[0] = operands[1]; - xops[1] = operands[2]; - split_di (operands, 1, xops + 2, xops + 3); - output_asm_insn ("%1 = %w0;", xops); - output_asm_insn ("%2 = %1;", xops); - output_asm_insn ("%1 = %x0;", xops); - output_asm_insn ("%3 = %1;", xops); - return ""; -} - [(set_attr "seq_insns" "multi") - (set_attr "type" "mcld") - (set_attr "length" "12")]) - -;; Jump instructions - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" -{ - if (get_attr_length (insn) == 2) - return "jump.s %0;"; - else - return "jump.l %0;"; -} - [(set_attr "type" "br")]) - -(define_insn "indirect_jump" - [(set (pc) - (match_operand:SI 0 "register_operand" "a"))] - "" - "jump (%0);" - [(set_attr "type" "misc")]) - -(define_expand "tablejump" - [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "a")) - (use (label_ref (match_operand 1 "" "")))])] - "" -{ - /* In PIC mode, the table entries are stored PC relative. - Convert the relative address to an absolute address. */ - if (flag_pic) - { - rtx op1 = gen_rtx_LABEL_REF (Pmode, operands[1]); - - operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], - op1, NULL_RTX, 0, OPTAB_DIRECT); - } -}) - -(define_insn "*tablejump_internal" - [(set (pc) (match_operand:SI 0 "register_operand" "a")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jump (%0);" - [(set_attr "type" "misc")]) - -;; Hardware loop - -; operand 0 is the loop count pseudo register -; operand 1 is the number of loop iterations or 0 if it is unknown -; operand 2 is the maximum number of loop iterations -; operand 3 is the number of levels of enclosed loops -; operand 4 is the label to jump to at the top of the loop -(define_expand "doloop_end" - [(parallel [(set (pc) (if_then_else - (ne (match_operand:SI 0 "" "") - (const_int 1)) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1))) - (unspec [(const_int 0)] UNSPEC_LSETUP_END) - (clobber (match_scratch:SI 5 ""))])] - "" -{ - /* The loop optimizer doesn't check the predicates... */ - if (GET_MODE (operands[0]) != SImode) - FAIL; - /* Due to limitations in the hardware (an initial loop count of 0 - does not loop 2^32 times) we must avoid to generate a hardware - loops when we cannot rule out this case. */ - if (!flag_unsafe_loop_optimizations - && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF) - FAIL; - bfin_hardware_loop (); -}) - -(define_insn "loop_end" - [(set (pc) - (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,0,0") - (const_int 1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_operand:SI 0 "nonimmediate_operand" "=a*d,*b*v*f,m") - (plus (match_dup 2) - (const_int -1))) - (unspec [(const_int 0)] UNSPEC_LSETUP_END) - (clobber (match_scratch:SI 3 "=X,&r,&r"))] - "" - "@ - /* loop end %0 %l1 */ - # - #" - [(set_attr "length" "6,10,14")]) - -(define_split - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "nondp_reg_or_memory_operand" "") - (const_int 1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus (match_dup 0) - (const_int -1))) - (unspec [(const_int 0)] UNSPEC_LSETUP_END) - (clobber (match_scratch:SI 2 "=&r"))] - "memory_operand (operands[0], SImode) || splitting_loops" - [(set (match_dup 2) (match_dup 0)) - (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1))) - (set (match_dup 0) (match_dup 2)) - (set (reg:BI REG_CC) (eq:BI (match_dup 2) (const_int 0))) - (set (pc) - (if_then_else (eq (reg:BI REG_CC) - (const_int 0)) - (label_ref (match_dup 1)) - (pc)))] - "") - -(define_insn "lsetup_with_autoinit" - [(set (match_operand:SI 0 "lt_register_operand" "=t") - (label_ref (match_operand 1 "" ""))) - (set (match_operand:SI 2 "lb_register_operand" "=u") - (label_ref (match_operand 3 "" ""))) - (set (match_operand:SI 4 "lc_register_operand" "=k") - (match_operand:SI 5 "register_operand" "a"))] - "" - "LSETUP (%1, %3) %4 = %5;" - [(set_attr "length" "4")]) - -(define_insn "lsetup_without_autoinit" - [(set (match_operand:SI 0 "lt_register_operand" "=t") - (label_ref (match_operand 1 "" ""))) - (set (match_operand:SI 2 "lb_register_operand" "=u") - (label_ref (match_operand 3 "" ""))) - (use (match_operand:SI 4 "lc_register_operand" "k"))] - "" - "LSETUP (%1, %3) %4;" - [(set_attr "length" "4")]) - -;; Call instructions.. - -;; The explicit MEM inside the UNSPEC prevents the compiler from moving -;; the load before a branch after a NULL test, or before a store that -;; initializes a function descriptor. - -(define_insn_and_split "load_funcdescsi" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))] - UNSPEC_VOLATILE_LOAD_FUNCDESC))] - "" - "#" - "reload_completed" - [(set (match_dup 0) (mem:SI (match_dup 1)))]) - -(define_expand "call" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))])] - "" -{ - bfin_expand_call (NULL_RTX, operands[0], operands[1], operands[2], 0); - DONE; -}) - -(define_expand "sibcall" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (return)])] - "" -{ - bfin_expand_call (NULL_RTX, operands[0], operands[1], operands[2], 1); - DONE; -}) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (match_operand:SI 1 "" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" ""))])] - "" -{ - bfin_expand_call (operands[0], operands[1], operands[2], operands[3], 0); - DONE; -}) - -(define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (match_operand:SI 1 "" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (return)])] - "" -{ - bfin_expand_call (operands[0], operands[1], operands[2], operands[3], 1); - DONE; -}) - -(define_insn "*call_symbol_fdpic" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) - (match_operand 1 "general_operand" "g")) - (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn) - && GET_CODE (operands[0]) == SYMBOL_REF - && !bfin_longcall_p (operands[0], INTVAL (operands[3]))" - "call %0;" - [(set_attr "type" "call") - (set_attr "length" "4")]) - -(define_insn "*sibcall_symbol_fdpic" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) - (match_operand 1 "general_operand" "g")) - (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" "")) - (return)] - "SIBLING_CALL_P (insn) - && GET_CODE (operands[0]) == SYMBOL_REF - && !bfin_longcall_p (operands[0], INTVAL (operands[3]))" - "jump.l %0;" - [(set_attr "type" "br") - (set_attr "length" "4")]) - -(define_insn "*call_value_symbol_fdpic" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn) - && GET_CODE (operands[1]) == SYMBOL_REF - && !bfin_longcall_p (operands[1], INTVAL (operands[4]))" - "call %1;" - [(set_attr "type" "call") - (set_attr "length" "4")]) - -(define_insn "*sibcall_value_symbol_fdpic" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" "")) - (return)] - "SIBLING_CALL_P (insn) - && GET_CODE (operands[1]) == SYMBOL_REF - && !bfin_longcall_p (operands[1], INTVAL (operands[4]))" - "jump.l %1;" - [(set_attr "type" "br") - (set_attr "length" "4")]) - -(define_insn "*call_insn_fdpic" - [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y")) - (match_operand 1 "general_operand" "g")) - (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn)" - "call (%0);" - [(set_attr "type" "call") - (set_attr "length" "2")]) - -(define_insn "*sibcall_insn_fdpic" - [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y")) - (match_operand 1 "general_operand" "g")) - (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" "")) - (return)] - "SIBLING_CALL_P (insn)" - "jump (%0);" - [(set_attr "type" "br") - (set_attr "length" "2")]) - -(define_insn "*call_value_insn_fdpic" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn)" - "call (%1);" - [(set_attr "type" "call") - (set_attr "length" "2")]) - -(define_insn "*sibcall_value_insn_fdpic" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" "")) - (return)] - "SIBLING_CALL_P (insn)" - "jump (%1);" - [(set_attr "type" "br") - (set_attr "length" "2")]) - -(define_insn "*call_symbol" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) - (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn) - && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) - && GET_CODE (operands[0]) == SYMBOL_REF - && !bfin_longcall_p (operands[0], INTVAL (operands[2]))" - "call %0;" - [(set_attr "type" "call") - (set_attr "length" "4")]) - -(define_insn "*sibcall_symbol" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) - (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" "")) - (return)] - "SIBLING_CALL_P (insn) - && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) - && GET_CODE (operands[0]) == SYMBOL_REF - && !bfin_longcall_p (operands[0], INTVAL (operands[2]))" - "jump.l %0;" - [(set_attr "type" "br") - (set_attr "length" "4")]) - -(define_insn "*call_value_symbol" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn) - && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) - && GET_CODE (operands[1]) == SYMBOL_REF - && !bfin_longcall_p (operands[1], INTVAL (operands[3]))" - "call %1;" - [(set_attr "type" "call") - (set_attr "length" "4")]) - -(define_insn "*sibcall_value_symbol" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" "")) - (return)] - "SIBLING_CALL_P (insn) - && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) - && GET_CODE (operands[1]) == SYMBOL_REF - && !bfin_longcall_p (operands[1], INTVAL (operands[3]))" - "jump.l %1;" - [(set_attr "type" "br") - (set_attr "length" "4")]) - -(define_insn "*call_insn" - [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "a")) - (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn)" - "call (%0);" - [(set_attr "type" "call") - (set_attr "length" "2")]) - -(define_insn "*sibcall_insn" - [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "z")) - (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" "")) - (return)] - "SIBLING_CALL_P (insn)" - "jump (%0);" - [(set_attr "type" "br") - (set_attr "length" "2")]) - -(define_insn "*call_value_insn" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "a")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" "")) - (clobber (reg:SI REG_RETS))] - "! SIBLING_CALL_P (insn)" - "call (%1);" - [(set_attr "type" "call") - (set_attr "length" "2")]) - -(define_insn "*sibcall_value_insn" - [(set (match_operand 0 "register_operand" "=d") - (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "z")) - (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" "")) - (return)] - "SIBLING_CALL_P (insn)" - "jump (%1);" - [(set_attr "type" "br") - (set_attr "length" "2")]) - -;; Block move patterns - -;; We cheat. This copies one more word than operand 2 indicates. - -(define_insn "rep_movsi" - [(set (match_operand:SI 0 "register_operand" "=&a") - (plus:SI (plus:SI (match_operand:SI 3 "register_operand" "0") - (ashift:SI (match_operand:SI 2 "register_operand" "a") - (const_int 2))) - (const_int 4))) - (set (match_operand:SI 1 "register_operand" "=&b") - (plus:SI (plus:SI (match_operand:SI 4 "register_operand" "1") - (ashift:SI (match_dup 2) (const_int 2))) - (const_int 4))) - (set (mem:BLK (match_dup 3)) - (mem:BLK (match_dup 4))) - (use (match_dup 2)) - (clobber (match_scratch:HI 5 "=&d")) - (clobber (reg:SI REG_LT1)) - (clobber (reg:SI REG_LC1)) - (clobber (reg:SI REG_LB1))] - "" - "%5 = [%4++]; lsetup (1f, 1f) LC1 = %2; 1: MNOP || [%3++] = %5 || %5 = [%4++]; [%3++] = %5;" - [(set_attr "type" "misc") - (set_attr "length" "16") - (set_attr "seq_insns" "multi")]) - -(define_insn "rep_movhi" - [(set (match_operand:SI 0 "register_operand" "=&a") - (plus:SI (plus:SI (match_operand:SI 3 "register_operand" "0") - (ashift:SI (match_operand:SI 2 "register_operand" "a") - (const_int 1))) - (const_int 2))) - (set (match_operand:SI 1 "register_operand" "=&b") - (plus:SI (plus:SI (match_operand:SI 4 "register_operand" "1") - (ashift:SI (match_dup 2) (const_int 1))) - (const_int 2))) - (set (mem:BLK (match_dup 3)) - (mem:BLK (match_dup 4))) - (use (match_dup 2)) - (clobber (match_scratch:HI 5 "=&d")) - (clobber (reg:SI REG_LT1)) - (clobber (reg:SI REG_LC1)) - (clobber (reg:SI REG_LB1))] - "" - "%h5 = W[%4++]; lsetup (1f, 1f) LC1 = %2; 1: MNOP || W [%3++] = %5 || %h5 = W [%4++]; W [%3++] = %5;" - [(set_attr "type" "misc") - (set_attr "length" "16") - (set_attr "seq_insns" "multi")]) - -(define_expand "movmemsi" - [(match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "") - (match_operand:SI 2 "const_int_operand" "") - (match_operand:SI 3 "const_int_operand" "")] - "" -{ - if (bfin_expand_movmem (operands[0], operands[1], operands[2], operands[3])) - DONE; - FAIL; -}) - -;; Conditional branch patterns -;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu - -(define_insn "compare_eq" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (eq:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKs3,aKs3")))] - "" - "cc =%1==%2;" - [(set_attr "type" "compare")]) - -(define_insn "compare_ne" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (ne:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKs3,aKs3")))] - "0" - "cc =%1!=%2;" - [(set_attr "type" "compare")]) - -(define_insn "compare_lt" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (lt:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKs3,aKs3")))] - "" - "cc =%1<%2;" - [(set_attr "type" "compare")]) - -(define_insn "compare_le" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (le:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKs3,aKs3")))] - "" - "cc =%1<=%2;" - [(set_attr "type" "compare")]) - -(define_insn "compare_leu" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (leu:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKu3,aKu3")))] - "" - "cc =%1<=%2 (iu);" - [(set_attr "type" "compare")]) - -(define_insn "compare_ltu" - [(set (match_operand:BI 0 "register_operand" "=C,C") - (ltu:BI (match_operand:SI 1 "register_operand" "d,a") - (match_operand:SI 2 "reg_or_const_int_operand" "dKu3,aKu3")))] - "" - "cc =%1<%2 (iu);" - [(set_attr "type" "compare")]) - -;; Same as above, but and CC with the overflow bit generated by the first -;; multiplication. -(define_insn "flag_mul_macv2hi_parts_acconly_andcc0" - [(set (match_operand:PDI 0 "register_operand" "=B,e,e") - (unspec:PDI [(vec_select:HI - (match_operand:V2HI 2 "register_operand" "d,d,d") - (parallel [(match_operand 4 "const01_operand" "P0P1,P0P1,P0P1")])) - (vec_select:HI - (match_operand:V2HI 3 "register_operand" "d,d,d") - (parallel [(match_operand 6 "const01_operand" "P0P1,P0P1,P0P1")])) - (match_operand 10 "const_int_operand" "PB,PA,PA")] - UNSPEC_MUL_WITH_FLAG)) - (set (match_operand:PDI 1 "register_operand" "=B,e,e") - (unspec:PDI [(vec_select:HI - (match_dup 2) - (parallel [(match_operand 5 "const01_operand" "P0P1,P0P1,P0P1")])) - (vec_select:HI - (match_dup 3) - (parallel [(match_operand 7 "const01_operand" "P0P1,P0P1,P0P1")])) - (match_operand:PDI 8 "register_operand" "1,1,1") - (match_operand 9 "const01_operand" "P0P1,P0P1,P0P1") - (match_operand 11 "const_int_operand" "PA,PB,PA")] - UNSPEC_MAC_WITH_FLAG)) - (set (reg:BI REG_CC) - (and:BI (reg:BI REG_CC) - (unspec:BI [(vec_select:HI (match_dup 2) (parallel [(match_dup 4)])) - (vec_select:HI (match_dup 3) (parallel [(match_dup 6)])) - (match_dup 10)] - UNSPEC_MUL_WITH_FLAG)))] - "MACFLAGS_MATCH_P (INTVAL (operands[10]), INTVAL (operands[11]))" -{ - rtx xops[6]; - const char *templates[] = { - "%0 = %h2 * %h3, %1 %b4 %h2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %h3, %1 %b4 %h2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %h3, %1 %b4 %d2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %h3, %1 %b4 %d2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %d3, %1 %b4 %h2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %d3, %1 %b4 %h2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %d3, %1 %b4 %d2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %d3, %1 %b4 %d2 * %h3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %h3, %1 %b4 %h2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %h3, %1 %b4 %h2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %h3, %1 %b4 %d2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %h3, %1 %b4 %d2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %d3, %1 %b4 %h2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %d3, %1 %b4 %h2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %h2 * %d3, %1 %b4 %d2 * %d3 %M5;\n\tCC &= %v0;", - "%0 = %d2 * %d3, %1 %b4 %d2 * %d3 %M5;\n\tCC &= %v0;" }; - int alt = (INTVAL (operands[4]) + (INTVAL (operands[5]) << 1) - + (INTVAL (operands[6]) << 2) + (INTVAL (operands[7]) << 3)); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = operands[2]; - xops[3] = operands[3]; - xops[4] = operands[9]; - xops[5] = which_alternative == 0 ? operands[10] : operands[11]; - output_asm_insn (templates[alt], xops); - return ""; -} - [(set_attr "type" "misc") - (set_attr "length" "6") - (set_attr "seq_insns" "multi")]) - -(define_expand "cbranchsi4" - [(set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_const_int_operand" "")]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" -{ - rtx bi_compare = bfin_gen_compare (operands[0], SImode); - emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode), - operands[3])); - DONE; -}) - -(define_insn "cbranchbi4" - [(set (pc) - (if_then_else - (match_operator 0 "bfin_bimode_comparison_operator" - [(match_operand:BI 1 "register_operand" "C") - (match_operand:BI 2 "immediate_operand" "P0")]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" -{ - asm_conditional_branch (insn, operands, 0, 0); - return ""; -} - [(set_attr "type" "brcc")]) - -;; Special cbranch patterns to deal with the speculative load problem - see -;; bfin_reorg for details. - -(define_insn "cbranch_predicted_taken" - [(set (pc) - (if_then_else - (match_operator 0 "bfin_bimode_comparison_operator" - [(match_operand:BI 1 "register_operand" "C") - (match_operand:BI 2 "immediate_operand" "P0")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (unspec [(const_int 0)] UNSPEC_CBRANCH_TAKEN)] - "" -{ - asm_conditional_branch (insn, operands, 0, 1); - return ""; -} - [(set_attr "type" "brcc")]) - -(define_insn "cbranch_with_nops" - [(set (pc) - (if_then_else - (match_operator 0 "bfin_bimode_comparison_operator" - [(match_operand:BI 1 "register_operand" "C") - (match_operand:BI 2 "immediate_operand" "P0")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (unspec [(match_operand 4 "immediate_operand" "")] UNSPEC_CBRANCH_NOPS)] - "reload_completed" -{ - asm_conditional_branch (insn, operands, INTVAL (operands[4]), 0); - return ""; -} - [(set_attr "type" "brcc") - (set_attr "length" "8")]) - -;; setcc insns. - -(define_expand "cstorebi4" - [(set (match_dup 4) - (match_operator:BI 1 "bfin_bimode_comparison_operator" - [(match_operand:BI 2 "register_operand" "") - (match_operand:BI 3 "reg_or_const_int_operand" "")])) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 4) (const_int 0)))] - "" -{ - /* It could be expanded as a movbisi instruction, but the portable - alternative produces better code. */ - if (GET_CODE (operands[1]) == NE) - FAIL; - - operands[4] = bfin_cc_rtx; -}) - -(define_expand "cstoresi4" - [(set (match_operand:SI 0 "register_operand") - (match_operator:SI 1 "ordered_comparison_operator" - [(match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "reg_or_const_int_operand" "")]))] - "" -{ - rtx bi_compare, test; - - if (!bfin_direct_comparison_operator (operands[1], SImode)) - { - if (!register_operand (operands[3], SImode) - || GET_CODE (operands[1]) == NE) - FAIL; - test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])), - SImode, operands[3], operands[2]); - } - else - test = operands[1]; - - bi_compare = bfin_gen_compare (test, SImode); - gcc_assert (GET_CODE (bi_compare) == NE); - emit_insn (gen_movbisi (operands[0], bfin_cc_rtx)); - DONE; -}) - -(define_insn "nop" - [(const_int 0)] - "" - "nop;") - -;; A nop which stays there when emitted. -(define_insn "forced_nop" - [(unspec [(const_int 0)] UNSPEC_NOP)] - "" - "nop;") - -(define_insn "mnop" - [(unspec [(const_int 0)] UNSPEC_32BIT)] - "" - "mnop%!" - [(set_attr "type" "dsp32")]) - -;;;;;;;;;;;;;;;;;;;; CC2dreg ;;;;;;;;;;;;;;;;;;;;;;;;; -(define_insn "movsibi" - [(set (match_operand:BI 0 "register_operand" "=C") - (ne:BI (match_operand:SI 1 "register_operand" "d") - (const_int 0)))] - "" - "CC = %1;" - [(set_attr "length" "2")]) - -(define_insn_and_split "movbisi" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_operand:BI 1 "register_operand" "C") - (const_int 0)))] - "" - "#" - "" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:BI 1 "register_operand" "")))] - "") - -(define_insn "notbi" - [(set (match_operand:BI 0 "register_operand" "=C") - (eq:BI (match_operand:BI 1 "register_operand" " 0") - (const_int 0)))] - "" - "%0 = ! %0;" /* NOT CC;" */ - [(set_attr "type" "compare")]) - -;; Vector and DSP insns - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") - (const_int 24)) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "d") - (const_int 8))))] - "" - "%0 = ALIGN8(%1, %2)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") - (const_int 16)) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "d") - (const_int 16))))] - "" - "%0 = ALIGN16(%1, %2)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") - (const_int 8)) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "d") - (const_int 24))))] - "" - "%0 = ALIGN24(%1, %2)%!" - [(set_attr "type" "dsp32")]) - -;; Prologue and epilogue. - -(define_expand "prologue" - [(const_int 1)] - "" - "bfin_expand_prologue (); DONE;") - -(define_expand "epilogue" - [(const_int 1)] - "" - "bfin_expand_epilogue (1, 0, 0); DONE;") - -(define_expand "sibcall_epilogue" - [(const_int 1)] - "" - "bfin_expand_epilogue (0, 0, 1); DONE;") - -(define_expand "eh_return" - [(use (match_operand:SI 0 "register_operand" ""))] - "" -{ - emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0])); - emit_jump_insn (gen_eh_return_internal ()); - emit_barrier (); - DONE; -}) - -(define_insn "eh_store_handler" - [(unspec_volatile [(match_operand:SI 1 "register_operand" "da")] - UNSPEC_VOLATILE_STORE_EH_HANDLER) - (clobber (match_operand:SI 0 "memory_operand" "=m"))] - "" - "%0 = %1%!" - [(set_attr "type" "mcst")]) - -(define_insn_and_split "eh_return_internal" - [(eh_return)] - "" - "#" - "epilogue_completed" - [(const_int 1)] - "bfin_expand_epilogue (1, 1, 0); DONE;") - -(define_insn "link" - [(set (mem:SI (plus:SI (reg:SI REG_SP) (const_int -4))) (reg:SI REG_RETS)) - (set (mem:SI (plus:SI (reg:SI REG_SP) (const_int -8))) (reg:SI REG_FP)) - (set (reg:SI REG_FP) - (plus:SI (reg:SI REG_SP) (const_int -8))) - (set (reg:SI REG_SP) - (plus:SI (reg:SI REG_SP) (match_operand:SI 0 "immediate_operand" "i")))] - "" - "LINK %Z0;" - [(set_attr "length" "4")]) - -(define_insn "unlink" - [(set (reg:SI REG_FP) (mem:SI (reg:SI REG_FP))) - (set (reg:SI REG_RETS) (mem:SI (plus:SI (reg:SI REG_FP) (const_int 4)))) - (set (reg:SI REG_SP) (plus:SI (reg:SI REG_FP) (const_int 8)))] - "" - "UNLINK;" - [(set_attr "length" "4")]) - -;; This pattern is slightly clumsy. The stack adjust must be the final SET in -;; the pattern, otherwise dwarf2out becomes very confused about which reg goes -;; where on the stack, since it goes through all elements of the parallel in -;; sequence. -(define_insn "push_multiple" - [(match_parallel 0 "push_multiple_operation" - [(unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_PUSH_MULTIPLE)])] - "" -{ - output_push_multiple (insn, operands); - return ""; -}) - -(define_insn "pop_multiple" - [(match_parallel 0 "pop_multiple_operation" - [(set (reg:SI REG_SP) - (plus:SI (reg:SI REG_SP) (match_operand:SI 1 "immediate_operand" "i")))])] - "" -{ - output_pop_multiple (insn, operands); - return ""; -}) - -(define_insn "return_internal" - [(return) - (use (match_operand 0 "register_operand" ""))] - "reload_completed" -{ - switch (REGNO (operands[0])) - { - case REG_RETX: - return "rtx;"; - case REG_RETN: - return "rtn;"; - case REG_RETI: - return "rti;"; - case REG_RETS: - return "rts;"; - } - gcc_unreachable (); -}) - -;; When used at a location where CC contains 1, causes a speculative load -;; that is later cancelled. This is used for certain workarounds in -;; interrupt handler prologues. -(define_insn "dummy_load" - [(unspec_volatile [(match_operand 0 "register_operand" "a") - (match_operand 1 "register_operand" "C")] - UNSPEC_VOLATILE_DUMMY)] - "" - "if cc jump 4;\n\tr7 = [%0];" - [(set_attr "type" "misc") - (set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -;; A placeholder insn inserted before the final scheduling pass. It is used -;; to improve scheduling of loads when workarounds for speculative loads are -;; needed, by not placing them in the first few cycles after a conditional -;; branch. -(define_insn "stall" - [(unspec_volatile [(match_operand 0 "const_int_operand" "P1P3")] - UNSPEC_VOLATILE_STALL)] - "" - "" - [(set_attr "type" "stall")]) - -(define_insn "csync" - [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)] - "" - "csync;" - [(set_attr "type" "sync")]) - -(define_insn "ssync" - [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_SSYNC)] - "" - "ssync;" - [(set_attr "type" "sync")]) - -(define_insn "trap" - [(trap_if (const_int 1) (const_int 3))] - "" - "excpt 3;" - [(set_attr "type" "misc") - (set_attr "length" "2")]) - -(define_insn "trapifcc" - [(trap_if (reg:BI REG_CC) (const_int 3))] - "" - "if !cc jump 4 (bp); excpt 3;" - [(set_attr "type" "misc") - (set_attr "length" "4") - (set_attr "seq_insns" "multi")]) - -;;; Vector instructions - -;; First, all sorts of move variants - -(define_insn "movhiv2hi_low" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (match_operand:HI 2 "register_operand" "d") - (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") - (parallel [(const_int 1)]))))] - "" - "%h0 = %h2 << 0%!" - [(set_attr "type" "dsp32shiftimm")]) - -(define_insn "movhiv2hi_high" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") - (parallel [(const_int 0)])) - (match_operand:HI 2 "register_operand" "d")))] - "" - "%d0 = %h2 << 0%!" - [(set_attr "type" "dsp32shiftimm")]) - -;; No earlyclobber on alternative two since our sequence ought to be safe. -;; The order of operands is intentional to match the VDSP builtin (high word -;; is passed first). -(define_insn_and_split "composev2hi" - [(set (match_operand:V2HI 0 "register_operand" "=d,d") - (vec_concat:V2HI (match_operand:HI 2 "register_operand" "0,d") - (match_operand:HI 1 "register_operand" "d,d")))] - "" - "@ - %d0 = %h1 << 0%! - #" - "reload_completed" - [(set (match_dup 0) - (vec_concat:V2HI - (vec_select:HI (match_dup 0) (parallel [(const_int 0)])) - (match_dup 1))) - (set (match_dup 0) - (vec_concat:V2HI - (match_dup 2) - (vec_select:HI (match_dup 0) (parallel [(const_int 1)]))))] - "" - [(set_attr "type" "dsp32shiftimm")]) - -; Like composev2hi, but operating on elements of V2HI vectors. -; Useful on its own, and as a combiner bridge for the multiply and -; mac patterns. -(define_insn "packv2hi" - [(set (match_operand:V2HI 0 "register_operand" "=d,d,d,d,d,d,d,d") - (vec_concat:V2HI (vec_select:HI - (match_operand:V2HI 1 "register_operand" "0,0,d,d,d,d,d,d") - (parallel [(match_operand 3 "const01_operand" "P0,P0,P0,P1,P0,P1,P0,P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d,d,0,0,d,d,d,d") - (parallel [(match_operand 4 "const01_operand" "P0,P1,P1,P1,P0,P0,P1,P1")]))))] - "" - "@ - %d0 = %h2 << 0%! - %d0 = %d2 << 0%! - %h0 = %h1 << 0%! - %h0 = %d1 << 0%! - %0 = PACK (%h2,%h1)%! - %0 = PACK (%h2,%d1)%! - %0 = PACK (%d2,%h1)%! - %0 = PACK (%d2,%d1)%!" - [(set_attr "type" "dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32,dsp32,dsp32,dsp32")]) - -(define_insn "movv2hi_hi" - [(set (match_operand:HI 0 "register_operand" "=d,d,d") - (vec_select:HI (match_operand:V2HI 1 "register_operand" "0,d,d") - (parallel [(match_operand 2 "const01_operand" "P0,P0,P1")])))] - "" - "@ - /* optimized out */ - %h0 = %h1 << 0%! - %h0 = %d1 << 0%!" - [(set_attr "type" "dsp32shiftimm")]) - -(define_expand "movv2hi_hi_low" - [(set (match_operand:HI 0 "register_operand" "") - (vec_select:HI (match_operand:V2HI 1 "register_operand" "") - (parallel [(const_int 0)])))] - "" - "") - -(define_expand "movv2hi_hi_high" - [(set (match_operand:HI 0 "register_operand" "") - (vec_select:HI (match_operand:V2HI 1 "register_operand" "") - (parallel [(const_int 1)])))] - "" - "") - -;; Unusual arithmetic operations on 16-bit registers. - -(define_code_iterator sp_or_sm [ss_plus ss_minus]) -(define_code_attr spm_string [(ss_plus "+") (ss_minus "-")]) -(define_code_attr spm_name [(ss_plus "add") (ss_minus "sub")]) - -(define_insn "ss<spm_name>hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (sp_or_sm:HI (match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d")))] - "" - "%h0 = %h1 <spm_string> %h2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ss<spm_name>hi3_parts" - [(set (match_operand:HI 0 "register_operand" "=d") - (sp_or_sm:HI (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")]))))] - "" -{ - const char *templates[] = { - "%h0 = %h1 <spm_string> %h2 (S)%!", - "%h0 = %d1 <spm_string> %h2 (S)%!", - "%h0 = %h1 <spm_string> %d2 (S)%!", - "%h0 = %d1 <spm_string> %d2 (S)%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "ss<spm_name>hi3_low_parts" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") - (parallel [(const_int 0)])) - (sp_or_sm:HI (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 3 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])))))] - "" -{ - const char *templates[] = { - "%h0 = %h2 <spm_string> %h3 (S)%!", - "%h0 = %d2 <spm_string> %h3 (S)%!", - "%h0 = %h2 <spm_string> %d3 (S)%!", - "%h0 = %d2 <spm_string> %d3 (S)%!" }; - int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "ss<spm_name>hi3_high_parts" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (sp_or_sm:HI (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 3 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")]))) - (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") - (parallel [(const_int 1)]))))] - "" -{ - const char *templates[] = { - "%d0 = %h2 <spm_string> %h3 (S)%!", - "%d0 = %d2 <spm_string> %h3 (S)%!", - "%d0 = %h2 <spm_string> %d3 (S)%!", - "%d0 = %d2 <spm_string> %d3 (S)%!" }; - int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -;; V2HI vector insns - -(define_insn "addv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (plus:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = %1 +|+ %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssaddv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (ss_plus:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = %1 +|+ %2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (minus:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = %1 -|- %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sssubv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (ss_minus:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = %1 -|- %2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "addsubv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 +|- %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subaddv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 -|+ %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssaddsubv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (ss_minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 +|- %2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sssubaddv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI - (ss_minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (ss_plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 -|+ %2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sublohiv2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))))] - "" - "%h0 = %d1 - %h2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subhilov2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)]))))] - "" - "%h0 = %h1 - %d2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sssublohiv2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))))] - "" - "%h0 = %d1 - %h2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sssubhilov2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)]))))] - "" - "%h0 = %h1 - %d2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "addlohiv2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))))] - "" - "%h0 = %d1 + %h2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "addhilov2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)]))))] - "" - "%h0 = %h1 + %d2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssaddlohiv2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))))] - "" - "%h0 = %d1 + %h2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssaddhilov2hi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)]))))] - "" - "%h0 = %h1 + %d2 (S)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "sminv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (smin:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = MIN (%1, %2) (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "smaxv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (smax:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%0 = MAX (%1, %2) (V)%!" - [(set_attr "type" "dsp32")]) - -;; Multiplications. - -;; The Blackfin allows a lot of different options, and we need many patterns to -;; cover most of the hardware's abilities. -;; There are a few simple patterns using MULT rtx codes, but most of them use -;; an unspec with a const_int operand that determines which flag to use in the -;; instruction. -;; There are variants for single and parallel multiplications. -;; There are variants which just use 16-bit lowparts as inputs, and variants -;; which allow the user to choose just which halves to use as input values. -;; There are variants which set D registers, variants which set accumulators, -;; variants which set both, some of them optionally using the accumulators as -;; inputs for multiply-accumulate operations. - -(define_insn "flag_mulhi" - [(set (match_operand:HI 0 "register_operand" "=d") - (unspec:HI [(match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d") - (match_operand 3 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" - "%h0 = %h1 * %h2 %M3%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_mulhi_parts" - [(set (match_operand:HI 0 "register_operand" "=d") - (unspec:HI [(vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (match_operand 5 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%h0 = %h1 * %h2 %M5%!", - "%h0 = %d1 * %h2 %M5%!", - "%h0 = %h1 * %d2 %M5%!", - "%h0 = %d1 * %d2 %M5%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "flag_mulhisi" - [(set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d") - (match_operand 3 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" - "%0 = %h1 * %h2 %M3%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_mulhisi_parts" - [(set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (match_operand 5 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%0 = %h1 * %h2 %M5%!", - "%0 = %d1 * %h2 %M5%!", - "%0 = %h1 * %d2 %M5%!", - "%0 = %d1 * %d2 %M5%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -;; Three alternatives here to cover all possible allocations: -;; 0. mac flag is usable only for accumulator 1 - use A1 and odd DREG -;; 1. mac flag is usable for accumulator 0 - use A0 and even DREG -;; 2. mac flag is usable in any accumulator - use A1 and odd DREG -;; Other patterns which don't have a DREG destination can collapse cases -;; 1 and 2 into one. -(define_insn "flag_machi" - [(set (match_operand:HI 0 "register_operand" "=W,D,W") - (unspec:HI [(match_operand:HI 2 "register_operand" "d,d,d") - (match_operand:HI 3 "register_operand" "d,d,d") - (match_operand 4 "register_operand" "1,1,1") - (match_operand 5 "const01_operand" "P0P1,P0P1,P0P1") - (match_operand 6 "const_int_operand" "PB,PA,PA")] - UNSPEC_MAC_WITH_FLAG)) - (set (match_operand:PDI 1 "register_operand" "=B,A,B") - (unspec:PDI [(match_dup 1) (match_dup 2) (match_dup 3) - (match_dup 4) (match_dup 5)] - UNSPEC_MAC_WITH_FLAG))] - "" - "%h0 = (%1 %b5 %h2 * %h3) %M6%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_machi_acconly" - [(set (match_operand:PDI 0 "register_operand" "=B,e") - (unspec:PDI [(match_operand:HI 1 "register_operand" "d,d") - (match_operand:HI 2 "register_operand" "d,d") - (match_operand 3 "register_operand" "0,0") - (match_operand 4 "const01_operand" "P0P1,P0P1") - (match_operand 5 "const_int_operand" "PB,PA")] - UNSPEC_MAC_WITH_FLAG))] - "" - "%0 %b4 %h1 * %h2 %M5%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_machi_parts_acconly" - [(set (match_operand:PDI 0 "register_operand" "=B,e") - (unspec:PDI [(vec_select:HI - (match_operand:V2HI 1 "register_operand" "d,d") - (parallel [(match_operand 3 "const01_operand" "P0P1,P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d,d") - (parallel [(match_operand 4 "const01_operand" "P0P1,P0P1")])) - (match_operand:PDI 5 "register_operand" "0,0") - (match_operand 6 "const01_operand" "P0P1,P0P1") - (match_operand 7 "const_int_operand" "PB,PA")] - UNSPEC_MAC_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%0 %b6 %h1 * %h2 %M7%!", - "%0 %b6 %d1 * %h2 %M7%!", - "%0 %b6 %h1 * %d2 %M7%!", - "%0 %b6 %d1 * %d2 %M7%!" - }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "flag_macinithi" - [(set (match_operand:HI 0 "register_operand" "=W,D,W") - (unspec:HI [(match_operand:HI 1 "register_operand" "d,d,d") - (match_operand:HI 2 "register_operand" "d,d,d") - (match_operand 3 "const_int_operand" "PB,PA,PA")] - UNSPEC_MAC_WITH_FLAG)) - (set (match_operand:PDI 4 "register_operand" "=B,A,B") - (unspec:PDI [(match_dup 1) (match_dup 2) (match_dup 3)] - UNSPEC_MAC_WITH_FLAG))] - "" - "%h0 = (%4 = %h1 * %h2) %M3%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_macinit1hi" - [(set (match_operand:PDI 0 "register_operand" "=B,e") - (unspec:PDI [(match_operand:HI 1 "register_operand" "d,d") - (match_operand:HI 2 "register_operand" "d,d") - (match_operand 3 "const_int_operand" "PB,PA")] - UNSPEC_MAC_WITH_FLAG))] - "" - "%0 = %h1 * %h2 %M3%!" - [(set_attr "type" "dsp32")]) - -(define_insn "mulv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (mult:V2HI (match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d")))] - "" - "%h0 = %h1 * %h2, %d0 = %d1 * %d2 (IS)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_mulv2hi" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d") - (match_operand:V2HI 2 "register_operand" "d") - (match_operand 3 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" - "%h0 = %h1 * %h2, %d0 = %d1 * %d2 %M3%!" - [(set_attr "type" "dsp32")]) - -(define_insn "flag_mulv2hi_parts" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (unspec:V2HI [(vec_concat:V2HI - (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_dup 1) - (parallel [(match_operand 4 "const01_operand" "P0P1")]))) - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (vec_select:HI (match_dup 2) - (parallel [(match_operand 6 "const01_operand" "P0P1")]))) - (match_operand 7 "const_int_operand" "n")] - UNSPEC_MUL_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%h0 = %h1 * %h2, %d0 = %h1 * %h2 %M7%!", - "%h0 = %d1 * %h2, %d0 = %h1 * %h2 %M7%!", - "%h0 = %h1 * %h2, %d0 = %d1 * %h2 %M7%!", - "%h0 = %d1 * %h2, %d0 = %d1 * %h2 %M7%!", - "%h0 = %h1 * %d2, %d0 = %h1 * %h2 %M7%!", - "%h0 = %d1 * %d2, %d0 = %h1 * %h2 %M7%!", - "%h0 = %h1 * %d2, %d0 = %d1 * %h2 %M7%!", - "%h0 = %d1 * %d2, %d0 = %d1 * %h2 %M7%!", - "%h0 = %h1 * %h2, %d0 = %h1 * %d2 %M7%!", - "%h0 = %d1 * %h2, %d0 = %h1 * %d2 %M7%!", - "%h0 = %h1 * %h2, %d0 = %d1 * %d2 %M7%!", - "%h0 = %d1 * %h2, %d0 = %d1 * %d2 %M7%!", - "%h0 = %h1 * %d2, %d0 = %h1 * %d2 %M7%!", - "%h0 = %d1 * %d2, %d0 = %h1 * %d2 %M7%!", - "%h0 = %h1 * %d2, %d0 = %d1 * %d2 %M7%!", - "%h0 = %d1 * %d2, %d0 = %d1 * %d2 %M7%!" }; - int alt = (INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2) + (INTVAL (operands[6]) << 3)); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -;; A slightly complicated pattern. -;; Operand 0 is the halfword output; operand 11 is the accumulator output -;; Halfword inputs are operands 1 and 2; operands 3, 4, 5 and 6 specify which -;; parts of these 2x16 bit registers to use. -;; Operand 7 is the accumulator input. -;; Operands 8/9 specify whether low/high parts are mac (0) or msu (1) -;; Operand 10 is the macflag to be used. -(define_insn "flag_macv2hi_parts" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (unspec:V2HI [(vec_concat:V2HI - (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_dup 1) - (parallel [(match_operand 4 "const01_operand" "P0P1")]))) - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (vec_select:HI (match_dup 2) - (parallel [(match_operand 6 "const01_operand" "P0P1")]))) - (match_operand:V2PDI 7 "register_operand" "e") - (match_operand 8 "const01_operand" "P0P1") - (match_operand 9 "const01_operand" "P0P1") - (match_operand 10 "const_int_operand" "n")] - UNSPEC_MAC_WITH_FLAG)) - (set (match_operand:V2PDI 11 "register_operand" "=e") - (unspec:V2PDI [(vec_concat:V2HI - (vec_select:HI (match_dup 1) (parallel [(match_dup 3)])) - (vec_select:HI (match_dup 1) (parallel [(match_dup 4)]))) - (vec_concat:V2HI - (vec_select:HI (match_dup 2) (parallel [(match_dup 5)])) - (vec_select:HI (match_dup 2) (parallel [(match_dup 5)]))) - (match_dup 7) (match_dup 8) (match_dup 9) (match_dup 10)] - UNSPEC_MAC_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%h0 = (A0 %b8 %h1 * %h2), %d0 = (A1 %b9 %h1 * %h2) %M10%!", - "%h0 = (A0 %b8 %d1 * %h2), %d0 = (A1 %b9 %h1 * %h2) %M10%!", - "%h0 = (A0 %b8 %h1 * %h2), %d0 = (A1 %b9 %d1 * %h2) %M10%!", - "%h0 = (A0 %b8 %d1 * %h2), %d0 = (A1 %b9 %d1 * %h2) %M10%!", - "%h0 = (A0 %b8 %h1 * %d2), %d0 = (A1 %b9 %h1 * %h2) %M10%!", - "%h0 = (A0 %b8 %d1 * %d2), %d0 = (A1 %b9 %h1 * %h2) %M10%!", - "%h0 = (A0 %b8 %h1 * %d2), %d0 = (A1 %b9 %d1 * %h2) %M10%!", - "%h0 = (A0 %b8 %d1 * %d2), %d0 = (A1 %b9 %d1 * %h2) %M10%!", - "%h0 = (A0 %b8 %h1 * %h2), %d0 = (A1 %b9 %h1 * %d2) %M10%!", - "%h0 = (A0 %b8 %d1 * %h2), %d0 = (A1 %b9 %h1 * %d2) %M10%!", - "%h0 = (A0 %b8 %h1 * %h2), %d0 = (A1 %b9 %d1 * %d2) %M10%!", - "%h0 = (A0 %b8 %d1 * %h2), %d0 = (A1 %b9 %d1 * %d2) %M10%!", - "%h0 = (A0 %b8 %h1 * %d2), %d0 = (A1 %b9 %h1 * %d2) %M10%!", - "%h0 = (A0 %b8 %d1 * %d2), %d0 = (A1 %b9 %h1 * %d2) %M10%!", - "%h0 = (A0 %b8 %h1 * %d2), %d0 = (A1 %b9 %d1 * %d2) %M10%!", - "%h0 = (A0 %b8 %d1 * %d2), %d0 = (A1 %b9 %d1 * %d2) %M10%!" }; - int alt = (INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2) + (INTVAL (operands[6]) << 3)); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "flag_macv2hi_parts_acconly" - [(set (match_operand:V2PDI 0 "register_operand" "=e") - (unspec:V2PDI [(vec_concat:V2HI - (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_dup 1) - (parallel [(match_operand 4 "const01_operand" "P0P1")]))) - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (vec_select:HI (match_dup 2) - (parallel [(match_operand 6 "const01_operand" "P0P1")]))) - (match_operand:V2PDI 7 "register_operand" "e") - (match_operand 8 "const01_operand" "P0P1") - (match_operand 9 "const01_operand" "P0P1") - (match_operand 10 "const_int_operand" "n")] - UNSPEC_MAC_WITH_FLAG))] - "" -{ - const char *templates[] = { - "A0 %b8 %h1 * %h2, A1 %b9 %h1 * %h2 %M10%!", - "A0 %b8 %d1 * %h2, A1 %b9 %h1 * %h2 %M10%!", - "A0 %b8 %h1 * %h2, A1 %b9 %d1 * %h2 %M10%!", - "A0 %b8 %d1 * %h2, A1 %b9 %d1 * %h2 %M10%!", - "A0 %b8 %h1 * %d2, A1 %b9 %h1 * %h2 %M10%!", - "A0 %b8 %d1 * %d2, A1 %b9 %h1 * %h2 %M10%!", - "A0 %b8 %h1 * %d2, A1 %b9 %d1 * %h2 %M10%!", - "A0 %b8 %d1 * %d2, A1 %b9 %d1 * %h2 %M10%!", - "A0 %b8 %h1 * %h2, A1 %b9 %h1 * %d2 %M10%!", - "A0 %b8 %d1 * %h2, A1 %b9 %h1 * %d2 %M10%!", - "A0 %b8 %h1 * %h2, A1 %b9 %d1 * %d2 %M10%!", - "A0 %b8 %d1 * %h2, A1 %b9 %d1 * %d2 %M10%!", - "A0 %b8 %h1 * %d2, A1 %b9 %h1 * %d2 %M10%!", - "A0 %b8 %d1 * %d2, A1 %b9 %h1 * %d2 %M10%!", - "A0 %b8 %h1 * %d2, A1 %b9 %d1 * %d2 %M10%!", - "A0 %b8 %d1 * %d2, A1 %b9 %d1 * %d2 %M10%!" }; - int alt = (INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2) + (INTVAL (operands[6]) << 3)); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -;; Same as above, but initializing the accumulators and therefore a couple fewer -;; necessary operands. -(define_insn "flag_macinitv2hi_parts" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (unspec:V2HI [(vec_concat:V2HI - (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_dup 1) - (parallel [(match_operand 4 "const01_operand" "P0P1")]))) - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (vec_select:HI (match_dup 2) - (parallel [(match_operand 6 "const01_operand" "P0P1")]))) - (match_operand 7 "const_int_operand" "n")] - UNSPEC_MAC_WITH_FLAG)) - (set (match_operand:V2PDI 8 "register_operand" "=e") - (unspec:V2PDI [(vec_concat:V2HI - (vec_select:HI (match_dup 1) (parallel [(match_dup 3)])) - (vec_select:HI (match_dup 1) (parallel [(match_dup 4)]))) - (vec_concat:V2HI - (vec_select:HI (match_dup 2) (parallel [(match_dup 5)])) - (vec_select:HI (match_dup 2) (parallel [(match_dup 5)]))) - (match_dup 7)] - UNSPEC_MAC_WITH_FLAG))] - "" -{ - const char *templates[] = { - "%h0 = (A0 = %h1 * %h2), %d0 = (A1 = %h1 * %h2) %M7%!", - "%h0 = (A0 = %d1 * %h2), %d0 = (A1 = %h1 * %h2) %M7%!", - "%h0 = (A0 = %h1 * %h2), %d0 = (A1 = %d1 * %h2) %M7%!", - "%h0 = (A0 = %d1 * %h2), %d0 = (A1 = %d1 * %h2) %M7%!", - "%h0 = (A0 = %h1 * %d2), %d0 = (A1 = %h1 * %h2) %M7%!", - "%h0 = (A0 = %d1 * %d2), %d0 = (A1 = %h1 * %h2) %M7%!", - "%h0 = (A0 = %h1 * %d2), %d0 = (A1 = %d1 * %h2) %M7%!", - "%h0 = (A0 = %d1 * %d2), %d0 = (A1 = %d1 * %h2) %M7%!", - "%h0 = (A0 = %h1 * %h2), %d0 = (A1 = %h1 * %d2) %M7%!", - "%h0 = (A0 = %d1 * %h2), %d0 = (A1 = %h1 * %d2) %M7%!", - "%h0 = (A0 = %h1 * %h2), %d0 = (A1 = %d1 * %d2) %M7%!", - "%h0 = (A0 = %d1 * %h2), %d0 = (A1 = %d1 * %d2) %M7%!", - "%h0 = (A0 = %h1 * %d2), %d0 = (A1 = %h1 * %d2) %M7%!", - "%h0 = (A0 = %d1 * %d2), %d0 = (A1 = %h1 * %d2) %M7%!", - "%h0 = (A0 = %h1 * %d2), %d0 = (A1 = %d1 * %d2) %M7%!", - "%h0 = (A0 = %d1 * %d2), %d0 = (A1 = %d1 * %d2) %M7%!" }; - int alt = (INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2) + (INTVAL (operands[6]) << 3)); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -(define_insn "flag_macinit1v2hi_parts" - [(set (match_operand:V2PDI 0 "register_operand" "=e") - (unspec:V2PDI [(vec_concat:V2HI - (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (vec_select:HI - (match_dup 1) - (parallel [(match_operand 4 "const01_operand" "P0P1")]))) - (vec_concat:V2HI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (vec_select:HI (match_dup 2) - (parallel [(match_operand 6 "const01_operand" "P0P1")]))) - (match_operand 7 "const_int_operand" "n")] - UNSPEC_MAC_WITH_FLAG))] - "" -{ - const char *templates[] = { - "A0 = %h1 * %h2, A1 = %h1 * %h2 %M7%!", - "A0 = %d1 * %h2, A1 = %h1 * %h2 %M7%!", - "A0 = %h1 * %h2, A1 = %d1 * %h2 %M7%!", - "A0 = %d1 * %h2, A1 = %d1 * %h2 %M7%!", - "A0 = %h1 * %d2, A1 = %h1 * %h2 %M7%!", - "A0 = %d1 * %d2, A1 = %h1 * %h2 %M7%!", - "A0 = %h1 * %d2, A1 = %d1 * %h2 %M7%!", - "A0 = %d1 * %d2, A1 = %d1 * %h2 %M7%!", - "A0 = %h1 * %h2, A1 = %h1 * %d2 %M7%!", - "A0 = %d1 * %h2, A1 = %h1 * %d2 %M7%!", - "A0 = %h1 * %h2, A1 = %d1 * %d2 %M7%!", - "A0 = %d1 * %h2, A1 = %d1 * %d2 %M7%!", - "A0 = %h1 * %d2, A1 = %h1 * %d2 %M7%!", - "A0 = %d1 * %d2, A1 = %h1 * %d2 %M7%!", - "A0 = %h1 * %d2, A1 = %d1 * %d2 %M7%!", - "A0 = %d1 * %d2, A1 = %d1 * %d2 %M7%!" }; - int alt = (INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2) + (INTVAL (operands[6]) << 3)); - return templates[alt]; -} - [(set_attr "type" "dsp32")]) - -;; A mixture of multiply and multiply-accumulate for when we only want to -;; initialize one part. -(define_insn "flag_mul_macv2hi_parts_acconly" - [(set (match_operand:PDI 0 "register_operand" "=B,e,e") - (unspec:PDI [(vec_select:HI - (match_operand:V2HI 2 "register_operand" "d,d,d") - (parallel [(match_operand 4 "const01_operand" "P0P1,P0P1,P0P1")])) - (vec_select:HI - (match_operand:V2HI 3 "register_operand" "d,d,d") - (parallel [(match_operand 6 "const01_operand" "P0P1,P0P1,P0P1")])) - (match_operand 10 "const_int_operand" "PB,PA,PA")] - UNSPEC_MUL_WITH_FLAG)) - (set (match_operand:PDI 1 "register_operand" "=B,e,e") - (unspec:PDI [(vec_select:HI - (match_dup 2) - (parallel [(match_operand 5 "const01_operand" "P0P1,P0P1,P0P1")])) - (vec_select:HI - (match_dup 3) - (parallel [(match_operand 7 "const01_operand" "P0P1,P0P1,P0P1")])) - (match_operand:PDI 8 "register_operand" "1,1,1") - (match_operand 9 "const01_operand" "P0P1,P0P1,P0P1") - (match_operand 11 "const_int_operand" "PA,PB,PA")] - UNSPEC_MAC_WITH_FLAG))] - "MACFLAGS_MATCH_P (INTVAL (operands[10]), INTVAL (operands[11]))" -{ - rtx xops[6]; - const char *templates[] = { - "%0 = %h2 * %h3, %1 %b4 %h2 * %h3 %M5%!", - "%0 = %d2 * %h3, %1 %b4 %h2 * %h3 %M5%!", - "%0 = %h2 * %h3, %1 %b4 %d2 * %h3 %M5%!", - "%0 = %d2 * %h3, %1 %b4 %d2 * %h3 %M5%!", - "%0 = %h2 * %d3, %1 %b4 %h2 * %h3 %M5%!", - "%0 = %d2 * %d3, %1 %b4 %h2 * %h3 %M5%!", - "%0 = %h2 * %d3, %1 %b4 %d2 * %h3 %M5%!", - "%0 = %d2 * %d3, %1 %b4 %d2 * %h3 %M5%!", - "%0 = %h2 * %h3, %1 %b4 %h2 * %d3 %M5%!", - "%0 = %d2 * %h3, %1 %b4 %h2 * %d3 %M5%!", - "%0 = %h2 * %h3, %1 %b4 %d2 * %d3 %M5%!", - "%0 = %d2 * %h3, %1 %b4 %d2 * %d3 %M5%!", - "%0 = %h2 * %d3, %1 %b4 %h2 * %d3 %M5%!", - "%0 = %d2 * %d3, %1 %b4 %h2 * %d3 %M5%!", - "%0 = %h2 * %d3, %1 %b4 %d2 * %d3 %M5%!", - "%0 = %d2 * %d3, %1 %b4 %d2 * %d3 %M5%!" }; - int alt = (INTVAL (operands[4]) + (INTVAL (operands[5]) << 1) - + (INTVAL (operands[6]) << 2) + (INTVAL (operands[7]) << 3)); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = operands[2]; - xops[3] = operands[3]; - xops[4] = operands[9]; - xops[5] = which_alternative == 0 ? operands[10] : operands[11]; - output_asm_insn (templates[alt], xops); - return ""; -} - [(set_attr "type" "dsp32")]) - - -(define_code_iterator s_or_u [sign_extend zero_extend]) -(define_code_attr su_optab [(sign_extend "mul") - (zero_extend "umul")]) -(define_code_attr su_modifier [(sign_extend "IS") - (zero_extend "FU")]) - -(define_insn "<su_optab>hisi_ll" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "%d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %h2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_lh" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_hl" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)])))))] - "" - "%0 = %d1 * %h2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_hh" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "%d") - (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -;; Additional variants for signed * unsigned multiply. - -(define_insn "usmulhisi_ull" - [(set (match_operand:SI 0 "register_operand" "=W") - (mult:SI (zero_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "%d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)])))))] - "" - "%0 = %h2 * %h1 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_ulh" - [(set (match_operand:SI 0 "register_operand" "=W") - (mult:SI (zero_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)])))))] - "" - "%0 = %d2 * %h1 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_uhl" - [(set (match_operand:SI 0 "register_operand" "=W") - (mult:SI (zero_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)])))))] - "" - "%0 = %h2 * %d1 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_uhh" - [(set (match_operand:SI 0 "register_operand" "=W") - (mult:SI (zero_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "%d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 1)])))))] - "" - "%0 = %d2 * %d1 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -;; Parallel versions of these operations. First, normal signed or unsigned -;; multiplies. - -(define_insn "<su_optab>hisi_ll_lh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %h2, %3 = %h1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_ll_hl" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %h2, %3 = %d1 * %h2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_ll_hh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %h2, %3 = %d1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_lh_hl" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %d2, %3 = %d1 * %h2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_lh_hh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %d2, %3 = %d1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "<su_optab>hisi_hl_hh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (s_or_u:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (s_or_u:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (s_or_u:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %h2, %3 = %d1 * %d2 (<su_modifier>)%!" - [(set_attr "type" "dsp32")]) - -;; Special signed * unsigned variants. - -(define_insn "usmulhisi_ll_lul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %h2, %3 = %h1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_ll_luh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %h2, %3 = %h1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_ll_hul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %h2, %3 = %d1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_ll_huh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %h2, %3 = %d1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_lh_lul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %d2, %3 = %h1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_lh_luh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %d2, %3 = %h1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_lh_hul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %h1 * %d2, %3 = %d1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_lh_huh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %h1 * %d2, %3 = %d1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hl_lul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %d1 * %h2, %3 = %h1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hl_luh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %h2, %3 = %h1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hl_hul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %d1 * %h2, %3 = %d1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hl_huh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 0)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %h2, %3 = %d1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hh_lul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %d1 * %d2, %3 = %h1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hh_luh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 0)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %d2, %3 = %h1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hh_hul" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 0)])))))] - "" - "%0 = %d1 * %d2, %3 = %d1 * %h2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "usmulhisi_hh_huh" - [(set (match_operand:SI 0 "register_operand" "=q0,q2,q4,q6") - (mult:SI (sign_extend:SI - (vec_select:HI (match_operand:V2HI 1 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))) - (sign_extend:SI - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d,d,d,d") - (parallel [(const_int 1)]))))) - (set (match_operand:SI 3 "register_operand" "=q1,q3,q5,q7") - (mult:SI (sign_extend:SI - (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))) - (zero_extend:SI - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %d1 * %d2, %3 = %d1 * %d2 (IS,M)%!" - [(set_attr "type" "dsp32")]) - -;; Vector neg/abs. - -(define_insn "ssnegv2hi2" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (ss_neg:V2HI (match_operand:V2HI 1 "register_operand" "d")))] - "" - "%0 = - %1 (V)%!" - [(set_attr "type" "dsp32")]) - -(define_insn "ssabsv2hi2" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (ss_abs:V2HI (match_operand:V2HI 1 "register_operand" "d")))] - "" - "%0 = ABS %1 (V)%!" - [(set_attr "type" "dsp32")]) - -;; Shifts. - -(define_insn "ssashiftv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d,d,d") - (if_then_else:V2HI - (lt (match_operand:HI 2 "vec_shift_operand" "d,Ku4,Ks4") (const_int 0)) - (ashiftrt:V2HI (match_operand:V2HI 1 "register_operand" "d,d,d") - (match_dup 2)) - (ss_ashift:V2HI (match_dup 1) (match_dup 2))))] - "" - "@ - %0 = ASHIFT %1 BY %h2 (V, S)%! - %0 = %1 << %2 (V,S)%! - %0 = %1 >>> %N2 (V,S)%!" - [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) - -(define_insn "ssashifthi3" - [(set (match_operand:HI 0 "register_operand" "=d,d,d") - (if_then_else:HI - (lt (match_operand:HI 2 "vec_shift_operand" "d,Ku4,Ks4") (const_int 0)) - (ashiftrt:HI (match_operand:HI 1 "register_operand" "d,d,d") - (match_dup 2)) - (ss_ashift:HI (match_dup 1) (match_dup 2))))] - "" - "@ - %0 = ASHIFT %1 BY %h2 (V, S)%! - %0 = %1 << %2 (V,S)%! - %0 = %1 >>> %N2 (V,S)%!" - [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) - -(define_insn "ssashiftsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (if_then_else:SI - (lt (match_operand:HI 2 "reg_or_const_int_operand" "d,Ku5,Ks5") (const_int 0)) - (ashiftrt:SI (match_operand:HI 1 "register_operand" "d,d,d") - (match_dup 2)) - (ss_ashift:SI (match_dup 1) (match_dup 2))))] - "" - "@ - %0 = ASHIFT %1 BY %h2 (S)%! - %0 = %1 << %2 (S)%! - %0 = %1 >>> %N2 (S)%!" - [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) - -(define_insn "lshiftv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d,d,d") - (if_then_else:V2HI - (lt (match_operand:HI 2 "vec_shift_operand" "d,Ku4,Ks4") (const_int 0)) - (lshiftrt:V2HI (match_operand:V2HI 1 "register_operand" "d,d,d") - (match_dup 2)) - (ashift:V2HI (match_dup 1) (match_dup 2))))] - "" - "@ - %0 = LSHIFT %1 BY %h2 (V)%! - %0 = %1 << %2 (V)%! - %0 = %1 >> %N2 (V)%!" - [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) - -(define_insn "lshifthi3" - [(set (match_operand:HI 0 "register_operand" "=d,d,d") - (if_then_else:HI - (lt (match_operand:HI 2 "vec_shift_operand" "d,Ku4,Ks4") (const_int 0)) - (lshiftrt:HI (match_operand:HI 1 "register_operand" "d,d,d") - (match_dup 2)) - (ashift:HI (match_dup 1) (match_dup 2))))] - "" - "@ - %0 = LSHIFT %1 BY %h2 (V)%! - %0 = %1 << %2 (V)%! - %0 = %1 >> %N2 (V)%!" - [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) - -;; Load without alignment exception (masking off low bits) - -(define_insn "loadbytes" - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (and:SI (match_operand:SI 1 "register_operand" "b") - (const_int -4))))] - "" - "DISALGNEXCPT || %0 = [%1];" - [(set_attr "type" "mcld") - (set_attr "length" "8")]) - -(include "sync.md") diff --git a/gcc-4.7/gcc/config/bfin/bfin.opt b/gcc-4.7/gcc/config/bfin/bfin.opt deleted file mode 100644 index 15aebf3fa..000000000 --- a/gcc-4.7/gcc/config/bfin/bfin.opt +++ /dev/null @@ -1,118 +0,0 @@ -; Options for the Blackfin port of the compiler -; -; Copyright (C) 2005, 2007, 2008, 2011 Free Software Foundation, Inc. -; -; This file is part of GCC. -; -; GCC is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License as published by the Free -; Software Foundation; either version 3, or (at your option) any later -; version. -; -; GCC is distributed in the hope that it will be useful, but WITHOUT -; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -; License for more details. -; -; You should have received a copy of the GNU General Public License -; along with GCC; see the file COPYING3. If not see -; <http://www.gnu.org/licenses/>. - -HeaderInclude -config/bfin/bfin-opts.h - -; Value of -mcpu=. -Variable -bfin_cpu_t bfin_cpu_type = BFIN_CPU_UNKNOWN - -; -msi-revision support. There are three special values: -; -1 -msi-revision=none. -; 0xffff -msi-revision=any. -Variable -int bfin_si_revision - -; The workarounds enabled. -Variable -unsigned int bfin_workarounds = 0 - -msim -Target RejectNegative -Use simulator runtime - -mcpu= -Target RejectNegative Joined -Specify the name of the target CPU - -momit-leaf-frame-pointer -Target Report Mask(OMIT_LEAF_FRAME_POINTER) -Omit frame pointer for leaf functions - -mlow64k -Target Report Mask(LOW_64K) -Program is entirely located in low 64k of memory - -mcsync-anomaly -Target Report Var(bfin_csync_anomaly) Init(-1) -Work around a hardware anomaly by adding a number of NOPs before a -CSYNC or SSYNC instruction. - -mspecld-anomaly -Target Report Var(bfin_specld_anomaly) Init(-1) -Avoid speculative loads to work around a hardware anomaly. - -mid-shared-library -Target Report Mask(ID_SHARED_LIBRARY) -Enabled ID based shared library - -mleaf-id-shared-library -Target Report Mask(LEAF_ID_SHARED_LIBRARY) -Generate code that won't be linked against any other ID shared libraries, -but may be used as a shared library. - -mshared-library-id= -Target RejectNegative Joined UInteger Var(bfin_library_id) -ID of shared library to build - -msep-data -Target Report Mask(SEP_DATA) -Enable separate data segment - -mlong-calls -Target Report Mask(LONG_CALLS) -Avoid generating pc-relative calls; use indirection - -mfast-fp -Target Report Mask(FAST_FP) -Link with the fast floating-point library - -mfdpic -Target Report Mask(FDPIC) -Enable Function Descriptor PIC mode - -minline-plt -Target Report Mask(INLINE_PLT) -Enable inlining of PLT in function calls - -mstack-check-l1 -Target Report Mask(STACK_CHECK_L1) -Do stack checking using bounds in L1 scratch memory - -mmulticore -Target Report Mask(MULTICORE) -Enable multicore support - -mcorea -Target Report Mask(COREA) -Build for Core A - -mcoreb -Target Report Mask(COREB) -Build for Core B - -msdram -Target Report Mask(SDRAM) -Build for SDRAM - -micplb -Target Report Mask(ICPLB) -Assume ICPLBs are enabled at runtime. diff --git a/gcc-4.7/gcc/config/bfin/constraints.md b/gcc-4.7/gcc/config/bfin/constraints.md deleted file mode 100644 index fa9dcf143..000000000 --- a/gcc-4.7/gcc/config/bfin/constraints.md +++ /dev/null @@ -1,225 +0,0 @@ -;; Constraint definitions for Blackfin -;; Copyright (C) 2008 Free Software Foundation, Inc. -;; Contributed by Analog Devices - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published -;; by the Free Software Foundation; either version 3, or (at your -;; option) any later version. - -;; GCC is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -(define_register_constraint "a" "PREGS" - "A Pn register.") - -(define_register_constraint "d" "DREGS" - "A Rn register.") - -(define_register_constraint "z" "PREGS_CLOBBERED" - "A call clobbered Pn register.") - -(define_register_constraint "D" "EVEN_DREGS" - "An even-numbered Rn register.") - -(define_register_constraint "W" "ODD_DREGS" - "An odd-numbered Rn register.") - -(define_register_constraint "e" "AREGS" - "An accumulator register.") - -(define_register_constraint "A" "EVEN_AREGS" - "An even-numbered accumulator; A0.") - -(define_register_constraint "B" "ODD_AREGS" - "An odd-numbered accumulator; A1.") - -(define_register_constraint "b" "IREGS" - "An I register.") - -(define_register_constraint "v" "BREGS" - "A B register.") - -(define_register_constraint "f" "MREGS" - "An M register.") - -(define_register_constraint "c" "CIRCREGS" - "A register used for circular buffering, i.e. I, B, or L registers.") - -(define_register_constraint "C" "CCREGS" - "The CC register.") - -(define_register_constraint "t" "LT_REGS" - "LT0 or LT1.") - -(define_register_constraint "u" "LB_REGS" - "LB0 or LB1.") - -(define_register_constraint "k" "LC_REGS" - "LC0 or LC1.") - -(define_register_constraint "x" "MOST_REGS" - "Any R, P, B, M, I or L register.") - -(define_register_constraint "y" "PROLOGUE_REGS" - "Additional registers typically used only in prologues and epilogues: - RETS, RETN, RETI, RETX, RETE, ASTAT, SEQSTAT and USP.") - -(define_register_constraint "w" "NON_A_CC_REGS" - "Any register except accumulators or CC.") - -(define_register_constraint "Z" "FDPIC_REGS" - "@internal The FD-PIC GOT pointer; P3.") - -(define_register_constraint "Y" "FDPIC_FPTR_REGS" - "@internal The FD-PIC function pointer register; P1.") - -(define_register_constraint "q0" "D0REGS" - "The register R0.") - -(define_register_constraint "q1" "D1REGS" - "The register R1.") - -(define_register_constraint "q2" "D2REGS" - "The register R2.") - -(define_register_constraint "q3" "D3REGS" - "The register R3.") - -(define_register_constraint "q4" "D4REGS" - "The register R4.") - -(define_register_constraint "q5" "D5REGS" - "The register R5.") - -(define_register_constraint "q6" "D6REGS" - "The register R6.") - -(define_register_constraint "q7" "D7REGS" - "The register R7.") - -(define_register_constraint "qA" "P0REGS" - "The register P0.") - -;; Constant constraints. - -(define_constraint "J" - "A constant value of the form 2**N, where N 5-bit wide." - (and (match_code "const_int") - (match_test "log2constp (ival)"))) - -(define_constraint "Ks3" - "A signed 3 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -4 && ival <= 3"))) - -(define_constraint "Ku3" - "An unsigned 3 bit immediate." - (and (match_code "const_int") - (match_test "ival >= 0 && ival <= 7"))) - -(define_constraint "Ks4" - "A signed 4 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -8 && ival <= 7"))) - -(define_constraint "Ku4" - "An unsigned 4 bit immediate." - (and (match_code "const_int") - (match_test "ival >= 0 && ival <= 15"))) - -(define_constraint "Ks5" - "A signed 5 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -16 && ival <= 15"))) - -(define_constraint "Ku5" - "An unsigned 5 bit immediate." - (and (match_code "const_int") - (match_test "ival >= 0 && ival <= 31"))) - -(define_constraint "Ks7" - "A signed 7 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -64 && ival <= 63"))) - -(define_constraint "KN7" - "A constant that when negated is a signed 7 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -63 && ival <= 64"))) - -(define_constraint "Ksh" - "A signed 16 bit immediate." - (and (match_code "const_int") - (match_test "ival >= -32768 && ival <= 32767"))) - -(define_constraint "Kuh" - "An unsigned 16 bit immediate." - (and (match_code "const_int") - (match_test "ival >= 0 && ival <= 65535"))) - -(define_constraint "L" - "A constant value of the form ~(2**N)." - (and (match_code "const_int") - (match_test "log2constp (~ival)"))) - -(define_constraint "M1" - "An integer with the value 255." - (and (match_code "const_int") - (match_test "ival == 255"))) - -(define_constraint "M2" - "An integer with the value 65535." - (and (match_code "const_int") - (match_test "ival == 65535"))) - -(define_constraint "P0" - "An integer with the value 0." - (and (match_code "const_int") - (match_test "ival == 0"))) - -(define_constraint "P1" - "An integer with the value 1." - (and (match_code "const_int") - (match_test "ival == 1"))) - -(define_constraint "P2" - "An integer with the value 2." - (and (match_code "const_int") - (match_test "ival == 2"))) - -(define_constraint "P3" - "An integer with the value 3." - (and (match_code "const_int") - (match_test "ival == 3"))) - -(define_constraint "P4" - "An integer with the value 4." - (and (match_code "const_int") - (match_test "ival == 4"))) - -(define_constraint "PA" - "An integer constant describing any macflag except variants involving M." - (and (match_code "const_int") - (match_test "ival != MACFLAG_M && ival != MACFLAG_IS_M"))) - -(define_constraint "PB" - "An integer constant describing any macflag involving M." - (and (match_code "const_int") - (match_test "ival == MACFLAG_M || ival == MACFLAG_IS_M"))) - - -;; Extra constraints - -(define_constraint "Q" - "A SYMBOL_REF." - (match_code "symbol_ref")) - diff --git a/gcc-4.7/gcc/config/bfin/elf.h b/gcc-4.7/gcc/config/bfin/elf.h deleted file mode 100644 index 14e209aa4..000000000 --- a/gcc-4.7/gcc/config/bfin/elf.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "\ -%{msim:%{!shared:crt0%O%s}} \ -%{!msim:%{!mcpu=bf561*:%{!msdram:basiccrt%O%s} %{msdram:basiccrts%O%s};: \ - %{!msdram:basiccrt561%O%s} %{msdram:basiccrt561s%O%s}} \ - %{mcpu=bf561*:%{mmulticore:%{!mcorea:%{!mcoreb:basiccrt561b%O%s}}}}} \ -crti%O%s crtbegin%O%s crtlibid%O%s" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend%O%s crtn%O%s" - -#undef LIB_SPEC -#define LIB_SPEC "--start-group -lc %{msim:-lsim}%{!msim:-lnosys} --end-group \ -%{!T*:%{!msim:%{!msdram: \ - %{mcpu=bf512*:-T bf512.ld%s}%{mcpu=bf514*:-T bf514.ld%s} \ - %{mcpu=bf516*:-T bf516.ld%s}%{mcpu=bf518*:-T bf518.ld%s} \ - %{mcpu=bf522*:-T bf522.ld%s}%{mcpu=bf523*:-T bf523.ld%s} \ - %{mcpu=bf524*:-T bf524.ld%s}%{mcpu=bf525*:-T bf525.ld%s} \ - %{mcpu=bf526*:-T bf526.ld%s}%{mcpu=bf527*:-T bf527.ld%s} \ - %{mcpu=bf531*:-T bf531.ld%s}%{mcpu=bf532*:-T bf532.ld%s} \ - %{mcpu=bf533*:-T bf533.ld%s}%{mcpu=bf534*:-T bf534.ld%s} \ - %{mcpu=bf536*:-T bf536.ld%s}%{mcpu=bf537*:-T bf537.ld%s} \ - %{mcpu=bf538*:-T bf538.ld%s}%{mcpu=bf539*:-T bf539.ld%s} \ - %{mcpu=bf542*:-T bf542.ld%s}%{mcpu=bf544*:-T bf544.ld%s} \ - %{mcpu=bf547*:-T bf547.ld%s}%{mcpu=bf548*:-T bf548.ld%s} \ - %{mcpu=bf549*:-T bf549.ld%s} \ - %{mcpu=bf561*:%{!mmulticore:-T bf561.ld%s} \ - %{mmulticore:%{mcorea:-T bf561a.ld%s}} \ - %{mmulticore:%{mcoreb:-T bf561b.ld%s}} \ - %{mmulticore:%{!mcorea:%{!mcoreb:-T bf561m.ld%s}}}} \ - %{mcpu=bf592*:-T bf592.ld%s} \ - %{!mcpu=*:%eno processor type specified for linking} \ - %{!mcpu=bf561*:-T bfin-common-sc.ld%s} \ - %{mcpu=bf561*:%{!mmulticore:-T bfin-common-sc.ld%s} \ - %{mmulticore:-T bfin-common-mc.ld%s}}}}}" - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" - -#ifdef __BFIN_FDPIC__ -#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ -asm (SECTION_OP); \ -asm ("P3 = [SP + 20];\n\tcall " USER_LABEL_PREFIX #FUNC ";"); \ -asm (TEXT_SECTION_ASM_OP); -#endif - -#undef SUBTARGET_DRIVER_SELF_SPECS -#define SUBTARGET_DRIVER_SELF_SPECS \ - "%{mfdpic:-msim} %{mid-shared-library:-msim}" - -#define NO_IMPLICIT_EXTERN_C diff --git a/gcc-4.7/gcc/config/bfin/linux.h b/gcc-4.7/gcc/config/bfin/linux.h deleted file mode 100644 index f91cf17f1..000000000 --- a/gcc-4.7/gcc/config/bfin/linux.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -#undef SUBTARGET_DRIVER_SELF_SPECS -#define SUBTARGET_DRIVER_SELF_SPECS \ - "%{!mno-fdpic:-mfdpic} -micplb", - -#undef TARGET_OS_CPP_BUILTINS -#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS() - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} crtreloc.o%s \ - crti.o%s %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}" - -#undef LINK_GCC_C_SEQUENCE_SPEC -#define LINK_GCC_C_SEQUENCE_SPEC \ - "%{static:--start-group} %{mfast-fp:-lbffastfp} %G %L %{static:--end-group} \ - %{!static:%{mfast-fp:-lbffastfp} %G}" - -#undef LINK_SPEC -#define LINK_SPEC "\ - %{mfdpic: -m elf32bfinfd -z text} %{shared} %{pie} \ - %{static:-dn -Bstatic} \ - %{shared:-G -Bdynamic} \ - %{!shared: %{!static: \ - %{rdynamic:-export-dynamic} \ - -dynamic-linker /lib/ld-uClibc.so.0} \ - %{static}} -init __init -fini __fini" - -#undef TARGET_SUPPORTS_SYNC_CALLS -#define TARGET_SUPPORTS_SYNC_CALLS 1 diff --git a/gcc-4.7/gcc/config/bfin/predicates.md b/gcc-4.7/gcc/config/bfin/predicates.md deleted file mode 100644 index 84bf59195..000000000 --- a/gcc-4.7/gcc/config/bfin/predicates.md +++ /dev/null @@ -1,241 +0,0 @@ -;; Predicate definitions for the Blackfin. -;; Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -;; Contributed by Analog Devices. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. -;; -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Return nonzero iff OP is one of the integer constants 1 or 2. -(define_predicate "pos_scale_operand" - (and (match_code "const_int") - (match_test "INTVAL (op) == 1 || INTVAL (op) == 2"))) - -;; Return nonzero iff OP is one of the integer constants 2 or 4. -(define_predicate "scale_by_operand" - (and (match_code "const_int") - (match_test "INTVAL (op) == 2 || INTVAL (op) == 4"))) - -;; Return nonzero if OP is a constant that consists of two parts; lower -;; bits all zero and upper bits all ones. In this case, we can perform -;; an AND operation with a sequence of two shifts. Don't return nonzero -;; if the constant would be cheap to load. -(define_predicate "highbits_operand" - (and (match_code "const_int") - (match_test "log2constp (-INTVAL (op)) && !satisfies_constraint_Ks7 (op)"))) - -;; Return nonzero if OP is suitable as a right-hand side operand for an -;; andsi3 operation. -(define_predicate "rhs_andsi3_operand" - (ior (match_operand 0 "register_operand") - (and (match_code "const_int") - (match_test "log2constp (~INTVAL (op)) || INTVAL (op) == 255 || INTVAL (op) == 65535")))) - -;; Return nonzero if OP is a register or a constant with exactly one bit -;; set. -(define_predicate "regorlog2_operand" - (ior (match_operand 0 "register_operand") - (and (match_code "const_int") - (match_test "log2constp (INTVAL (op))")))) - -;; Return nonzero if OP is a register or an integer constant. -(define_predicate "reg_or_const_int_operand" - (ior (match_operand 0 "register_operand") - (match_code "const_int"))) - -(define_predicate "const01_operand" - (and (match_code "const_int") - (match_test "op == const0_rtx || op == const1_rtx"))) - -(define_predicate "const1_operand" - (and (match_code "const_int") - (match_test "op == const1_rtx"))) - -(define_predicate "const3_operand" - (and (match_code "const_int") - (match_test "INTVAL (op) == 3"))) - -(define_predicate "vec_shift_operand" - (ior (and (match_code "const_int") - (match_test "INTVAL (op) >= -16 && INTVAL (op) < 15")) - (match_operand 0 "register_operand"))) - -;; Like register_operand, but make sure that hard regs have a valid mode. -(define_predicate "valid_reg_operand" - (match_operand 0 "register_operand") -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (REGNO (op) < FIRST_PSEUDO_REGISTER) - return HARD_REGNO_MODE_OK (REGNO (op), mode); - return 1; -}) - -;; Return nonzero if OP is a D register. -(define_predicate "d_register_operand" - (and (match_code "reg") - (match_test "D_REGNO_P (REGNO (op))"))) - -(define_predicate "p_register_operand" - (and (match_code "reg") - (match_test "P_REGNO_P (REGNO (op))"))) - -(define_predicate "dp_register_operand" - (and (match_code "reg") - (match_test "D_REGNO_P (REGNO (op)) || P_REGNO_P (REGNO (op))"))) - -;; Return nonzero if OP is a LC register. -(define_predicate "lc_register_operand" - (and (match_code "reg") - (match_test "REGNO (op) == REG_LC0 || REGNO (op) == REG_LC1"))) - -;; Return nonzero if OP is a LT register. -(define_predicate "lt_register_operand" - (and (match_code "reg") - (match_test "REGNO (op) == REG_LT0 || REGNO (op) == REG_LT1"))) - -;; Return nonzero if OP is a LB register. -(define_predicate "lb_register_operand" - (and (match_code "reg") - (match_test "REGNO (op) == REG_LB0 || REGNO (op) == REG_LB1"))) - -;; Return nonzero if OP is a register or a 7-bit signed constant. -(define_predicate "reg_or_7bit_operand" - (ior (match_operand 0 "register_operand") - (and (match_code "const_int") - (match_test "satisfies_constraint_Ks7 (op)")))) - -;; Return nonzero if OP is a register other than DREG and PREG. -(define_predicate "nondp_register_operand" - (match_operand 0 "register_operand") -{ - unsigned int regno; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - regno = REGNO (op); - return (regno >= FIRST_PSEUDO_REGISTER || !DP_REGNO_P (regno)); -}) - -;; Return nonzero if OP is a register other than DREG and PREG, or MEM. -(define_predicate "nondp_reg_or_memory_operand" - (ior (match_operand 0 "nondp_register_operand") - (match_operand 0 "memory_operand"))) - -;; Return nonzero if OP is a register or, when negated, a 7-bit signed -;; constant. -(define_predicate "reg_or_neg7bit_operand" - (ior (match_operand 0 "register_operand") - (and (match_code "const_int") - (match_test "satisfies_constraint_KN7 (op)")))) - -;; Used for secondary reloads, this function returns 1 if OP is of the -;; form (plus (fp) (const_int)). -(define_predicate "fp_plus_const_operand" - (match_code "plus") -{ - rtx op1, op2; - - op1 = XEXP (op, 0); - op2 = XEXP (op, 1); - return (REG_P (op1) - && (REGNO (op1) == FRAME_POINTER_REGNUM - || REGNO (op1) == STACK_POINTER_REGNUM) - && GET_CODE (op2) == CONST_INT); -}) - -;; Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref, -;; possibly with an offset. -(define_predicate "symbolic_operand" - (ior (match_code "symbol_ref,label_ref") - (and (match_code "const") - (match_test "GET_CODE (XEXP (op,0)) == PLUS - && (GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF - || GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF) - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT")))) - -;; Returns 1 if OP is a plain constant or matched by symbolic_operand. -(define_predicate "symbolic_or_const_operand" - (ior (match_code "const_int,const_double") - (match_operand 0 "symbolic_operand"))) - -;; Returns 1 if OP is a SYMBOL_REF. -(define_predicate "symbol_ref_operand" - (match_code "symbol_ref")) - -;; True for any non-virtual or eliminable register. Used in places where -;; instantiation of such a register may cause the pattern to not be recognized. -(define_predicate "register_no_elim_operand" - (match_operand 0 "register_operand") -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return !(op == arg_pointer_rtx - || op == frame_pointer_rtx - || (REGNO (op) >= FIRST_PSEUDO_REGISTER - && REGNO (op) <= LAST_VIRTUAL_REGISTER)); -}) - -;; Test for an operator valid in a BImode conditional branch -(define_predicate "bfin_bimode_comparison_operator" - (match_code "eq,ne")) - -;; Test for an operator whose result is accessible with movbisi. -(define_predicate "bfin_direct_comparison_operator" - (match_code "eq,lt,le,leu,ltu")) - -;; The following three are used to compute the addrtype attribute. They return -;; true if passed a memory address usable for a 16-bit load or store using a -;; P or I register, respectively. If neither matches, we know we have a -;; 32-bit instruction. -;; We subdivide the P case into normal P registers, and SP/FP. We can assume -;; that speculative loads through SP and FP are no problem, so this has -;; an effect on the anomaly workaround code. - -(define_predicate "mem_p_address_operand" - (match_code "mem") -{ - if (effective_address_32bit_p (op, mode)) - return 0; - op = XEXP (op, 0); - if (GET_CODE (op) == PLUS || GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC) - op = XEXP (op, 0); - gcc_assert (REG_P (op)); - return PREG_P (op) && op != stack_pointer_rtx && op != frame_pointer_rtx; -}) - -(define_predicate "mem_spfp_address_operand" - (match_code "mem") -{ - if (effective_address_32bit_p (op, mode)) - return 0; - op = XEXP (op, 0); - if (GET_CODE (op) == PLUS || GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC) - op = XEXP (op, 0); - gcc_assert (REG_P (op)); - return op == stack_pointer_rtx || op == frame_pointer_rtx; -}) - -(define_predicate "mem_i_address_operand" - (match_code "mem") -{ - if (effective_address_32bit_p (op, mode)) - return 0; - op = XEXP (op, 0); - if (GET_CODE (op) == PLUS || GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC) - op = XEXP (op, 0); - gcc_assert (REG_P (op)); - return IREG_P (op); -}) diff --git a/gcc-4.7/gcc/config/bfin/print-sysroot-suffix.sh b/gcc-4.7/gcc/config/bfin/print-sysroot-suffix.sh deleted file mode 100644 index c33ff47c3..000000000 --- a/gcc-4.7/gcc/config/bfin/print-sysroot-suffix.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -# Copyright (C) 2007 Free Software Foundation, Inc. -# This file is part of GCC. - -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. - -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -# This script takes the following arguments: -# -# - the target sysroot -# - the value of $(MULTILIB_MATCHES) -# - the value of $(MULTILIB_OPTIONS) -# -# It uses these arguments to construct a definition of SYSROOT_SUFFIX_SPEC, -# which it prints to the standard output. For each multilib directory FOO, -# the script checks whether $sysroot has a subdirectory FOO, and if so will -# use /FOO for all compatible command-line options. It will not add a -# suffix for /FOO's options otherwise. These suffixes are concatenated, -# with one subspec for each space-separated entry in $(MULTILIB_OPTIONS). -set -e -sysroot=$1 -matches=$2 -options=$3 - -# For each multilib option OPT, add to $substs a sed command of the -# form "-e 's/OPT/OPT/'". -substs="" -for option in `echo "$options" | tr '/' ' '` -do - substs="$substs -e 's/$option/$option/g'" -done - -# For each ALIAS=CANONICAL entry in $MULTILIB_MATCHES, look for sed -# arguments in $substs of the form "-e 's/CANONICAL/.../'". Replace -# such entries with "-e 's/CANONICAL/ALIAS|.../'". Both the ALIAS and -# CANONICAL parts of $MULTILIB_MATCHES use '?' to stand for '='. -# -# After this loop, a command of the form "echo FOO | eval sed $substs" -# will replace a canonical option FOO with a %{...}-style spec pattern. -for match in $matches -do - canonical=`echo "$match" | sed -e 's/=.*//' -e 's/?/=/g'` - alias=`echo "$match" | sed -e 's/.*=//' -e 's/?/=/g'` - substs=`echo "$substs" | sed -e "s,s/$canonical/,&$alias|,"` -done - -# Build up the final SYSROOT_SUFFIX_SPEC in $spec. -spec= -for combo in $options -do - # See which option alternatives in $combo have their own sysroot - # directory. Create a subspec of the form "%{PAT1:/DIR1;...;PATn:DIRn}" - # from each such option OPTi, where DIRi is the directory associated - # with OPTi and PATi is the result of passing OPTi through $substs. - subspec= - for option in `echo "$combo" | tr '/' ' '` - do - dir=`echo "$option" | sed 's/mcpu=//'` - if test -d "$sysroot/$dir"; then - test -z "$subspec" || subspec="$subspec;" - subspec="$subspec"`echo "$option" | eval sed $substs`":/$dir" - fi - done - # Concatenate all the subspecs. - test -z "$subspec" || spec="$spec%{$subspec}" -done -if test -n "$spec"; then - echo "#undef SYSROOT_SUFFIX_SPEC" - echo "#define SYSROOT_SUFFIX_SPEC \"$spec\"" -fi diff --git a/gcc-4.7/gcc/config/bfin/rtems.h b/gcc-4.7/gcc/config/bfin/rtems.h deleted file mode 100644 index 6fa6ef10e..000000000 --- a/gcc-4.7/gcc/config/bfin/rtems.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Definitions for rtems targeting a bfin - Copyright (C) 2006, 2007 Free Software Foundation, Inc. - Contributed by Ralf Corsépius (ralf.corsepius@rtems.org). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* Target OS preprocessor built-ins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__rtems__"); \ - builtin_assert ("system=rtems"); \ - } \ - while (0) diff --git a/gcc-4.7/gcc/config/bfin/sync.md b/gcc-4.7/gcc/config/bfin/sync.md deleted file mode 100644 index 7025af497..000000000 --- a/gcc-4.7/gcc/config/bfin/sync.md +++ /dev/null @@ -1,178 +0,0 @@ -;; GCC machine description for Blackfin synchronization instructions. -;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. -;; Contributed by Analog Devices. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. -;; -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -(define_code_iterator FETCHOP [plus minus ior and xor]) -(define_code_attr fetchop_name - [(plus "add") (minus "sub") (ior "ior") (and "and") (xor "xor")]) -(define_code_attr fetchop_addr - [(plus "1072") (minus "1088") (ior "1104") (and "1120") (xor "1136")]) - -(define_insn "sync_<fetchop_name>si_internal" - [(set (mem:SI (match_operand:SI 0 "register_operand" "qA")) - (unspec:SI - [(FETCHOP:SI (mem:SI (match_dup 0)) - (match_operand:SI 1 "register_operand" "q0")) - (match_operand:SI 2 "register_no_elim_operand" "a")] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 3 "=q0")) - (clobber (match_scratch:SI 4 "=q1")) - (clobber (reg:SI REG_RETS))] - "TARGET_SUPPORTS_SYNC_CALLS" - "call (%2);" - [(set_attr "type" "call")]) - -(define_expand "sync_<fetchop_name>si" - [(parallel - [(set (match_operand:SI 0 "memory_operand" "+m") - (unspec:SI - [(FETCHOP:SI (match_dup 0) - (match_operand:SI 1 "register_operand" "q0")) - (match_dup 2)] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 3 "")) - (clobber (match_scratch:SI 4 "")) - (clobber (reg:SI REG_RETS))])] - "TARGET_SUPPORTS_SYNC_CALLS" -{ - if (!REG_P (XEXP (operands[0], 0))) - { - operands[0] = shallow_copy_rtx (operands[0]); - XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0)); - } - operands[2] = force_reg (Pmode, GEN_INT (<fetchop_addr>)); -}) - -(define_insn "sync_old_<fetchop_name>si_internal" - [(set (match_operand:SI 0 "register_operand" "=q1") - (mem:SI (match_operand:SI 1 "register_operand" "qA"))) - (set (mem:SI (match_dup 1)) - (unspec:SI - [(FETCHOP:SI (mem:SI (match_dup 1)) - (match_operand:SI 2 "register_operand" "q0")) - (match_operand:SI 3 "register_no_elim_operand" "a")] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 4 "=q0")) - (clobber (reg:SI REG_RETS))] - "TARGET_SUPPORTS_SYNC_CALLS" - "call (%3);" - [(set_attr "type" "call")]) - -(define_expand "sync_old_<fetchop_name>si" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "memory_operand" "")) - (set (match_dup 1) - (unspec:SI - [(FETCHOP:SI (match_dup 1) - (match_operand:SI 2 "register_operand" "")) - (match_dup 3)] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 4 "")) - (clobber (reg:SI REG_RETS))])] - "TARGET_SUPPORTS_SYNC_CALLS" -{ - if (!REG_P (XEXP (operands[1], 0))) - { - operands[1] = shallow_copy_rtx (operands[1]); - XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); - } - operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>)); -}) - -(define_insn "sync_new_<fetchop_name>si_internal" - [(set (match_operand:SI 0 "register_operand" "=q0") - (unspec:SI - [(FETCHOP:SI - (mem:SI (match_operand:SI 1 "register_operand" "qA")) - (match_operand:SI 2 "register_operand" "q0")) - (match_operand:SI 3 "register_no_elim_operand" "a")] - UNSPEC_ATOMIC)) - (set (mem:SI (match_dup 1)) - (unspec:SI - [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2)) - (match_dup 3)] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 4 "=q1")) - (clobber (reg:SI REG_RETS))] - "TARGET_SUPPORTS_SYNC_CALLS" - "call (%3);" - [(set_attr "type" "call")]) - -(define_expand "sync_new_<fetchop_name>si" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (unspec:SI - [(FETCHOP:SI (match_operand:SI 1 "memory_operand" "") - (match_operand:SI 2 "register_operand" "")) - (match_dup 3)] - UNSPEC_ATOMIC)) - (set (match_dup 1) - (unspec:SI - [(FETCHOP:SI (match_dup 1) (match_dup 2)) - (match_dup 3)] - UNSPEC_ATOMIC)) - (clobber (match_scratch:SI 4 "")) - (clobber (reg:SI REG_RETS))])] - "TARGET_SUPPORTS_SYNC_CALLS" -{ - if (!REG_P (XEXP (operands[1], 0))) - { - operands[1] = shallow_copy_rtx (operands[1]); - XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); - } - operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>)); -}) - -(define_insn "sync_compare_and_swapsi_internal" - [(set (match_operand:SI 0 "register_operand" "=q0") - (mem:SI (match_operand:SI 1 "register_operand" "qA"))) - (set (mem:SI (match_dup 1)) - (unspec:SI - [(mem:SI (match_dup 1)) - (match_operand:SI 2 "register_operand" "q1") - (match_operand:SI 3 "register_operand" "q2") - (match_operand:SI 4 "register_no_elim_operand" "a")] - UNSPEC_ATOMIC)) - (clobber (reg:SI REG_RETS))] - "TARGET_SUPPORTS_SYNC_CALLS" - "call (%4);" - [(set_attr "type" "call")]) - -(define_expand "sync_compare_and_swapsi" - [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "memory_operand" "")) - (set (match_dup 1) - (unspec:SI - [(match_dup 1) - (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "register_operand" "") - (match_dup 4)] - UNSPEC_ATOMIC)) - (clobber (reg:SI REG_RETS))])] - "TARGET_SUPPORTS_SYNC_CALLS" -{ - if (!REG_P (XEXP (operands[1], 0))) - { - operands[1] = shallow_copy_rtx (operands[1]); - XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); - } - operands[4] = force_reg (Pmode, GEN_INT (0x420)); -}) diff --git a/gcc-4.7/gcc/config/bfin/t-bfin-elf b/gcc-4.7/gcc/config/bfin/t-bfin-elf deleted file mode 100644 index 742740ebc..000000000 --- a/gcc-4.7/gcc/config/bfin/t-bfin-elf +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2005, 2006, 2007, 2008, 2011 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -## Target part of the Makefile - -MULTILIB_OPTIONS=mcpu=bf532-none -MULTILIB_OPTIONS+=mid-shared-library/msep-data/mfdpic mleaf-id-shared-library -MULTILIB_DIRNAMES=bf532-none mid-shared-library msep-data mfdpic mleaf-id-shared-library - -MULTILIB_MATCHES=mcpu?bf532-none=mcpu?bf512-none mcpu?bf532-none=mcpu?bf514-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf516-none mcpu?bf532-none=mcpu?bf518-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf522-none mcpu?bf532-none=mcpu?bf523-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf524-none mcpu?bf532-none=mcpu?bf525-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf526-none mcpu?bf532-none=mcpu?bf527-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none - -MULTILIB_EXCEPTIONS=mleaf-id-shared-library* -MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library* -MULTILIB_EXCEPTIONS+=*mfdpic/mleaf-id-shared-library* -MULTILIB_EXCEPTIONS+=*msep-data/mleaf-id-shared-library* diff --git a/gcc-4.7/gcc/config/bfin/t-bfin-linux b/gcc-4.7/gcc/config/bfin/t-bfin-linux deleted file mode 100644 index 7d25358c2..000000000 --- a/gcc-4.7/gcc/config/bfin/t-bfin-linux +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -## Target part of the Makefile - -MULTILIB_OPTIONS=mcpu=bf532-none -MULTILIB_DIRNAMES=bf532-none - -MULTILIB_MATCHES=mcpu?bf532-none=mcpu?bf512-none mcpu?bf532-none=mcpu?bf514-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf516-none mcpu?bf532-none=mcpu?bf518-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf522-none mcpu?bf532-none=mcpu?bf523-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf524-none mcpu?bf532-none=mcpu?bf525-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf526-none mcpu?bf532-none=mcpu?bf527-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none - -# This rule uses MULTILIB_MATCHES to generate a definition of -# SYSROOT_SUFFIX_SPEC. -linux-sysroot-suffix.h: $(srcdir)/config/bfin/print-sysroot-suffix.sh - $(SHELL) $(srcdir)/config/bfin/print-sysroot-suffix.sh \ - "$(SYSTEM_HEADER_DIR)/../.." "$(MULTILIB_MATCHES)" \ - "$(MULTILIB_OPTIONS)" > $@ - -generated_files += linux-sysroot-suffix.h diff --git a/gcc-4.7/gcc/config/bfin/t-bfin-uclinux b/gcc-4.7/gcc/config/bfin/t-bfin-uclinux deleted file mode 100644 index e3e9b13e7..000000000 --- a/gcc-4.7/gcc/config/bfin/t-bfin-uclinux +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -## Target part of the Makefile - -MULTILIB_OPTIONS=mcpu=bf532-none -MULTILIB_OPTIONS+=mid-shared-library/msep-data mleaf-id-shared-library -MULTILIB_DIRNAMES=bf532-none mid-shared-library msep-data mleaf-id-shared-library - -MULTILIB_MATCHES=mcpu?bf532-none=mcpu?bf512-none mcpu?bf532-none=mcpu?bf514-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf516-none mcpu?bf532-none=mcpu?bf518-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf522-none mcpu?bf532-none=mcpu?bf523-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf524-none mcpu?bf532-none=mcpu?bf525-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf526-none mcpu?bf532-none=mcpu?bf527-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none -MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none - -MULTILIB_EXCEPTIONS=mleaf-id-shared-library* -MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library* -MULTILIB_EXCEPTIONS+=*msep-data/mleaf-id-shared-library* diff --git a/gcc-4.7/gcc/config/bfin/t-rtems b/gcc-4.7/gcc/config/bfin/t-rtems deleted file mode 100644 index 728ab1c4f..000000000 --- a/gcc-4.7/gcc/config/bfin/t-rtems +++ /dev/null @@ -1,6 +0,0 @@ -# Multilibs for fbin RTEMS targets. - -MULTILIB_OPTIONS = -MULTILIB_DIRNAMES = -MULTILIB_EXTRA_OPTS = -MULTILIB_EXCEPTIONS = diff --git a/gcc-4.7/gcc/config/bfin/uclinux.h b/gcc-4.7/gcc/config/bfin/uclinux.h deleted file mode 100644 index da26be576..000000000 --- a/gcc-4.7/gcc/config/bfin/uclinux.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!shared: crt1%O%s} crti%O%s crtbegin%O%s crtlibid%O%s" - -#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS() - -#undef LINK_GCC_C_SEQUENCE_SPEC -#define LINK_GCC_C_SEQUENCE_SPEC "\ - %{mfast-fp:-lbffastfp} %G %L %{mfast-fp:-lbffastfp} %G \ -" - -/* Like the definition in gcc.c, but for purposes of uClinux, every link is - static. */ -#define MFWRAP_SPEC " %{fmudflap|fmudflapth: \ - --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ - --wrap=mmap --wrap=munmap --wrap=alloca\ - %{fmudflapth: --wrap=pthread_create\ -}} %{fmudflap|fmudflapth: --wrap=main}" - -#undef TARGET_SUPPORTS_SYNC_CALLS -#define TARGET_SUPPORTS_SYNC_CALLS 1 - -#define SUBTARGET_FDPIC_NOT_SUPPORTED |