/* Subroutines used for MIPS code generation.
Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by A. Lichnewsky, lich@inria.inria.fr.
Changes by Michael Meissner, meissner@osf.org.
64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "cfglayout.h"
#include "sched-int.h"
#include "tree-gimple.h"
+#include "bitmap.h"
/* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
ADDRESS_SYMBOLIC
};
+/* Classifies the prototype of a builtin function. */
+enum mips_function_type
+{
+ MIPS_V2SF_FTYPE_V2SF,
+ MIPS_V2SF_FTYPE_V2SF_V2SF,
+ MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
+ MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
+ MIPS_V2SF_FTYPE_SF_SF,
+ MIPS_INT_FTYPE_V2SF_V2SF,
+ MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
+ MIPS_INT_FTYPE_SF_SF,
+ MIPS_INT_FTYPE_DF_DF,
+ MIPS_SF_FTYPE_V2SF,
+ MIPS_SF_FTYPE_SF,
+ MIPS_SF_FTYPE_SF_SF,
+ MIPS_DF_FTYPE_DF,
+ MIPS_DF_FTYPE_DF_DF,
+
+ /* For MIPS DSP ASE */
+ MIPS_DI_FTYPE_DI_SI,
+ MIPS_DI_FTYPE_DI_SI_SI,
+ MIPS_DI_FTYPE_DI_V2HI_V2HI,
+ MIPS_DI_FTYPE_DI_V4QI_V4QI,
+ MIPS_SI_FTYPE_DI_SI,
+ MIPS_SI_FTYPE_PTR_SI,
+ MIPS_SI_FTYPE_SI,
+ MIPS_SI_FTYPE_SI_SI,
+ MIPS_SI_FTYPE_V2HI,
+ MIPS_SI_FTYPE_V2HI_V2HI,
+ MIPS_SI_FTYPE_V4QI,
+ MIPS_SI_FTYPE_V4QI_V4QI,
+ MIPS_SI_FTYPE_VOID,
+ MIPS_V2HI_FTYPE_SI,
+ MIPS_V2HI_FTYPE_SI_SI,
+ MIPS_V2HI_FTYPE_V2HI,
+ MIPS_V2HI_FTYPE_V2HI_SI,
+ MIPS_V2HI_FTYPE_V2HI_V2HI,
+ MIPS_V2HI_FTYPE_V4QI,
+ MIPS_V2HI_FTYPE_V4QI_V2HI,
+ MIPS_V4QI_FTYPE_SI,
+ MIPS_V4QI_FTYPE_V2HI_V2HI,
+ MIPS_V4QI_FTYPE_V4QI_SI,
+ MIPS_V4QI_FTYPE_V4QI_V4QI,
+ MIPS_VOID_FTYPE_SI_SI,
+ MIPS_VOID_FTYPE_V2HI_V2HI,
+ MIPS_VOID_FTYPE_V4QI_V4QI,
+
+ /* The last type. */
+ MIPS_MAX_FTYPE_MAX
+};
+
+/* Specifies how a builtin function should be converted into rtl. */
+enum mips_builtin_type
+{
+ /* The builtin corresponds directly to an .md pattern. The return
+ value is mapped to operand 0 and the arguments are mapped to
+ operands 1 and above. */
+ MIPS_BUILTIN_DIRECT,
+
+ /* The builtin corresponds directly to an .md pattern. There is no return
+ value and the arguments are mapped to operands 0 and above. */
+ MIPS_BUILTIN_DIRECT_NO_TARGET,
+
+ /* The builtin corresponds to a comparison instruction followed by
+ a mips_cond_move_tf_ps pattern. The first two arguments are the
+ values to compare and the second two arguments are the vector
+ operands for the movt.ps or movf.ps instruction (in assembly order). */
+ MIPS_BUILTIN_MOVF,
+ MIPS_BUILTIN_MOVT,
+
+ /* The builtin corresponds to a V2SF comparison instruction. Operand 0
+ of this instruction is the result of the comparison, which has mode
+ CCV2 or CCV4. The function arguments are mapped to operands 1 and
+ above. The function's return value is an SImode boolean that is
+ true under the following conditions:
+
+ MIPS_BUILTIN_CMP_ANY: one of the registers is true
+ MIPS_BUILTIN_CMP_ALL: all of the registers are true
+ MIPS_BUILTIN_CMP_LOWER: the first register is true
+ MIPS_BUILTIN_CMP_UPPER: the second register is true. */
+ MIPS_BUILTIN_CMP_ANY,
+ MIPS_BUILTIN_CMP_ALL,
+ MIPS_BUILTIN_CMP_UPPER,
+ MIPS_BUILTIN_CMP_LOWER,
+
+ /* As above, but the instruction only sets a single $fcc register. */
+ MIPS_BUILTIN_CMP_SINGLE,
+
+ /* For generating bposge32 branch instructions in MIPS32 DSP ASE. */
+ MIPS_BUILTIN_BPOSGE32
+};
+
+/* Invokes MACRO (COND) for each c.cond.fmt condition. */
+#define MIPS_FP_CONDITIONS(MACRO) \
+ MACRO (f), \
+ MACRO (un), \
+ MACRO (eq), \
+ MACRO (ueq), \
+ MACRO (olt), \
+ MACRO (ult), \
+ MACRO (ole), \
+ MACRO (ule), \
+ MACRO (sf), \
+ MACRO (ngle), \
+ MACRO (seq), \
+ MACRO (ngl), \
+ MACRO (lt), \
+ MACRO (nge), \
+ MACRO (le), \
+ MACRO (ngt)
+
+/* Enumerates the codes above as MIPS_FP_COND_<X>. */
+#define DECLARE_MIPS_COND(X) MIPS_FP_COND_ ## X
+enum mips_fp_condition {
+ MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
+};
+
+/* Index X provides the string representation of MIPS_FP_COND_<X>. */
+#define STRINGIFY(X) #X
+static const char *const mips_fp_conditions[] = {
+ MIPS_FP_CONDITIONS (STRINGIFY)
+};
+
/* A function to save or store a register. The first argument is the
register and the second is the stack slot. */
typedef void (*mips_save_restore_fn) (rtx, rtx);
static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
static bool mips_classify_address (struct mips_address_info *, rtx,
enum machine_mode, int);
+static bool mips_cannot_force_const_mem (rtx);
static int mips_symbol_insns (enum mips_symbol_type);
static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
static rtx mips_force_temporary (rtx, rtx);
static bool mips_get_unaligned_mem (rtx *, unsigned int, int, rtx *, rtx *);
static void mips_set_architecture (const struct mips_cpu_info *);
static void mips_set_tune (const struct mips_cpu_info *);
+static bool mips_handle_option (size_t, const char *, int);
static struct machine_function *mips_init_machine_status (void);
static void print_operand_reloc (FILE *, rtx, const char **);
#if TARGET_IRIX
static void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static int symbolic_expression_p (rtx);
-static void mips_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
+static section *mips_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+static section *mips_function_rodata_section (tree);
static bool mips_in_small_data_p (tree);
static int mips_fpr_return_fields (tree, tree *);
static bool mips_return_in_msb (tree);
static void mips_reorg (void);
static bool mips_strict_matching_cpu_name_p (const char *, const char *);
static bool mips_matching_cpu_name_p (const char *, const char *);
-static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
+static const struct mips_cpu_info *mips_parse_cpu (const char *);
static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
static bool mips_return_in_memory (tree, tree);
static bool mips_strict_argument_naming (CUMULATIVE_ARGS *);
static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
tree, bool);
+static bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode,
+ tree, bool);
+static int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode,
+ tree, bool);
+static bool mips_valid_pointer_mode (enum machine_mode);
static bool mips_vector_mode_supported_p (enum machine_mode);
-static void mips_init_builtins (void);
+static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
+static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static rtx mips_expand_compare_builtin (rtx, unsigned int, tree);
-static rtx mips_expand_ps_compare_builtin (enum mips_cmp_choice, rtx,
- unsigned int, tree);
-static rtx mips_expand_4s_compare_builtin (enum mips_cmp_choice, rtx,
- unsigned int, tree);
-static rtx mips_expand_ps_cond_move_builtin (enum mips_cmp_choice, rtx,
- unsigned int, tree);
+static void mips_init_builtins (void);
+static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool);
+static rtx mips_expand_builtin_movtf (enum mips_builtin_type,
+ enum insn_code, enum mips_fp_condition,
+ rtx, tree);
+static rtx mips_expand_builtin_compare (enum mips_builtin_type,
+ enum insn_code, enum mips_fp_condition,
+ rtx, tree);
+static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
+static void mips_encode_section_info (tree, rtx, int);
+static void mips_extra_live_on_entry (bitmap);
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
refers to GP relative global variables. */
rtx mips16_gp_pseudo_rtx;
+ /* The number of extra stack bytes taken up by register varargs.
+ This area is allocated by the callee at the very top of the frame. */
+ int varargs_size;
+
/* Current frame information, calculated by compute_frame_size. */
struct mips_frame_info frame;
/* The number of words passed in registers, rounded up. */
unsigned int reg_words;
- /* The offset of the first register from GP_ARG_FIRST or FP_ARG_FIRST,
- or MAX_ARGS_IN_REGISTERS if the argument is passed entirely
+ /* For EABI, the offset of the first register from GP_ARG_FIRST or
+ FP_ARG_FIRST. For other ABIs, the offset of the first register from
+ the start of the ABI's argument structure (see the CUMULATIVE_ARGS
+ comment for details).
+
+ The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely
on the stack. */
unsigned int reg_offset;
int mips_isa;
/* Which ABI to use. */
-int mips_abi;
+int mips_abi = MIPS_ABI_DEFAULT;
-/* Strings to hold which cpu and instruction set architecture to use. */
-const char *mips_arch_string; /* for -march=<xxx> */
-const char *mips_tune_string; /* for -mtune=<xxx> */
-const char *mips_isa_string; /* for -mips{1,2,3,4} */
-const char *mips_abi_string; /* for -mabi={32,n32,64,eabi} */
+/* Cost information to use. */
+const struct mips_rtx_cost_data *mips_cost;
/* Whether we are generating mips16 hard float code. In mips16 mode
we always set TARGET_SOFT_FLOAT; this variable is nonzero if
should arrange to call mips32 hard floating point code. */
int mips16_hard_float;
-const char *mips_cache_flush_func = CACHE_FLUSH_FUNC;
+/* The architecture selected by -mipsN. */
+static const struct mips_cpu_info *mips_isa_info;
/* If TRUE, we split addresses into their high and low parts in the RTL. */
int mips_split_addresses;
/* Map hard register number to register class */
const enum reg_class mips_regno_to_class[] =
{
- LEA_REGS, LEA_REGS, M16_NA_REGS, M16_NA_REGS,
+ LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG,
M16_REGS, M16_REGS, M16_REGS, M16_REGS,
LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
- COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS,
+ ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS
};
-/* Map register constraint character to register class. */
-enum reg_class mips_char_to_class[256];
+/* Table of machine dependent attributes. */
+const struct attribute_spec mips_attribute_table[] =
+{
+ { "long_call", 0, 0, false, true, true, NULL },
+ { NULL, 0, 0, false, false, false, NULL }
+};
\f
/* A table describing all the processors gcc knows about. Names are
matched in the order listed. The first mention of an ISA level is
/* MIPS32 */
{ "4kc", PROCESSOR_4KC, 32 },
- { "4kp", PROCESSOR_4KC, 32 }, /* = 4kc */
+ { "4km", PROCESSOR_4KC, 32 }, /* = 4kc */
+ { "4kp", PROCESSOR_4KP, 32 },
/* MIPS32 Release 2 */
{ "m4k", PROCESSOR_M4K, 33 },
+ { "24k", PROCESSOR_24K, 33 },
+ { "24kc", PROCESSOR_24K, 33 }, /* 24K no FPU */
+ { "24kf", PROCESSOR_24K, 33 }, /* 24K 1:2 FPU */
+ { "24kx", PROCESSOR_24KX, 33 }, /* 24K 1:1 FPU */
/* MIPS64 */
{ "5kc", PROCESSOR_5KC, 64 },
+ { "5kf", PROCESSOR_5KF, 64 },
{ "20kc", PROCESSOR_20KC, 64 },
{ "sb1", PROCESSOR_SB1, 64 },
{ "sr71000", PROCESSOR_SR71000, 64 },
/* End marker */
{ 0, 0, 0 }
};
+
+/* Default costs. If these are used for a processor we should look
+ up the actual costs. */
+#define DEFAULT_COSTS COSTS_N_INSNS (6), /* fp_add */ \
+ COSTS_N_INSNS (7), /* fp_mult_sf */ \
+ COSTS_N_INSNS (8), /* fp_mult_df */ \
+ COSTS_N_INSNS (23), /* fp_div_sf */ \
+ COSTS_N_INSNS (36), /* fp_div_df */ \
+ COSTS_N_INSNS (10), /* int_mult_si */ \
+ COSTS_N_INSNS (10), /* int_mult_di */ \
+ COSTS_N_INSNS (69), /* int_div_si */ \
+ COSTS_N_INSNS (69), /* int_div_di */ \
+ 2, /* branch_cost */ \
+ 4 /* memory_latency */
+
+/* Need to replace these with the costs of calling the appropriate
+ libgcc routine. */
+#define SOFT_FP_COSTS COSTS_N_INSNS (256), /* fp_add */ \
+ COSTS_N_INSNS (256), /* fp_mult_sf */ \
+ COSTS_N_INSNS (256), /* fp_mult_df */ \
+ COSTS_N_INSNS (256), /* fp_div_sf */ \
+ COSTS_N_INSNS (256) /* fp_div_df */
+
+static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] =
+ {
+ { /* R3000 */
+ COSTS_N_INSNS (2), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (12), /* fp_div_sf */
+ COSTS_N_INSNS (19), /* fp_div_df */
+ COSTS_N_INSNS (12), /* int_mult_si */
+ COSTS_N_INSNS (12), /* int_mult_di */
+ COSTS_N_INSNS (35), /* int_div_si */
+ COSTS_N_INSNS (35), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+
+ },
+ { /* 4KC */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (6), /* int_mult_si */
+ COSTS_N_INSNS (6), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (36), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 4KP */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (36), /* int_mult_si */
+ COSTS_N_INSNS (36), /* int_mult_di */
+ COSTS_N_INSNS (37), /* int_div_si */
+ COSTS_N_INSNS (37), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 5KC */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (11), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 5KF */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (11), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 20KC */
+ DEFAULT_COSTS
+ },
+ { /* 24k */
+ COSTS_N_INSNS (8), /* fp_add */
+ COSTS_N_INSNS (8), /* fp_mult_sf */
+ COSTS_N_INSNS (10), /* fp_mult_df */
+ COSTS_N_INSNS (34), /* fp_div_sf */
+ COSTS_N_INSNS (64), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (41), /* int_div_si */
+ COSTS_N_INSNS (41), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 24kx */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (41), /* int_div_si */
+ COSTS_N_INSNS (41), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* M4k */
+ DEFAULT_COSTS
+ },
+ { /* R3900 */
+ COSTS_N_INSNS (2), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (12), /* fp_div_sf */
+ COSTS_N_INSNS (19), /* fp_div_df */
+ COSTS_N_INSNS (2), /* int_mult_si */
+ COSTS_N_INSNS (2), /* int_mult_di */
+ COSTS_N_INSNS (35), /* int_div_si */
+ COSTS_N_INSNS (35), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R6000 */
+ COSTS_N_INSNS (3), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (15), /* fp_div_sf */
+ COSTS_N_INSNS (16), /* fp_div_df */
+ COSTS_N_INSNS (17), /* int_mult_si */
+ COSTS_N_INSNS (17), /* int_mult_di */
+ COSTS_N_INSNS (38), /* int_div_si */
+ COSTS_N_INSNS (38), /* int_div_di */
+ 2, /* branch_cost */
+ 6 /* memory_latency */
+ },
+ { /* R4000 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (10), /* int_mult_si */
+ COSTS_N_INSNS (10), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 2, /* branch_cost */
+ 6 /* memory_latency */
+ },
+ { /* R4100 */
+ DEFAULT_COSTS
+ },
+ { /* R4111 */
+ DEFAULT_COSTS
+ },
+ { /* R4120 */
+ DEFAULT_COSTS
+ },
+ { /* R4130 */
+ /* The only costs that appear to be updated here are
+ integer multiplication. */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (6), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R4300 */
+ DEFAULT_COSTS
+ },
+ { /* R4600 */
+ DEFAULT_COSTS
+ },
+ { /* R4650 */
+ DEFAULT_COSTS
+ },
+ { /* R5000 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (36), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R5400 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (30), /* fp_div_sf */
+ COSTS_N_INSNS (59), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (42), /* int_div_si */
+ COSTS_N_INSNS (74), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R5500 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (30), /* fp_div_sf */
+ COSTS_N_INSNS (59), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (9), /* int_mult_di */
+ COSTS_N_INSNS (42), /* int_div_si */
+ COSTS_N_INSNS (74), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R7000 */
+ /* The only costs that are changed here are
+ integer multiplication. */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (9), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R8000 */
+ DEFAULT_COSTS
+ },
+ { /* R9000 */
+ /* The only costs that are changed here are
+ integer multiplication. */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (8), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* SB1 */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (4), /* fp_mult_df */
+ COSTS_N_INSNS (24), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* SR71000 */
+ DEFAULT_COSTS
+ },
+ };
+
\f
/* Nonzero if -march should decide the default value of MASK_SOFT_FLOAT. */
#ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
#define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section
+#undef TARGET_ASM_FUNCTION_RODATA_SECTION
+#define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER mips_sched_reorder
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
mips_multipass_dfa_lookahead
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (TARGET_DEFAULT \
+ | TARGET_CPU_DEFAULT \
+ | TARGET_ENDIAN_DEFAULT \
+ | TARGET_FP_EXCEPTIONS_DEFAULT \
+ | MASK_CHECK_ZERO_DIV \
+ | MASK_FUSED_MADD)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION mips_handle_option
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE mips_pass_by_reference
+#undef TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES mips_callee_copies
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN mips_expand_builtin
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS HAVE_AS_TLS
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO mips_encode_section_info
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE mips_attribute_table
+
+#undef TARGET_EXTRA_LIVE_ON_ENTRY
+/* With -mabicalls (which is the default on GNU/Linux),
+ PIC_FUNCTION_ADDR_REGNUM is live on function entry and is to
+ initialize $28, which is PIC_OFFSET_TABLE_REGNUM. */
+#define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
return SYMBOL_GENERAL;
}
- if (GET_CODE (x) != SYMBOL_REF)
- abort ();
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+
+ if (SYMBOL_REF_TLS_MODEL (x))
+ return SYMBOL_TLS;
if (CONSTANT_POOL_ADDRESS_P (x))
{
if (UNSPEC_ADDRESS_P (x))
*symbol_type = UNSPEC_ADDRESS_TYPE (x);
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
- *symbol_type = mips_classify_symbol (x);
+ {
+ *symbol_type = mips_classify_symbol (x);
+ if (*symbol_type == SYMBOL_TLS)
+ return false;
+ }
else
return false;
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
case SYMBOL_GOTOFF_LOADGP:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_TPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TLS:
return false;
}
- abort ();
+ gcc_unreachable ();
}
if (!strict && GET_CODE (x) == SUBREG)
x = SUBREG_REG (x);
- return (GET_CODE (x) == REG
+ return (REG_P (x)
&& mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict));
}
/* The address will have to be loaded from the GOT first. */
return false;
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_TPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TLS:
+ return false;
+
case SYMBOL_GOTOFF_PAGE:
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
case SYMBOL_64_LOW:
return true;
}
- abort ();
+ gcc_unreachable ();
}
return false;
}
}
+
+/* Return true if X is a thread-local symbol. */
+
+static bool
+mips_tls_operand_p (rtx x)
+{
+ return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+/* Return true if X can not be forced into a constant pool. */
+
+static int
+mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ return mips_tls_operand_p (*x);
+}
+
+/* Return true if X can not be forced into a constant pool. */
+
+static bool
+mips_cannot_force_const_mem (rtx x)
+{
+ if (! TARGET_HAVE_TLS)
+ return false;
+
+ return for_each_rtx (&x, &mips_tls_symbol_ref_1, 0);
+}
\f
/* Return the number of instructions needed to load a symbol of the
given type into a register. If valid in an address, the same number
case SYMBOL_64_HIGH:
case SYMBOL_64_MID:
case SYMBOL_64_LOW:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TPREL:
/* Check whether the offset is a 16- or 32-bit value. */
return mips_split_p[type] ? 2 : 1;
+
+ case SYMBOL_TLS:
+ /* We don't treat a bare TLS symbol as a constant. */
+ return 0;
}
- abort ();
+ gcc_unreachable ();
}
/* Return true if X is a legitimate $sp-based address for mode MDOE. */
int
mips_fetch_insns (rtx x)
{
- if (GET_CODE (x) != MEM)
- abort ();
-
+ gcc_assert (MEM_P (x));
return mips_address_insns (XEXP (x, 0), GET_MODE (x));
}
count = 1;
if (TARGET_CHECK_ZERO_DIV)
- count += 2;
+ {
+ if (GENERATE_DIVIDE_TRAPS)
+ count++;
+ else
+ count += 2;
+ }
+
if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
count++;
return count;
return plus_constant (reg, offset);
}
+/* Emit a call to __tls_get_addr. SYM is the TLS symbol we are
+ referencing, and TYPE is the symbol type to use (either global
+ dynamic or local dynamic). V0 is an RTX for the return value
+ location. The entire insn sequence is returned. */
+
+static GTY(()) rtx mips_tls_symbol;
+
+static rtx
+mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
+{
+ rtx insn, loc, tga, a0;
+
+ a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+
+ if (!mips_tls_symbol)
+ mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
+
+ loc = mips_unspec_address (sym, type);
+
+ start_sequence ();
+
+ emit_insn (gen_rtx_SET (Pmode, a0,
+ gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
+ tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
+ insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
+ CONST_OR_PURE_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
+ insn = get_insns ();
+
+ end_sequence ();
+
+ return insn;
+}
+
+/* Generate the code to access LOC, a thread local SYMBOL_REF. The
+ return value will be a valid address and move_operand (either a REG
+ or a LO_SUM). */
+
+static rtx
+mips_legitimize_tls_address (rtx loc)
+{
+ rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
+ enum tls_model model;
+
+ v0 = gen_rtx_REG (Pmode, GP_RETURN);
+ v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
+
+ model = SYMBOL_REF_TLS_MODEL (loc);
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insn, dest, v0, loc);
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
+ tmp1 = gen_reg_rtx (Pmode);
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LDM result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLS_LDM);
+ emit_libcall_block (insn, tmp1, v0, eqv);
+
+ tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
+ dest = gen_rtx_LO_SUM (Pmode, tmp2,
+ mips_unspec_address (loc, SYMBOL_DTPREL));
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ tmp1 = gen_reg_rtx (Pmode);
+ tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
+ if (Pmode == DImode)
+ {
+ emit_insn (gen_tls_get_tp_di (v1));
+ emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
+ }
+ else
+ {
+ emit_insn (gen_tls_get_tp_si (v1));
+ emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
+ }
+ dest = gen_reg_rtx (Pmode);
+ emit_insn (gen_add3_insn (dest, tmp1, v1));
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+
+ if (Pmode == DImode)
+ emit_insn (gen_tls_get_tp_di (v1));
+ else
+ emit_insn (gen_tls_get_tp_si (v1));
+
+ tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
+ dest = gen_rtx_LO_SUM (Pmode, tmp1,
+ mips_unspec_address (loc, SYMBOL_TPREL));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return dest;
+}
/* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can
be legitimized in a way that the generic machinery might not expect,
{
enum mips_symbol_type symbol_type;
+ if (mips_tls_operand_p (*xloc))
+ {
+ *xloc = mips_legitimize_tls_address (*xloc);
+ return true;
+ }
+
/* See if the address can split into a high part and a LO_SUM. */
if (mips_symbolic_constant_p (*xloc, &symbol_type)
&& mips_symbolic_address_p (symbol_type, mode)
return;
}
+ if (mips_tls_operand_p (src))
+ {
+ emit_move_insn (dest, mips_legitimize_tls_address (src));
+ return;
+ }
+
/* See if the symbol can be split. For mips16, this is often worse than
forcing it in the constant pool since it needs the single-register form
of addiu or daddiu. */
mips_rtx_costs (rtx x, int code, int outer_code, int *total)
{
enum machine_mode mode = GET_MODE (x);
+ bool float_mode_p = FLOAT_MODE_P (mode);
switch (code)
{
case CONST_INT:
- if (!TARGET_MIPS16)
- {
- /* Always return 0, since we don't have different sized
- instructions, hence different costs according to Richard
- Kenner */
- *total = 0;
- return true;
- }
-
- /* A number between 1 and 8 inclusive is efficient for a shift.
- Otherwise, we will need an extended instruction. */
- if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT
- || (outer_code) == LSHIFTRT)
+ if (TARGET_MIPS16)
{
- if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
- *total = 0;
- else
- *total = COSTS_N_INSNS (1);
- return true;
- }
+ /* A number between 1 and 8 inclusive is efficient for a shift.
+ Otherwise, we will need an extended instruction. */
+ if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT
+ || (outer_code) == LSHIFTRT)
+ {
+ if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
- /* We can use cmpi for an xor with an unsigned 16 bit value. */
- if ((outer_code) == XOR
- && INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
- {
- *total = 0;
- return true;
- }
+ /* We can use cmpi for an xor with an unsigned 16 bit value. */
+ if ((outer_code) == XOR
+ && INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
+ {
+ *total = 0;
+ return true;
+ }
- /* We may be able to use slt or sltu for a comparison with a
- signed 16 bit value. (The boundary conditions aren't quite
- right, but this is just a heuristic anyhow.) */
- if (((outer_code) == LT || (outer_code) == LE
- || (outer_code) == GE || (outer_code) == GT
- || (outer_code) == LTU || (outer_code) == LEU
- || (outer_code) == GEU || (outer_code) == GTU)
- && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
- {
- *total = 0;
- return true;
- }
+ /* We may be able to use slt or sltu for a comparison with a
+ signed 16 bit value. (The boundary conditions aren't quite
+ right, but this is just a heuristic anyhow.) */
+ if (((outer_code) == LT || (outer_code) == LE
+ || (outer_code) == GE || (outer_code) == GT
+ || (outer_code) == LTU || (outer_code) == LEU
+ || (outer_code) == GEU || (outer_code) == GTU)
+ && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
+ {
+ *total = 0;
+ return true;
+ }
- /* Equality comparisons with 0 are cheap. */
- if (((outer_code) == EQ || (outer_code) == NE)
- && INTVAL (x) == 0)
- {
- *total = 0;
- return true;
- }
+ /* Equality comparisons with 0 are cheap. */
+ if (((outer_code) == EQ || (outer_code) == NE)
+ && INTVAL (x) == 0)
+ {
+ *total = 0;
+ return true;
+ }
- /* Constants in the range 0...255 can be loaded with an unextended
- instruction. They are therefore as cheap as a register move.
+ /* Constants in the range 0...255 can be loaded with an unextended
+ instruction. They are therefore as cheap as a register move.
- Given the choice between "li R1,0...255" and "move R1,R2"
- (where R2 is a known constant), it is usually better to use "li",
- since we do not want to unnessarily extend the lifetime of R2. */
- if (outer_code == SET
- && INTVAL (x) >= 0
- && INTVAL (x) < 256)
+ Given the choice between "li R1,0...255" and "move R1,R2"
+ (where R2 is a known constant), it is usually better to use "li",
+ since we do not want to unnecessarily extend the lifetime
+ of R2. */
+ if (outer_code == SET
+ && INTVAL (x) >= 0
+ && INTVAL (x) < 256)
+ {
+ *total = 0;
+ return true;
+ }
+ }
+ else
{
+ /* These can be used anywhere. */
*total = 0;
return true;
}
- /* Otherwise fall through to the handling below. */
+ /* Otherwise fall through to the handling below because
+ we'll need to construct the constant. */
case CONST:
case SYMBOL_REF:
case MEM:
{
- /* If the address is legitimate, return the number of
- instructions it needs, otherwise use the default handling. */
- int n = mips_address_insns (XEXP (x, 0), GET_MODE (x));
- if (n > 0)
- {
- *total = COSTS_N_INSNS (1 + n);
- return true;
- }
- return false;
+ /* If the address is legitimate, return the number of
+ instructions it needs, otherwise use the default handling. */
+ int n = mips_address_insns (XEXP (x, 0), GET_MODE (x));
+ if (n > 0)
+ {
+ *total = COSTS_N_INSNS (n + 1);
+ return true;
+ }
+ return false;
}
case FFS:
return false;
case ABS:
- if (mode == SFmode || mode == DFmode)
+ if (float_mode_p)
*total = COSTS_N_INSNS (1);
else
*total = COSTS_N_INSNS (4);
case PLUS:
case MINUS:
- if (mode == SFmode || mode == DFmode)
- {
- if (TUNE_MIPS3000 || TUNE_MIPS3900)
- *total = COSTS_N_INSNS (2);
- else if (TUNE_MIPS6000)
- *total = COSTS_N_INSNS (3);
- else if (TUNE_SB1)
- *total = COSTS_N_INSNS (4);
- else
- *total = COSTS_N_INSNS (6);
- return true;
- }
- if (mode == DImode && !TARGET_64BIT)
+ if (float_mode_p)
+ {
+ *total = mips_cost->fp_add;
+ return true;
+ }
+
+ else if (mode == DImode && !TARGET_64BIT)
{
*total = COSTS_N_INSNS (4);
return true;
case NEG:
if (mode == DImode && !TARGET_64BIT)
{
- *total = 4;
+ *total = COSTS_N_INSNS (4);
return true;
}
return false;
case MULT:
if (mode == SFmode)
- {
- if (TUNE_MIPS3000
- || TUNE_MIPS3900
- || TUNE_MIPS5000
- || TUNE_SB1)
- *total = COSTS_N_INSNS (4);
- else if (TUNE_MIPS6000
- || TUNE_MIPS5400
- || TUNE_MIPS5500)
- *total = COSTS_N_INSNS (5);
- else
- *total = COSTS_N_INSNS (7);
- return true;
- }
+ *total = mips_cost->fp_mult_sf;
- if (mode == DFmode)
- {
- if (TUNE_SB1)
- *total = COSTS_N_INSNS (4);
- else if (TUNE_MIPS3000
- || TUNE_MIPS3900
- || TUNE_MIPS5000)
- *total = COSTS_N_INSNS (5);
- else if (TUNE_MIPS6000
- || TUNE_MIPS5400
- || TUNE_MIPS5500)
- *total = COSTS_N_INSNS (6);
- else
- *total = COSTS_N_INSNS (8);
- return true;
- }
+ else if (mode == DFmode)
+ *total = mips_cost->fp_mult_df;
+
+ else if (mode == SImode)
+ *total = mips_cost->int_mult_si;
- if (TUNE_MIPS3000)
- *total = COSTS_N_INSNS (12);
- else if (TUNE_MIPS3900)
- *total = COSTS_N_INSNS (2);
- else if (TUNE_MIPS4130)
- *total = COSTS_N_INSNS (mode == DImode ? 6 : 4);
- else if (TUNE_MIPS5400 || TUNE_SB1)
- *total = COSTS_N_INSNS (mode == DImode ? 4 : 3);
- else if (TUNE_MIPS5500 || TUNE_MIPS7000)
- *total = COSTS_N_INSNS (mode == DImode ? 9 : 5);
- else if (TUNE_MIPS9000)
- *total = COSTS_N_INSNS (mode == DImode ? 8 : 3);
- else if (TUNE_MIPS6000)
- *total = COSTS_N_INSNS (17);
- else if (TUNE_MIPS5000)
- *total = COSTS_N_INSNS (5);
else
- *total = COSTS_N_INSNS (10);
+ *total = mips_cost->int_mult_di;
+
return true;
case DIV:
case MOD:
- if (mode == SFmode)
- {
- if (TUNE_MIPS3000
- || TUNE_MIPS3900)
- *total = COSTS_N_INSNS (12);
- else if (TUNE_MIPS6000)
- *total = COSTS_N_INSNS (15);
- else if (TUNE_SB1)
- *total = COSTS_N_INSNS (24);
- else if (TUNE_MIPS5400 || TUNE_MIPS5500)
- *total = COSTS_N_INSNS (30);
- else
- *total = COSTS_N_INSNS (23);
- return true;
- }
+ if (float_mode_p)
+ {
+ if (mode == SFmode)
+ *total = mips_cost->fp_div_sf;
+ else
+ *total = mips_cost->fp_div_df;
- if (mode == DFmode)
- {
- if (TUNE_MIPS3000
- || TUNE_MIPS3900)
- *total = COSTS_N_INSNS (19);
- else if (TUNE_MIPS5400 || TUNE_MIPS5500)
- *total = COSTS_N_INSNS (59);
- else if (TUNE_MIPS6000)
- *total = COSTS_N_INSNS (16);
- else if (TUNE_SB1)
- *total = COSTS_N_INSNS (32);
- else
- *total = COSTS_N_INSNS (36);
- return true;
- }
+ return true;
+ }
/* Fall through. */
case UDIV:
case UMOD:
- if (TUNE_MIPS3000
- || TUNE_MIPS3900)
- *total = COSTS_N_INSNS (35);
- else if (TUNE_MIPS6000)
- *total = COSTS_N_INSNS (38);
- else if (TUNE_MIPS5000)
- *total = COSTS_N_INSNS (36);
- else if (TUNE_SB1)
- *total = COSTS_N_INSNS ((mode == SImode) ? 36 : 68);
- else if (TUNE_MIPS5400 || TUNE_MIPS5500)
- *total = COSTS_N_INSNS ((mode == SImode) ? 42 : 74);
+ if (mode == DImode)
+ *total = mips_cost->int_div_di;
else
- *total = COSTS_N_INSNS (69);
+ *total = mips_cost->int_div_si;
+
return true;
case SIGN_EXTEND:
*total = COSTS_N_INSNS (1);
return true;
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case SQRT:
+ *total = mips_cost->fp_add;
+ return true;
+
default:
return false;
}
else
byte = 0;
- if (GET_CODE (op) == REG)
+ if (REG_P (op))
{
if (FP_REG_P (REGNO (op)))
return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
- if (REGNO (op) == HI_REGNUM)
- return gen_rtx_REG (word_mode, high_p ? HI_REGNUM : LO_REGNUM);
+ if (ACC_HI_REG_P (REGNO (op)))
+ return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1);
}
- if (GET_CODE (op) == MEM)
+ if (MEM_P (op))
return mips_rewrite_small_data (adjust_address (op, word_mode, byte));
return simplify_gen_subreg (word_mode, op, mode, byte);
ldc1 and sdc1 on MIPS II and above. */
if (mips_isa > 1)
{
- if (FP_REG_RTX_P (dest) && GET_CODE (src) == MEM)
+ if (FP_REG_RTX_P (dest) && MEM_P (src))
return false;
- if (FP_REG_RTX_P (src) && GET_CODE (dest) == MEM)
+ if (FP_REG_RTX_P (src) && MEM_P (dest))
return false;
}
return true;
rtx low_dest;
low_dest = mips_subword (dest, 0);
- if (GET_CODE (low_dest) == REG
+ if (REG_P (low_dest)
&& reg_overlap_mentioned_p (low_dest, src))
{
emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
if (MD_REG_P (REGNO (dest)))
return "mt%0\t%z1";
+ if (DSP_ACC_REG_P (REGNO (dest)))
+ {
+ static char retval[] = "mt__\t%z1,%q0";
+ retval[2] = reg_names[REGNO (dest)][4];
+ retval[3] = reg_names[REGNO (dest)][5];
+ return retval;
+ }
+
if (FP_REG_P (REGNO (dest)))
return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0");
{
if (src_code == REG)
{
+ if (DSP_ACC_REG_P (REGNO (src)))
+ {
+ static char retval[] = "mf__\t%0,%q1";
+ retval[2] = reg_names[REGNO (src)][4];
+ retval[3] = reg_names[REGNO (src)][5];
+ return retval;
+ }
+
if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
return retval;
}
- abort ();
+ gcc_unreachable ();
}
\f
/* Restore $gp from its save slot. Valid only when using o32 or
{
rtx address, slot;
- if (!TARGET_ABICALLS || !TARGET_OLDABI)
- abort ();
+ gcc_assert (TARGET_ABICALLS && TARGET_OLDABI);
address = mips_add_offset (pic_offset_table_rtx,
frame_pointer_needed
return sleu_operand (cmp1, VOIDmode);
default:
- abort ();
+ gcc_unreachable ();
}
}
+/* Canonicalize LE or LEU comparisons into LT comparisons when
+ possible to avoid extra instructions or inverting the
+ comparison. */
+
+static bool
+mips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1,
+ enum machine_mode mode)
+{
+ HOST_WIDE_INT original, plus_one;
+
+ if (GET_CODE (*cmp1) != CONST_INT)
+ return false;
+
+ original = INTVAL (*cmp1);
+ plus_one = trunc_int_for_mode ((unsigned HOST_WIDE_INT) original + 1, mode);
+
+ switch (*code)
+ {
+ case LE:
+ if (original < plus_one)
+ {
+ *code = LT;
+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
+ return true;
+ }
+ break;
+
+ case LEU:
+ if (plus_one != 0)
+ {
+ *code = LTU;
+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
+ return true;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return false;
+
+}
+
/* Compare CMP0 and CMP1 using relational operator CODE and store the
result in TARGET. CMP0 and TARGET are register_operands that have
the same integer mode. If INVERT_PTR is nonnull, it's OK to set
rtx target, rtx cmp0, rtx cmp1)
{
/* First see if there is a MIPS instruction that can do this operation
- with CMP1 in its current form. If not, try doing the same for the
+ with CMP1 in its current form. If not, try to canonicalize the
+ comparison to LT. If that fails, try doing the same for the
inverse operation. If that also fails, force CMP1 into a register
and try again. */
if (mips_relational_operand_ok_p (code, cmp1))
mips_emit_binary (code, target, cmp0, cmp1);
+ else if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target)))
+ mips_emit_binary (code, target, cmp0, cmp1);
else
{
enum rtx_code inv_code = reverse_condition (code);
switch (*code)
{
case NE:
- case UNGE:
- case UNGT:
case LTGT:
case ORDERED:
cmp_code = reverse_condition_maybe_unordered (*code);
rtx fp1, fp2;
/* Change the source to SFmode. */
- if (GET_CODE (src) == MEM)
+ if (MEM_P (src))
src = adjust_address (src, SFmode, 0);
- else if (GET_CODE (src) == REG || GET_CODE (src) == SUBREG)
+ else if (REG_P (src) || GET_CODE (src) == SUBREG)
src = gen_rtx_REG (SFmode, true_regnum (src));
fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
rtx slot_address;
compute_frame_size (get_frame_size ());
- if (((cfun->machine->frame.mask >> 31) & 1) == 0)
- abort ();
+ gcc_assert ((cfun->machine->frame.mask >> 31) & 1);
slot_address = mips_add_offset (scratch, stack_pointer_rtx,
cfun->machine->frame.gp_sp_offset);
{
rtx part = adjust_address (src, BLKmode, offset);
if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
- abort ();
+ gcc_unreachable ();
}
}
{
rtx part = adjust_address (dest, BLKmode, offset);
if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
- abort ();
+ gcc_unreachable ();
}
/* Mop up any left-over bytes. */
mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named, struct mips_arg_info *info)
{
- bool even_reg_p;
+ bool doubleword_aligned_p;
unsigned int num_bytes, num_words, max_regs;
/* Work out the size of the argument. */
break;
default:
- abort ();
+ gcc_unreachable ();
}
- /* Now decide whether the argument must go in an even-numbered register.
- Usually this is determined by type alignment, but there are two
- exceptions:
-
- - Under the O64 ABI, the second float argument goes in $f14 if it
- is single precision (doubles go in $f13 as expected).
-
- - Floats passed in FPRs must be in an even-numbered register if
- we're using paired FPRs. */
- if (type)
- even_reg_p = TYPE_ALIGN (type) > BITS_PER_WORD;
- else
- even_reg_p = GET_MODE_UNIT_SIZE (mode) > UNITS_PER_WORD;
-
- if (info->fpr_p)
- {
- if (mips_abi == ABI_O64 && mode == SFmode)
- even_reg_p = true;
- if (FP_INC > 1)
- even_reg_p = true;
- }
+ /* See whether the argument has doubleword alignment. */
+ doubleword_aligned_p = FUNCTION_ARG_BOUNDARY (mode, type) > BITS_PER_WORD;
/* Set REG_OFFSET to the register count we're interested in.
The EABI allocates the floating-point registers separately,
? cum->num_fprs
: cum->num_gprs);
- if (even_reg_p)
+ /* Advance to an even register if the argument is doubleword-aligned. */
+ if (doubleword_aligned_p)
info->reg_offset += info->reg_offset & 1;
- /* The alignment applied to registers is also applied to stack arguments. */
+ /* Work out the offset of a stack argument. */
info->stack_offset = cum->stack_words;
- if (even_reg_p)
+ if (doubleword_aligned_p)
info->stack_offset += info->stack_offset & 1;
max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset;
return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
}
- if (info.fpr_p)
- return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
- else
+ if (!info.fpr_p)
return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
+ else if (info.reg_offset == 1)
+ /* This code handles the special o32 case in which the second word
+ of the argument structure is passed in floating-point registers. */
+ return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC);
+ else
+ return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
}
-/* Implement FUNCTION_ARG_PARTIAL_NREGS. */
+/* Implement TARGET_ARG_PARTIAL_BYTES. */
-int
-function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
- enum machine_mode mode, tree type, int named)
+static int
+mips_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode, tree type, bool named)
{
struct mips_arg_info info;
mips_arg_info (cum, mode, type, named, &info);
- return info.stack_words > 0 ? info.reg_words : 0;
+ return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
}
+/* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least
+ PARM_BOUNDARY bits of alignment, but will be given anything up
+ to STACK_BOUNDARY bits if the type requires it. */
+
+int
+function_arg_boundary (enum machine_mode mode, tree type)
+{
+ unsigned int alignment;
+
+ alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
+ if (alignment < PARM_BOUNDARY)
+ alignment = PARM_BOUNDARY;
+ if (alignment > STACK_BOUNDARY)
+ alignment = STACK_BOUNDARY;
+ return alignment;
+}
+
/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
upward rather than downward. In other words, return true if the
first byte of the stack slot has useful data, false if the last
\f
static void
mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int *pretend_size, int no_rtl)
+ tree type, int *pretend_size ATTRIBUTE_UNUSED,
+ int no_rtl)
{
CUMULATIVE_ARGS local_cum;
int gp_saved, fp_saved;
{
rtx ptr, mem;
- ptr = virtual_incoming_args_rtx;
- switch (mips_abi)
- {
- case ABI_32:
- case ABI_O64:
- ptr = plus_constant (ptr, local_cum.num_gprs * UNITS_PER_WORD);
- break;
-
- case ABI_EABI:
- ptr = plus_constant (ptr, -gp_saved * UNITS_PER_WORD);
- break;
- }
+ ptr = plus_constant (virtual_incoming_args_rtx,
+ REG_PARM_STACK_SPACE (cfun->decl)
+ - gp_saved * UNITS_PER_WORD);
mem = gen_rtx_MEM (BLKmode, ptr);
set_mem_alias_set (mem, get_varargs_alias_set ());
}
}
}
- if (TARGET_OLDABI)
- {
- /* No need for pretend arguments: the register parameter area was
- allocated by the caller. */
- *pretend_size = 0;
- return;
- }
- *pretend_size = (gp_saved * UNITS_PER_WORD) + (fp_saved * UNITS_PER_FPREG);
+ if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
+ cfun->machine->varargs_size = (gp_saved * UNITS_PER_WORD
+ + fp_saved * UNITS_PER_FPREG);
}
/* Create the va_list data type.
void
mips_va_start (tree valist, rtx nextarg)
{
- const CUMULATIVE_ARGS *cum = ¤t_function_args_info;
-
- /* ARG_POINTER_REGNUM is initialized to STACK_POINTER_BOUNDARY, but
- since the stack is aligned for a pair of argument-passing slots,
- and the beginning of a variable argument list may be an odd slot,
- we have to decrease its alignment. */
- if (cfun && cfun->emit->regno_pointer_align)
- while (((current_function_pretend_args_size * BITS_PER_UNIT)
- & (REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) - 1)) != 0)
- REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) /= 2;
-
- if (mips_abi == ABI_EABI)
+ if (EABI_FLOAT_VARARGS_P)
{
+ const CUMULATIVE_ARGS *cum;
+ tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
+ tree ovfl, gtop, ftop, goff, foff;
+ tree t;
int gpr_save_area_size;
+ int fpr_save_area_size;
+ int fpr_offset;
+ cum = ¤t_function_args_info;
gpr_save_area_size
= (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD;
+ fpr_save_area_size
+ = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG;
- if (EABI_FLOAT_VARARGS_P)
- {
- tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
- tree ovfl, gtop, ftop, goff, foff;
- tree t;
- int fpr_offset;
- int fpr_save_area_size;
-
- f_ovfl = TYPE_FIELDS (va_list_type_node);
- f_gtop = TREE_CHAIN (f_ovfl);
- f_ftop = TREE_CHAIN (f_gtop);
- f_goff = TREE_CHAIN (f_ftop);
- f_foff = TREE_CHAIN (f_goff);
-
- ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
- NULL_TREE);
- gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
- NULL_TREE);
- ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
- NULL_TREE);
- goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
- NULL_TREE);
- foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
- NULL_TREE);
-
- /* Emit code to initialize OVFL, which points to the next varargs
- stack argument. CUM->STACK_WORDS gives the number of stack
- words used by named arguments. */
- t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
- if (cum->stack_words > 0)
- t = build (PLUS_EXPR, TREE_TYPE (ovfl), t,
- build_int_cst (NULL_TREE,
- cum->stack_words * UNITS_PER_WORD));
- t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- /* Emit code to initialize GTOP, the top of the GPR save area. */
- t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
- t = build (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- /* Emit code to initialize FTOP, the top of the FPR save area.
- This address is gpr_save_area_bytes below GTOP, rounded
- down to the next fp-aligned boundary. */
- t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
- fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
- fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
- if (fpr_offset)
- t = build (PLUS_EXPR, TREE_TYPE (ftop), t,
- build_int_cst (NULL_TREE, -fpr_offset));
- t = build (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t);
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- /* Emit code to initialize GOFF, the offset from GTOP of the
- next GPR argument. */
- t = build (MODIFY_EXPR, TREE_TYPE (goff), goff,
- build_int_cst (NULL_TREE, gpr_save_area_size));
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- /* Likewise emit code to initialize FOFF, the offset from FTOP
- of the next FPR argument. */
- fpr_save_area_size
- = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG;
- t = build (MODIFY_EXPR, TREE_TYPE (foff), foff,
- build_int_cst (NULL_TREE, fpr_save_area_size));
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
- else
- {
- /* Everything is in the GPR save area, or in the overflow
- area which is contiguous with it. */
- nextarg = plus_constant (nextarg, -gpr_save_area_size);
- std_expand_builtin_va_start (valist, nextarg);
- }
+ f_ovfl = TYPE_FIELDS (va_list_type_node);
+ f_gtop = TREE_CHAIN (f_ovfl);
+ f_ftop = TREE_CHAIN (f_gtop);
+ f_goff = TREE_CHAIN (f_ftop);
+ f_foff = TREE_CHAIN (f_goff);
+
+ ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+ NULL_TREE);
+ gtop = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+ NULL_TREE);
+ ftop = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+ NULL_TREE);
+ goff = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+ NULL_TREE);
+ foff = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+ NULL_TREE);
+
+ /* Emit code to initialize OVFL, which points to the next varargs
+ stack argument. CUM->STACK_WORDS gives the number of stack
+ words used by named arguments. */
+ t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
+ if (cum->stack_words > 0)
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), t,
+ build_int_cst (NULL_TREE,
+ cum->stack_words * UNITS_PER_WORD));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize GTOP, the top of the GPR save area. */
+ t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize FTOP, the top of the FPR save area.
+ This address is gpr_save_area_bytes below GTOP, rounded
+ down to the next fp-aligned boundary. */
+ t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
+ fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
+ fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
+ if (fpr_offset)
+ t = build2 (PLUS_EXPR, TREE_TYPE (ftop), t,
+ build_int_cst (NULL_TREE, -fpr_offset));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize GOFF, the offset from GTOP of the
+ next GPR argument. */
+ t = build2 (MODIFY_EXPR, TREE_TYPE (goff), goff,
+ build_int_cst (NULL_TREE, gpr_save_area_size));
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Likewise emit code to initialize FOFF, the offset from FTOP
+ of the next FPR argument. */
+ t = build2 (MODIFY_EXPR, TREE_TYPE (foff), foff,
+ build_int_cst (NULL_TREE, fpr_save_area_size));
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
else
- std_expand_builtin_va_start (valist, nextarg);
+ {
+ nextarg = plus_constant (nextarg, -cfun->machine->varargs_size);
+ std_expand_builtin_va_start (valist, nextarg);
+ }
}
\f
/* Implement va_arg. */
[1] and [9] can sometimes be optimized away. */
- ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
- NULL_TREE);
+ ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+ NULL_TREE);
if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
{
- top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
- NULL_TREE);
- off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
- NULL_TREE);
+ top = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+ NULL_TREE);
+ off = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+ NULL_TREE);
/* When floating-point registers are saved to the stack,
each one will take up UNITS_PER_HWFPVALUE bytes, regardless
}
else
{
- top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
- NULL_TREE);
- off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
- NULL_TREE);
+ top = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+ NULL_TREE);
+ off = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+ NULL_TREE);
if (rsize > UNITS_PER_WORD)
{
/* [1] Emit code for: off &= -rsize. */
- t = build (BIT_AND_EXPR, TREE_TYPE (off), off,
- build_int_cst (NULL_TREE, -rsize));
- t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (off), off,
+ build_int_cst (NULL_TREE, -rsize));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (off), off, t);
gimplify_and_add (t, pre_p);
}
osize = rsize;
}
/* [2] Emit code to branch if off == 0. */
- t = lang_hooks.truthvalue_conversion (off);
- addr = build (COND_EXPR, ptr_type_node, t, NULL, NULL);
+ t = build2 (NE_EXPR, boolean_type_node, off,
+ build_int_cst (TREE_TYPE (off), 0));
+ addr = build3 (COND_EXPR, ptr_type_node, t, NULL_TREE, NULL_TREE);
/* [5] Emit code for: off -= rsize. We do this as a form of
post-increment not available to C. Also widen for the
coming pointer arithmetic. */
t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
- t = build (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
+ t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
t = fold_convert (sizetype, t);
t = fold_convert (TREE_TYPE (top), t);
/* [4] Emit code for: addr_rtx = top - off. On big endian machines,
the argument has RSIZE - SIZE bytes of leading padding. */
- t = build (MINUS_EXPR, TREE_TYPE (top), top, t);
+ t = build2 (MINUS_EXPR, TREE_TYPE (top), top, t);
if (BYTES_BIG_ENDIAN && rsize > size)
{
u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE,
rsize - size));
- t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
}
COND_EXPR_THEN (addr) = t;
/* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
u = fold_convert (TREE_TYPE (ovfl),
build_int_cst (NULL_TREE, osize - 1));
- t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
u = fold_convert (TREE_TYPE (ovfl),
build_int_cst (NULL_TREE, -osize));
- t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
- align = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
+ align = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
}
else
align = NULL;
the argument has OSIZE - SIZE bytes of leading padding. */
u = fold_convert (TREE_TYPE (ovfl),
build_int_cst (NULL_TREE, osize));
- t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
+ t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
if (BYTES_BIG_ENDIAN && osize > size)
{
u = fold_convert (TREE_TYPE (t),
build_int_cst (NULL_TREE, osize - size));
- t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
}
/* String [9] and [10,11] together. */
if (align)
- t = build (COMPOUND_EXPR, TREE_TYPE (t), align, t);
+ t = build2 (COMPOUND_EXPR, TREE_TYPE (t), align, t);
COND_EXPR_ELSE (addr) = t;
addr = fold_convert (build_pointer_type (type), addr);
- addr = build_fold_indirect_ref (addr);
+ addr = build_va_arg_indirect_ref (addr);
}
if (indirect)
- addr = build_fold_indirect_ref (addr);
+ addr = build_va_arg_indirect_ref (addr);
return addr;
}
left-side instructions (lwl, swl, ldl, sdl).
*RIGHT is a QImode reference to the opposite end of the field and
- can be used in the parterning right-side instruction. */
+ can be used in the patterning right-side instruction. */
static bool
mips_get_unaligned_mem (rtx *op, unsigned int width, int bitpos,
/* Check that the operand really is a MEM. Not all the extv and
extzv predicates are checked. */
- if (GET_CODE (*op) != MEM)
+ if (!MEM_P (*op))
return false;
/* Check that the size is valid. */
}
return true;
}
-\f
-/* Set up globals to generate code for the ISA or processor
- described by INFO. */
-static void
-mips_set_architecture (const struct mips_cpu_info *info)
-{
- if (info != 0)
- {
+/* Return true if (zero_extract OP SIZE POSITION) can be used as the
+ source of an "ext" instruction or the destination of an "ins"
+ instruction. OP must be a register operand and the following
+ conditions must hold:
+
+ 0 <= POSITION < GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < POSITION + SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+
+ Also reject lengths equal to a word as they are better handled
+ by the move patterns. */
+
+bool
+mips_use_ins_ext_p (rtx op, rtx size, rtx position)
+{
+ HOST_WIDE_INT len, pos;
+
+ if (!ISA_HAS_EXT_INS
+ || !register_operand (op, VOIDmode)
+ || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
+ return false;
+
+ len = INTVAL (size);
+ pos = INTVAL (position);
+
+ if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op))
+ || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op)))
+ return false;
+
+ return true;
+}
+
+/* Set up globals to generate code for the ISA or processor
+ described by INFO. */
+
+static void
+mips_set_architecture (const struct mips_cpu_info *info)
+{
+ if (info != 0)
+ {
mips_arch_info = info;
mips_arch = info->cpu;
mips_isa = info->isa;
}
}
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+mips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_mabi_:
+ if (strcmp (arg, "32") == 0)
+ mips_abi = ABI_32;
+ else if (strcmp (arg, "o64") == 0)
+ mips_abi = ABI_O64;
+ else if (strcmp (arg, "n32") == 0)
+ mips_abi = ABI_N32;
+ else if (strcmp (arg, "64") == 0)
+ mips_abi = ABI_64;
+ else if (strcmp (arg, "eabi") == 0)
+ mips_abi = ABI_EABI;
+ else
+ return false;
+ return true;
+
+ case OPT_march_:
+ case OPT_mtune_:
+ return mips_parse_cpu (arg) != 0;
+
+ case OPT_mips:
+ mips_isa_info = mips_parse_cpu (ACONCAT (("mips", arg, NULL)));
+ return mips_isa_info != 0;
+
+ case OPT_mno_flush_func:
+ mips_cache_flush_func = NULL;
+ return true;
+
+ default:
+ return true;
+ }
+}
/* Set up the threshold for data to go into the small data area, instead
of the normal data area, and detect any conflicts in the switches. */
mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
- /* Interpret -mabi. */
- mips_abi = MIPS_ABI_DEFAULT;
- if (mips_abi_string != 0)
- {
- if (strcmp (mips_abi_string, "32") == 0)
- mips_abi = ABI_32;
- else if (strcmp (mips_abi_string, "o64") == 0)
- mips_abi = ABI_O64;
- else if (strcmp (mips_abi_string, "n32") == 0)
- mips_abi = ABI_N32;
- else if (strcmp (mips_abi_string, "64") == 0)
- mips_abi = ABI_64;
- else if (strcmp (mips_abi_string, "eabi") == 0)
- mips_abi = ABI_EABI;
- else
- fatal_error ("bad value (%s) for -mabi= switch", mips_abi_string);
- }
-
/* The following code determines the architecture and register size.
Similar code was added to GAS 2.14 (see tc-mips.c:md_after_parse_args()).
The GAS and GCC code should be kept in sync as much as possible. */
if (mips_arch_string != 0)
- mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
+ mips_set_architecture (mips_parse_cpu (mips_arch_string));
- if (mips_isa_string != 0)
+ if (mips_isa_info != 0)
{
- /* Handle -mipsN. */
- char *whole_isa_str = concat ("mips", mips_isa_string, NULL);
- const struct mips_cpu_info *isa_info;
-
- isa_info = mips_parse_cpu ("-mips option", whole_isa_str);
- free (whole_isa_str);
-
- /* -march takes precedence over -mipsN, since it is more descriptive.
- There's no harm in specifying both as long as the ISA levels
- are the same. */
- if (mips_arch_info != 0 && mips_isa != isa_info->isa)
- error ("-mips%s conflicts with the other architecture options, "
- "which specify a MIPS%d processor",
- mips_isa_string, mips_isa);
-
- /* Set architecture based on the given option. */
- mips_set_architecture (isa_info);
+ if (mips_arch_info == 0)
+ mips_set_architecture (mips_isa_info);
+ else if (mips_arch_info->isa != mips_isa_info->isa)
+ error ("-%s conflicts with the other architecture options, "
+ "which specify a %s processor",
+ mips_isa_info->name,
+ mips_cpu_info_from_isa (mips_arch_info->isa)->name);
}
if (mips_arch_info == 0)
{
#ifdef MIPS_CPU_STRING_DEFAULT
- mips_set_architecture (mips_parse_cpu ("default CPU",
- MIPS_CPU_STRING_DEFAULT));
+ mips_set_architecture (mips_parse_cpu (MIPS_CPU_STRING_DEFAULT));
#else
mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT));
#endif
/* Optimize for mips_arch, unless -mtune selects a different processor. */
if (mips_tune_string != 0)
- mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
+ mips_set_tune (mips_parse_cpu (mips_tune_string));
if (mips_tune_info == 0)
mips_set_tune (mips_arch_info);
+ /* Set cost structure for the processor. */
+ mips_cost = &mips_rtx_cost_data[mips_tune];
+
if ((target_flags_explicit & MASK_64BIT) != 0)
{
/* The user specified the size of the integer registers. Make sure
if ((target_flags_explicit & MASK_LONG64) == 0)
{
- /* If no type size setting options (-mlong64,-mint64,-mlong32)
- were used, then set the type sizes. In the EABI in 64 bit mode,
- longs and pointers are 64 bits. Likewise for the SGI Irix6 N64
- ABI. */
if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64)
target_flags |= MASK_LONG64;
else
target_flags &= ~MASK_BRANCHLIKELY;
}
if (TARGET_BRANCHLIKELY && !ISA_HAS_BRANCHLIKELY)
- warning ("generation of Branch Likely instructions enabled, but not supported by architecture");
+ warning (0, "generation of Branch Likely instructions enabled, but not supported by architecture");
/* The effect of -mabicalls isn't defined for the EABI. */
if (mips_abi == ABI_EABI && TARGET_ABICALLS)
{
flag_pic = 1;
if (mips_section_threshold > 0)
- warning ("-G is incompatible with PIC code which is the default");
+ warning (0, "-G is incompatible with PIC code which is the default");
}
/* mips_split_addresses is a half-way house between explicit
increase register pressure. */
flag_schedule_insns = 0;
+ /* Don't do hot/cold partitioning. The constant layout code expects
+ the whole function to be in a single section. */
+ flag_reorder_blocks_and_partition = 0;
+
/* Silently disable -mexplicit-relocs since it doesn't apply
to mips16 code. Even so, it would overly pedantic to warn
about "-mips16 -mexplicit-relocs", especially given that
/* Make sure that the user didn't turn off paired single support when
MIPS-3D support is requested. */
- if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE)
+ if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE_FLOAT)
&& !TARGET_PAIRED_SINGLE_FLOAT)
error ("-mips3d requires -mpaired-single");
- /* If TARGET_MIPS3D, enable MASK_PAIRED_SINGLE. */
+ /* If TARGET_MIPS3D, enable MASK_PAIRED_SINGLE_FLOAT. */
if (TARGET_MIPS3D)
- target_flags |= MASK_PAIRED_SINGLE;
+ target_flags |= MASK_PAIRED_SINGLE_FLOAT;
/* Make sure that when TARGET_PAIRED_SINGLE_FLOAT is true, TARGET_FLOAT64
and TARGET_HARD_FLOAT are both true. */
if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64)
error ("-mips3d/-mpaired-single must be used with -mips64");
+ if (TARGET_MIPS16 && TARGET_DSP)
+ error ("-mips16 and -mdsp cannot be used together");
+
mips_print_operand_punct['?'] = 1;
mips_print_operand_punct['#'] = 1;
mips_print_operand_punct['/'] = 1;
mips_print_operand_punct['+'] = 1;
mips_print_operand_punct['~'] = 1;
- mips_char_to_class['d'] = TARGET_MIPS16 ? M16_REGS : GR_REGS;
- mips_char_to_class['t'] = T_REG;
- mips_char_to_class['f'] = (TARGET_HARD_FLOAT ? FP_REGS : NO_REGS);
- mips_char_to_class['h'] = HI_REG;
- mips_char_to_class['l'] = LO_REG;
- mips_char_to_class['x'] = MD_REGS;
- mips_char_to_class['b'] = ALL_REGS;
- mips_char_to_class['c'] = (TARGET_ABICALLS ? PIC_FN_ADDR_REG :
- TARGET_MIPS16 ? M16_NA_REGS :
- GR_REGS);
- mips_char_to_class['e'] = LEA_REGS;
- mips_char_to_class['j'] = PIC_FN_ADDR_REG;
- mips_char_to_class['y'] = GR_REGS;
- mips_char_to_class['z'] = ST_REGS;
- mips_char_to_class['B'] = COP0_REGS;
- mips_char_to_class['C'] = COP2_REGS;
- mips_char_to_class['D'] = COP3_REGS;
-
/* Set up array to map GCC register number to debug register number.
Ignore the special purpose register numbers. */
&& size <= UNITS_PER_FPVALUE)
/* Allow integer modes that fit into a single
register. We need to put integers into FPRs
- when using instructions like cvt and trunc. */
- || (class == MODE_INT && size <= UNITS_PER_FPREG)
+ when using instructions like cvt and trunc.
+ We can't allow sizes smaller than a word,
+ the FPU has no appropriate load/store
+ instructions for those. */
+ || (class == MODE_INT
+ && size >= MIN_UNITS_PER_WORD
+ && size <= UNITS_PER_FPREG)
/* Allow TFmode for CCmode reloads. */
|| (ISA_HAS_8CC && mode == TFmode));
- else if (MD_REG_P (regno))
+ else if (ACC_REG_P (regno))
temp = (INTEGRAL_MODE_P (mode)
&& (size <= UNITS_PER_WORD
- || (regno == MD_REG_FIRST
+ || (ACC_HI_REG_P (regno)
&& size == 2 * UNITS_PER_WORD)));
else if (ALL_COP_REG_P (regno))
mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
}
+ /* Thread-local relocation operators. */
+ mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
+ mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
+ mips_split_p[SYMBOL_DTPREL] = 1;
+ mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
+ mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
+ mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
+ mips_split_p[SYMBOL_TPREL] = 1;
+ mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
+ mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
+
+ /* We don't have a thread pointer access instruction on MIPS16, or
+ appropriate TLS relocations. */
+ if (TARGET_MIPS16)
+ targetm.have_tls = false;
+
/* Default to working around R4000 errata only if the processor
was selected explicitly. */
if ((target_flags_explicit & MASK_FIX_R4000) == 0
void
mips_conditional_register_usage (void)
{
+ if (!TARGET_DSP)
+ {
+ int regno;
+
+ for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ }
if (!TARGET_HARD_FLOAT)
{
int regno;
return offset;
}
\f
-/* A helper function for print_operand. This prints out a floating point
- condition code register. OP is the operand we are printing. CODE is the
- rtx code of OP. ALIGN is the required register alignment for OP. OFFSET
- is the index into operand for multiple register operands. If IGNORE is
- true, then we only print the register name if it isn't fcc0, and we
- follow it with a comma. */
-
-static void
-print_fcc_operand (FILE *file, rtx op, enum rtx_code code,
- int align, int offset, int ignore)
-{
- int regnum;
-
- if (code != REG)
- abort ();
-
- regnum = REGNO (op);
- if (!ST_REG_P (regnum)
- || (regnum - ST_REG_FIRST) % align != 0)
- abort ();
-
- if (!ignore || regnum != ST_REG_FIRST)
- fprintf (file, "%s%s", reg_names[regnum+offset], (ignore ? "," : ""));
-}
-
/* Implement the PRINT_OPERAND macro. The MIPS-specific operand codes are:
'X' OP is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
'T' print 'f' for (eq:CC ...), 't' for (ne:CC ...),
'z' for (eq:?I ...), 'n' for (ne:?I ...).
't' like 'T', but with the EQ/NE cases reversed
- 'Z' print register and a comma, but print nothing for $fcc0
+ 'Y' for a CONST_INT X, print mips_fp_conditions[X]
+ 'Z' print the operand and a comma for ISA_HAS_8CC, otherwise print nothing
'R' print the reloc associated with LO_SUM
- 'V' Check if the fcc register number divided by 4 is zero. Then print
- the fcc register plus 2.
- 'v' Check if the fcc register number divided by 4 is zero. Then print
- the fcc register.
- 'Q' print the fcc register.
+ 'q' print DSP accumulator registers
The punctuation characters are:
else if (letter == 'R')
print_operand_reloc (file, op, mips_lo_relocs);
+ else if (letter == 'Y')
+ {
+ if (GET_CODE (op) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (op)
+ < ARRAY_SIZE (mips_fp_conditions)))
+ fputs (mips_fp_conditions[INTVAL (op)], file);
+ else
+ output_operand_lossage ("invalid %%Y value");
+ }
+
else if (letter == 'Z')
- print_fcc_operand (file, op, code, 1, 0, 1);
+ {
+ if (ISA_HAS_8CC)
+ {
+ print_operand (file, op, 0);
+ fputc (',', file);
+ }
+ }
- else if (letter == 'V')
- print_fcc_operand (file, op, code, 4, 2, 0);
+ else if (letter == 'q')
+ {
+ int regnum;
- else if (letter == 'v')
- print_fcc_operand (file, op, code, 4, 0, 0);
+ if (code != REG)
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
- else if (letter == 'Q')
- print_fcc_operand (file, op, code, 1, 0, 0);
+ regnum = REGNO (op);
+ if (MD_REG_P (regnum))
+ fprintf (file, "$ac0");
+ else if (DSP_ACC_REG_P (regnum))
+ fprintf (file, "$ac%c", reg_names[regnum][3]);
+ else
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
+ }
else if (code == REG || code == SUBREG)
{
output_addr_const (file, x);
return;
}
- abort ();
+ gcc_unreachable ();
}
\f
/* When using assembler macros, keep track of all of small-data externs
void
mips_output_filename (FILE *stream, const char *name)
{
- char ltext_label_name[100];
/* If we are emitting DWARF-2, let dwarf2out handle the ".file"
directives. */
mips_output_filename_first_time = 0;
num_source_filenames += 1;
current_function_file = name;
- ASM_OUTPUT_FILENAME (stream, num_source_filenames, name);
+ fprintf (stream, "\t.file\t%d ", num_source_filenames);
+ output_quoted_string (stream, name);
+ putc ('\n', stream);
}
+ /* If we are emitting stabs, let dbxout.c handle this (except for
+ the mips_output_filename_first_time case). */
else if (write_symbols == DBX_DEBUG)
- {
- ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
- fputs ("\t.stabs\t", stream);
- output_quoted_string (stream, name);
- fprintf (stream, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]);
- }
+ return;
else if (name != current_function_file
&& strcmp (name, current_function_file) != 0)
{
num_source_filenames += 1;
current_function_file = name;
- ASM_OUTPUT_FILENAME (stream, num_source_filenames, name);
- }
-}
-\f
-/* Emit a linenumber. For encapsulated stabs, we need to put out a stab
- as well as a .loc, since it is possible that MIPS ECOFF might not be
- able to represent the location for inlines that come from a different
- file. */
-
-void
-mips_output_lineno (FILE *stream, int line)
-{
- if (write_symbols == DBX_DEBUG)
- {
- ++sym_lineno;
- fprintf (stream, "%sLM%d:\n\t.stabn\t%d,0,%d,%sLM%d\n",
- LOCAL_LABEL_PREFIX, sym_lineno, N_SLINE, line,
- LOCAL_LABEL_PREFIX, sym_lineno);
- }
- else
- {
- fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
+ fprintf (stream, "\t.file\t%d ", num_source_filenames);
+ output_quoted_string (stream, name);
+ putc ('\n', stream);
}
}
\f
{
register int c = string[i];
- switch (c)
+ if (ISPRINT (c))
{
- case '\"':
- case '\\':
- putc ('\\', stream);
- putc (c, stream);
- cur_pos += 2;
- break;
-
- case TARGET_NEWLINE:
- fputs ("\\n", stream);
- if (i+1 < len
- && (((c = string[i+1]) >= '\040' && c <= '~')
- || c == TARGET_TAB))
- cur_pos = 32767; /* break right here */
- else
- cur_pos += 2;
- break;
-
- case TARGET_TAB:
- fputs ("\\t", stream);
- cur_pos += 2;
- break;
-
- case TARGET_FF:
- fputs ("\\f", stream);
- cur_pos += 2;
- break;
-
- case TARGET_BS:
- fputs ("\\b", stream);
- cur_pos += 2;
- break;
-
- case TARGET_CR:
- fputs ("\\r", stream);
- cur_pos += 2;
- break;
-
- default:
- if (c >= ' ' && c < 0177)
+ if (c == '\\' || c == '\"')
{
- putc (c, stream);
+ putc ('\\', stream);
cur_pos++;
}
- else
- {
- fprintf (stream, "\\%03o", c);
- cur_pos += 4;
- }
+ putc (c, stream);
+ cur_pos++;
+ }
+ else
+ {
+ fprintf (stream, "\\%03o", c);
+ cur_pos += 4;
}
if (cur_pos > 72 && i+1 < len)
case ABI_O64: abi_string = "abiO64"; break;
case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
default:
- abort ();
+ gcc_unreachable ();
}
- /* Note - we use fprintf directly rather than called named_section()
+ /* Note - we use fprintf directly rather than calling switch_to_section
because in this way we can avoid creating an allocated section. We
do not want this section to take up any space in the running
executable. */
extern tree last_assemble_variable_decl;
if (mips_in_small_data_p (decl))
- named_section (0, ".sbss", 0);
+ switch_to_section (get_named_section (NULL, ".sbss", 0));
else
- bss_section ();
+ switch_to_section (bss_section);
ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
last_assemble_variable_decl = decl;
ASM_DECLARE_OBJECT_NAME (stream, name, decl);
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
targetm.asm_out.globalize_label (stream, name);
- readonly_data_section ();
+ switch_to_section (readonly_data_section);
ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
mips_declare_object (stream, name, "",
":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
}
- mips_declare_object (stream, name, "", ":\n", 0);
+ mips_declare_object (stream, name, "", ":\n");
}
/* Implement ASM_FINISH_DECLARE_OBJECT. This is generic ELF stuff. */
/* Return the bytes needed to compute the frame pointer from the current
stack pointer. SIZE is the size (in bytes) of the local variables.
- Mips stack frames look like:
+ MIPS stack frames look like:
Before call After call
+-----------------------+ +-----------------------+
gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size);
total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size);
- /* Add in space reserved on the stack by the callee for storing arguments
- passed in registers. */
- if (!TARGET_OLDABI)
- total_size += MIPS_STACK_ALIGN (current_function_pretend_args_size);
+ /* Add in the space required for saving incoming register arguments. */
+ total_size += current_function_pretend_args_size;
+ total_size += MIPS_STACK_ALIGN (cfun->machine->varargs_size);
/* Save other computed information. */
cfun->machine->frame.total_size = total_size;
break;
case ARG_POINTER_REGNUM:
- offset = cfun->machine->frame.total_size;
- if (TARGET_NEWABI)
- offset -= current_function_pretend_args_size;
+ offset = (cfun->machine->frame.total_size
+ - current_function_pretend_args_size);
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM)
#ifdef SDB_DEBUGGING_INFO
if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG)
- ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl), 0);
+ SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
#endif
/* In mips16 mode, we may need to generate a 32 bit to handle
static rtx
mips_frame_set (rtx mem, rtx reg)
{
- rtx set = gen_rtx_SET (VOIDmode, mem, reg);
+ rtx set;
+
+ /* If we're saving the return address register and the dwarf return
+ address column differs from the hard register number, adjust the
+ note reg to refer to the former. */
+ if (REGNO (reg) == GP_REG_FIRST + 31
+ && DWARF_FRAME_RETURN_COLUMN != GP_REG_FIRST + 31)
+ reg = gen_rtx_REG (GET_MODE (reg), DWARF_FRAME_RETURN_COLUMN);
+
+ set = gen_rtx_SET (VOIDmode, mem, reg);
RTX_FRAME_RELATED_P (set) = 1;
+
return set;
}
from the stack pointer, so use the frame pointer as a
temporary. We should always be using a frame pointer
in this case anyway. */
- if (!frame_pointer_needed)
- abort ();
-
+ gcc_assert (frame_pointer_needed);
emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
emit_insn (gen_sub3_insn (hard_frame_pointer_rtx,
hard_frame_pointer_rtx,
if (TARGET_MIPS16 && cfun->machine->frame.args_size != 0)
{
rtx offset = GEN_INT (cfun->machine->frame.args_size);
- RTX_FRAME_RELATED_P
- (emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
- stack_pointer_rtx,
- offset))) = 1;
+ if (SMALL_OPERAND (cfun->machine->frame.args_size))
+ RTX_FRAME_RELATED_P
+ (emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ offset))) = 1;
+ else
+ {
+ emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), offset);
+ emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx,
+ MIPS_PROLOGUE_TEMP (Pmode)));
+ mips_set_frame_expr
+ (gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
+ plus_constant (stack_pointer_rtx,
+ cfun->machine->frame.args_size)));
+ }
}
else
RTX_FRAME_RELATED_P (emit_move_insn (hard_frame_pointer_rtx,
mips16_lay_out_constants ();
shorten_branches (insn);
final_start_function (insn, file, 1);
- final (insn, file, 1, 0);
+ final (insn, file, 1);
final_end_function ();
/* Clean up the vars set above. Note that final_end_function resets
/* Choose the section to use for the constant rtx expression X that has
mode MODE. */
-static void
+static section *
mips_select_rtx_section (enum machine_mode mode, rtx x,
unsigned HOST_WIDE_INT align)
{
/* In mips16 mode, the constant table always goes in the same section
as the function, so that constants can be loaded using PC relative
addressing. */
- function_section (current_function_decl);
+ return function_section (current_function_decl);
}
else if (TARGET_EMBEDDED_DATA)
{
/* For embedded applications, always put constants in read-only data,
in order to reduce RAM usage. */
- mergeable_constant_section (mode, align, 0);
+ return mergeable_constant_section (mode, align, 0);
}
else
{
if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold
&& mips_section_threshold > 0)
- named_section (0, ".sdata", 0);
+ return get_named_section (NULL, ".sdata", 0);
else if (flag_pic && symbolic_expression_p (x))
- named_section (0, ".data.rel.ro", 3);
+ return get_named_section (NULL, ".data.rel.ro", 3);
else
- mergeable_constant_section (mode, align, 0);
+ return mergeable_constant_section (mode, align, 0);
}
}
+/* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
+
+ The complication here is that, with the combination TARGET_ABICALLS
+ && !TARGET_GPWORD, jump tables will use absolute addresses, and should
+ therefore not be included in the read-only part of a DSO. Handle such
+ cases by selecting a normal data section instead of a read-only one.
+ The logic apes that in default_function_rodata_section. */
+
+static section *
+mips_function_rodata_section (tree decl)
+{
+ if (!TARGET_ABICALLS || TARGET_GPWORD)
+ return default_function_rodata_section (decl);
+
+ if (decl && DECL_SECTION_NAME (decl))
+ {
+ const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+ {
+ char *rname = ASTRDUP (name);
+ rname[14] = 'd';
+ return get_section (rname, SECTION_LINKONCE | SECTION_WRITE, decl);
+ }
+ else if (flag_function_sections && flag_data_sections
+ && strncmp (name, ".text.", 6) == 0)
+ {
+ char *rname = ASTRDUP (name);
+ memcpy (rname + 1, "data", 4);
+ return get_section (rname, SECTION_WRITE, decl);
+ }
+ }
+ return data_section;
+}
+
/* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
access DECL using %gp_rel(...)($gp). */
mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
}
}
+
+ /* For EABI, the class of return register depends entirely on MODE.
+ For example, "struct { some_type x; }" and "union { some_type x; }"
+ are returned in the same way as a bare "some_type" would be.
+ Other ABIs only use FPRs for scalar, complex or vector types. */
+ if (mips_abi != ABI_EABI && !FLOAT_TYPE_P (valtype))
+ return gen_rtx_REG (mode, GP_RETURN);
}
if ((GET_MODE_CLASS (mode) == MODE_FLOAT
}
}
-/* Return the class of registers for which a mode change from FROM to TO
- is invalid.
-
- In little-endian mode, the hi-lo registers are numbered backwards,
- so (subreg:SI (reg:DI hi) 0) gets the high word instead of the low
- word as intended.
-
- Similarly, when using paired floating-point registers, the first
- register holds the low word, regardless of endianness. So in big
- endian mode, (subreg:SI (reg:DF $f0) 0) does not get the high word
- as intended.
+static bool
+mips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED, bool named)
+{
+ return mips_abi == ABI_EABI && named;
+}
- Also, loading a 32-bit value into a 64-bit floating-point register
- will not sign-extend the value, despite what LOAD_EXTEND_OP says.
- We can't allow 64-bit float registers to change from a 32-bit
- mode to a 64-bit mode. */
+/* Return true if registers of class CLASS cannot change from mode FROM
+ to mode TO. */
bool
mips_cannot_change_mode_class (enum machine_mode from,
enum machine_mode to, enum reg_class class)
{
- if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
+ if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD
+ && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS_PER_WORD)
{
if (TARGET_BIG_ENDIAN)
- return reg_classes_intersect_p (FP_REGS, class);
- if (TARGET_FLOAT64)
- return reg_classes_intersect_p (HI_AND_FP_REGS, class);
- return reg_classes_intersect_p (HI_REG, class);
+ {
+ /* When a multi-word value is stored in paired floating-point
+ registers, the first register always holds the low word.
+ We therefore can't allow FPRs to change between single-word
+ and multi-word modes. */
+ if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
+ return true;
+ }
+ else
+ {
+ /* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored
+ in LO and HI, the high word always comes first. We therefore
+ can't allow values stored in HI to change between single-word
+ and multi-word modes.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_classes_intersect_p (ACC_REGS, class))
+ return true;
+ }
}
+ /* Loading a 32-bit value into a 64-bit floating-point register
+ will not sign-extend the value, despite what LOAD_EXTEND_OP says.
+ We can't allow 64-bit float registers to change from SImode to
+ to a wider mode. */
+ if (TARGET_FLOAT64
+ && from == SImode
+ && GET_MODE_SIZE (to) >= UNITS_PER_WORD
+ && reg_classes_intersect_p (FP_REGS, class))
+ return true;
return false;
}
int regno = -1;
int gp_reg_p;
- if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
+ if (REG_P (x)|| GET_CODE (x) == SUBREG)
regno = true_regnum (x);
gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
}
/* Copying from HI or LO to anywhere other than a general register
- requires a general register. */
- if (class == HI_REG || class == LO_REG || class == MD_REGS)
+ requires a general register.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_class_subset_p (class, ACC_REGS))
{
if (TARGET_MIPS16 && in_p)
{
}
return gp_reg_p ? NO_REGS : gr_regs;
}
- if (MD_REG_P (regno))
+ if (ACC_REG_P (regno))
{
if (TARGET_MIPS16 && ! in_p)
{
if (class == FP_REGS)
{
- if (GET_CODE (x) == MEM)
+ if (MEM_P (x))
{
/* In this case we can use lwc1, swc1, ldc1 or sdc1. */
return NO_REGS;
return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
}
-bool
+static bool
mips_valid_pointer_mode (enum machine_mode mode)
{
return (mode == SImode || (TARGET_64BIT && mode == DImode));
}
/* Target hook for vector_mode_supported_p. */
+
static bool
mips_vector_mode_supported_p (enum machine_mode mode)
{
- if (mode == V2SFmode && TARGET_PAIRED_SINGLE_FLOAT)
- return true;
- else
- return false;
+ switch (mode)
+ {
+ case V2SFmode:
+ return TARGET_PAIRED_SINGLE_FLOAT;
+
+ case V2HImode:
+ case V4QImode:
+ return TARGET_DSP;
+
+ default:
+ return false;
+ }
}
\f
/* If we can access small data directly (using gp-relative relocation
/* We need to emit the initialization after the FUNCTION_BEG
note, so that it will be integrated. */
for (scan = get_insns (); scan != NULL_RTX; scan = NEXT_INSN (scan))
- if (GET_CODE (scan) == NOTE
+ if (NOTE_P (scan)
&& NOTE_LINE_NUMBER (scan) == NOTE_INSN_FUNCTION_BEG)
break;
if (scan == NULL_RTX)
unsigned int f;
/* This code only works for the original 32 bit ABI and the O64 ABI. */
- if (!TARGET_OLDABI)
- abort ();
+ gcc_assert (TARGET_OLDABI);
if (from_fp_p)
s = "mfc1";
}
}
else
- abort ();
+ gcc_unreachable ();
++gparg;
++fparg;
fprintf (file, ")\n");
fprintf (file, "\t.set\tnomips16\n");
- function_section (stubdecl);
+ switch_to_section (function_section (stubdecl));
ASM_OUTPUT_ALIGN (file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
/* ??? If FUNCTION_NAME_ALREADY_DECLARED is defined, then we are
fprintf (file, "\t.set\tmips16\n");
- function_section (current_function_decl);
+ switch_to_section (function_section (current_function_decl));
}
/* We keep a list of functions for which we have already built stubs
/* This code will only work for o32 and o64 abis. The other ABI's
require more sophisticated support. */
- if (!TARGET_OLDABI)
- abort ();
+ gcc_assert (TARGET_OLDABI);
/* We can only handle SFmode and DFmode floating point return
values. */
- if (fpret && GET_MODE (retval) != SFmode && GET_MODE (retval) != DFmode)
- abort ();
+ if (fpret)
+ gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode);
/* If we're calling via a function pointer, then we must always call
via a stub. There are magic stubs provided in libgcc.a for each
insn = emit_call_insn (insn);
/* Put the register usage information on the CALL. */
- if (GET_CODE (insn) != CALL_INSN)
- abort ();
CALL_INSN_FUNCTION_USAGE (insn) =
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 2)),
Fortunately, this case is illegal, since it means that a function
was declared in two different ways in a single compilation. */
if (fpret && ! l->fpret)
- error ("cannot handle inconsistent calls to `%s'", fnname);
+ error ("cannot handle inconsistent calls to %qs", fnname);
/* If we are calling a stub which handles a floating point return
value, we need to arrange to save $18 in the prologue. We do
insn = gen_call_value_internal (retval, fn, arg_size);
insn = emit_call_insn (insn);
- if (GET_CODE (insn) != CALL_INSN)
- abort ();
-
CALL_INSN_FUNCTION_USAGE (insn) =
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
}
default:
- abort ();
+ gcc_unreachable ();
}
}
emit_barrier_after (insn);
}
-/* Return the length of instruction INSN.
-
- ??? MIPS16 switch tables go in .text, but we don't define
- JUMP_TABLES_IN_TEXT_SECTION, so get_attr_length will not
- compute their lengths correctly. */
+/* Return the length of instruction INSN. */
static int
mips16_insn_length (rtx insn)
{
- if (GET_CODE (insn) == JUMP_INSN)
+ if (JUMP_P (insn))
{
rtx body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC)
first = SEQ_BEGIN (insn);
second = SEQ_END (insn);
- if (GET_CODE (first) == JUMP_INSN
- && GET_CODE (second) == INSN
+ if (JUMP_P (first)
+ && NONJUMP_INSN_P (second)
&& GET_CODE (PATTERN (first)) == SET
&& GET_CODE (SET_DEST (PATTERN (first))) == PC
&& GET_CODE (SET_SRC (PATTERN (first))) == IF_THEN_ELSE)
way, if the nop makes Y aligned, it will also align any labels
between X and Y. */
if (state.insns_left != state.issue_rate
- && GET_CODE (subinsn) != CALL_INSN)
+ && !CALL_P (subinsn))
{
if (subinsn == SEQ_BEGIN (insn) && aligned_p)
{
mips.md patern, the length is only an estimate. Insert an
8 byte alignment after it so that the following instructions
can be handled correctly. */
- if (GET_CODE (SEQ_BEGIN (insn)) == INSN
+ if (NONJUMP_INSN_P (SEQ_BEGIN (insn))
&& (recog_memoized (insn) < 0 || length >= 8))
{
next = emit_insn_after (gen_align (GEN_INT (3)), insn);
case HAZARD_DELAY:
set = single_set (insn);
- if (set == 0)
- abort ();
+ gcc_assert (set != 0);
*delayed_reg = SET_DEST (set);
break;
}
cfun->machine->ignore_hazard_length_p = true;
shorten_branches (get_insns ());
- /* The profiler code uses assembler macros. -mfix-vr4120 relies on
- assembler nop insertion. */
- cfun->machine->all_noreorder_p = (!current_function_profile
- && !TARGET_FIX_VR4120);
+ cfun->machine->all_noreorder_p = true;
+
+ /* Profiled functions can't be all noreorder because the profiler
+ support uses assembler macros. */
+ if (current_function_profile)
+ cfun->machine->all_noreorder_p = false;
+
+ /* Code compiled with -mfix-vr4120 can't be all noreorder because
+ we rely on the assembler to work around some errata. */
+ if (TARGET_FIX_VR4120)
+ cfun->machine->all_noreorder_p = false;
+
+ /* The same is true for -mfix-vr4130 if we might generate mflo or
+ mfhi instructions. Note that we avoid using mflo and mfhi if
+ the VR4130 macc and dmacc instructions are available instead;
+ see the *mfhilo_{si,di}_macc patterns. */
+ if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
+ cfun->machine->all_noreorder_p = false;
last_insn = 0;
hilo_delay = 2;
else if (TARGET_EXPLICIT_RELOCS)
{
if (mips_flag_delayed_branch)
- dbr_schedule (get_insns (), dump_file);
+ dbr_schedule (get_insns ());
mips_avoid_hazards ();
if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
vr4130_align_insns ();
}
else if (to == FP_REGS)
return 4;
- else if (to == HI_REG || to == LO_REG || to == MD_REGS)
+ else if (reg_class_subset_p (to, ACC_REGS))
{
if (TARGET_MIPS16)
return 12;
{
return 5;
}
- } /* GR_REG_CLASS_P (from) */
+ }
else if (from == FP_REGS)
{
if (GR_REG_CLASS_P (to))
return 2;
else if (to == ST_REGS)
return 8;
- } /* from == FP_REGS */
- else if (from == HI_REG || from == LO_REG || from == MD_REGS)
+ }
+ else if (reg_class_subset_p (from, ACC_REGS))
{
if (GR_REG_CLASS_P (to))
{
else
return 6;
}
- } /* from == HI_REG, etc. */
+ }
else if (from == ST_REGS && GR_REG_CLASS_P (to))
return 4;
else if (COP_REG_CLASS_P (from))
{
return 5;
- } /* COP_REG_CLASS_P (from) */
+ }
- /* Fall through. */
+ /* Fall through.
+ ??? What cases are these? Shouldn't we return 2 here? */
return 12;
}
/* Output delay slot instruction. */
rtx insn = final_sequence;
final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
- optimize, 0, 1, NULL);
+ optimize, 1, NULL);
INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
}
else
/* Output delay slot instruction. */
rtx insn = final_sequence;
final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
- optimize, 0, 1, NULL);
+ optimize, 1, NULL);
INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
}
else
}
default:
- abort ();
+ gcc_unreachable ();
}
/* NOTREACHED */
output_asm_insn (s, operands);
s = "bnez\t%2,1f\n\tbreak\t7\n1:";
}
+ else if (GENERATE_DIVIDE_TRAPS)
+ {
+ output_asm_insn (s, operands);
+ s = "teq\t%2,%.,7";
+ }
else
{
output_asm_insn ("%(bne\t%2,%.,1f", operands);
}
-/* Parse an option that takes the name of a processor as its argument.
- OPTION is the name of the option and CPU_STRING is the argument.
- Return the corresponding processor enumeration if the CPU_STRING is
- recognized, otherwise report an error and return null.
+/* Return the mips_cpu_info entry for the processor or ISA given
+ by CPU_STRING. Return null if the string isn't recognized.
A similar function exists in GAS. */
static const struct mips_cpu_info *
-mips_parse_cpu (const char *option, const char *cpu_string)
+mips_parse_cpu (const char *cpu_string)
{
const struct mips_cpu_info *p;
const char *s;
for (s = cpu_string; *s != 0; s++)
if (ISUPPER (*s))
{
- warning ("the cpu name must be lower case");
+ warning (0, "the cpu name must be lower case");
break;
}
if (mips_matching_cpu_name_p (p->name, cpu_string))
return p;
- error ("bad value (%s) for %s", cpu_string, option);
return 0;
}
default:
return 1;
}
-
- abort ();
-
}
/* Implements TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should
struct builtin_description
{
- /* Instruction code. */
+ /* The code of the main .md file instruction. See mips_builtin_type
+ for more information. */
enum insn_code icode;
- /* Builtin function name. */
- const char *name;
- /* Builtin code. */
- enum mips_builtins code;
- /* Function type. */
- enum mips_function_type ftype;
- /* The target flag required for this builtin function. */
- int target_flags;
+
+ /* The floating-point comparison code to use with ICODE, if any. */
+ enum mips_fp_condition cond;
+
+ /* The name of the builtin function. */
+ const char *name;
+
+ /* Specifies how the function should be expanded. */
+ enum mips_builtin_type builtin_type;
+
+ /* The function's prototype. */
+ enum mips_function_type function_type;
+
+ /* The target flags required for this function. */
+ int target_flags;
};
-/* NOTE: The order of mips_bdesc[] must be the same as the order of
- enum mips_builtins{} in mips.h. */
+/* Define a MIPS_BUILTIN_DIRECT function for instruction CODE_FOR_mips_<INSN>.
+ FUNCTION_TYPE and TARGET_FLAGS are builtin_description fields. */
+#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
+ MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, TARGET_FLAGS }
+
+/* Define __builtin_mips_<INSN>_<COND>_{s,d}, both of which require
+ TARGET_FLAGS. */
+#define CMP_SCALAR_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_" #INSN "_" #COND "_s", \
+ MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_SF_SF, TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_d, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_" #INSN "_" #COND "_d", \
+ MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_DF_DF, TARGET_FLAGS }
+
+/* Define __builtin_mips_{any,all,upper,lower}_<INSN>_<COND>_ps.
+ The lower and upper forms require TARGET_FLAGS while the any and all
+ forms require MASK_MIPS3D. */
+#define CMP_PS_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_any_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_all_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_lower_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_LOWER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_upper_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_UPPER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }
+
+/* Define __builtin_mips_{any,all}_<INSN>_<COND>_4s. The functions
+ require MASK_MIPS3D. */
+#define CMP_4S_BUILTINS(INSN, COND) \
+ { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_any_" #INSN "_" #COND "_4s", \
+ MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_all_" #INSN "_" #COND "_4s", \
+ MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ MASK_MIPS3D }
+
+/* Define __builtin_mips_mov{t,f}_<INSN>_<COND>_ps. The comparison
+ instruction requires TARGET_FLAGS. */
+#define MOVTF_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_movt_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_MOVT, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_movf_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_MOVF, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ TARGET_FLAGS }
+
+/* Define all the builtins related to c.cond.fmt condition COND. */
+#define CMP_BUILTINS(COND) \
+ MOVTF_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
+ MOVTF_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_SCALAR_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_PS_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
+ CMP_PS_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_4S_BUILTINS (c, COND), \
+ CMP_4S_BUILTINS (cabs, COND)
+
+/* __builtin_mips_abs_ps() maps to the standard absM2 pattern. */
+#define CODE_FOR_mips_abs_ps CODE_FOR_absv2sf2
+
static const struct builtin_description mips_bdesc[] =
{
- { CODE_FOR_mips_pll_ps, "__builtin_mips_pll_ps", MIPS_BUILTIN_PLL_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_pul_ps, "__builtin_mips_pul_ps", MIPS_BUILTIN_PUL_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_plu_ps, "__builtin_mips_plu_ps", MIPS_BUILTIN_PLU_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_puu_ps, "__builtin_mips_puu_ps", MIPS_BUILTIN_PUU_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_cvt_ps_s, "__builtin_mips_cvt_ps_s", MIPS_BUILTIN_CVT_PS_S,
- MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_cvt_s_pl, "__builtin_mips_cvt_s_pl", MIPS_BUILTIN_CVT_S_PL,
- MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_cvt_s_pu, "__builtin_mips_cvt_s_pu", MIPS_BUILTIN_CVT_S_PU,
- MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_absv2sf2, "__builtin_mips_abs_ps", MIPS_BUILTIN_ABS_PS,
- MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_alnv_ps, "__builtin_mips_alnv_ps", MIPS_BUILTIN_ALNV_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF_INT, MASK_PAIRED_SINGLE },
-
- { CODE_FOR_mips_addr_ps, "__builtin_mips_addr_ps", MIPS_BUILTIN_ADDR_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_mulr_ps, "__builtin_mips_mulr_ps", MIPS_BUILTIN_MULR_PS,
- MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cvt_pw_ps, "__builtin_mips_cvt_pw_ps",
- MIPS_BUILTIN_CVT_PW_PS, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cvt_ps_pw, "__builtin_mips_cvt_ps_pw",
- MIPS_BUILTIN_CVT_PS_PW, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D },
-
- { CODE_FOR_mips_recip1_s, "__builtin_mips_recip1_s", MIPS_BUILTIN_RECIP1_S,
- MIPS_SF_FTYPE_SF, MASK_MIPS3D },
- { CODE_FOR_mips_recip1_d, "__builtin_mips_recip1_d", MIPS_BUILTIN_RECIP1_D,
- MIPS_DF_FTYPE_DF, MASK_MIPS3D },
- { CODE_FOR_mips_recip1_ps, "__builtin_mips_recip1_ps",
- MIPS_BUILTIN_RECIP1_PS, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_recip2_s, "__builtin_mips_recip2_s", MIPS_BUILTIN_RECIP2_S,
- MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_recip2_d, "__builtin_mips_recip2_d", MIPS_BUILTIN_RECIP2_D,
- MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_recip2_ps, "__builtin_mips_recip2_ps",
- MIPS_BUILTIN_RECIP2_PS, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D },
-
- { CODE_FOR_mips_rsqrt1_s, "__builtin_mips_rsqrt1_s", MIPS_BUILTIN_RSQRT1_S,
- MIPS_SF_FTYPE_SF, MASK_MIPS3D },
- { CODE_FOR_mips_rsqrt1_d, "__builtin_mips_rsqrt1_d", MIPS_BUILTIN_RSQRT1_D,
- MIPS_DF_FTYPE_DF, MASK_MIPS3D },
- { CODE_FOR_mips_rsqrt1_ps, "__builtin_mips_rsqrt1_ps",
- MIPS_BUILTIN_RSQRT1_PS, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_rsqrt2_s, "__builtin_mips_rsqrt2_s", MIPS_BUILTIN_RSQRT2_S,
- MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_rsqrt2_d, "__builtin_mips_rsqrt2_d", MIPS_BUILTIN_RSQRT2_D,
- MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_rsqrt2_ps, "__builtin_mips_rsqrt2_ps",
- MIPS_BUILTIN_RSQRT2_PS, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D },
-
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_any_c_f_ps", MIPS_BUILTIN_ANY_C_F_PS,
- MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_upper_c_f_ps",
- MIPS_BUILTIN_UPPER_C_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_lower_c_f_ps",
- MIPS_BUILTIN_LOWER_C_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_all_c_f_ps", MIPS_BUILTIN_ALL_C_F_PS,
- MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_any_c_un_ps",
- MIPS_BUILTIN_ANY_C_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_upper_c_un_ps",
- MIPS_BUILTIN_UPPER_C_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_lower_c_un_ps",
- MIPS_BUILTIN_LOWER_C_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_all_c_un_ps",
- MIPS_BUILTIN_ALL_C_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_any_c_eq_ps",
- MIPS_BUILTIN_ANY_C_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_upper_c_eq_ps",
- MIPS_BUILTIN_UPPER_C_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_lower_c_eq_ps",
- MIPS_BUILTIN_LOWER_C_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_all_c_eq_ps",
- MIPS_BUILTIN_ALL_C_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_any_c_ueq_ps",
- MIPS_BUILTIN_ANY_C_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_upper_c_ueq_ps",
- MIPS_BUILTIN_UPPER_C_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_lower_c_ueq_ps",
- MIPS_BUILTIN_LOWER_C_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_all_c_ueq_ps",
- MIPS_BUILTIN_ALL_C_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_any_c_olt_ps",
- MIPS_BUILTIN_ANY_C_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_upper_c_olt_ps",
- MIPS_BUILTIN_UPPER_C_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_lower_c_olt_ps",
- MIPS_BUILTIN_LOWER_C_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_all_c_olt_ps",
- MIPS_BUILTIN_ALL_C_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_any_c_ult_ps",
- MIPS_BUILTIN_ANY_C_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_upper_c_ult_ps",
- MIPS_BUILTIN_UPPER_C_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_lower_c_ult_ps",
- MIPS_BUILTIN_LOWER_C_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_all_c_ult_ps",
- MIPS_BUILTIN_ALL_C_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_any_c_ole_ps",
- MIPS_BUILTIN_ANY_C_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_upper_c_ole_ps",
- MIPS_BUILTIN_UPPER_C_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_lower_c_ole_ps",
- MIPS_BUILTIN_LOWER_C_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_all_c_ole_ps",
- MIPS_BUILTIN_ALL_C_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_any_c_ule_ps",
- MIPS_BUILTIN_ANY_C_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_upper_c_ule_ps",
- MIPS_BUILTIN_UPPER_C_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_lower_c_ule_ps",
- MIPS_BUILTIN_LOWER_C_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_all_c_ule_ps",
- MIPS_BUILTIN_ALL_C_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_any_c_sf_ps",
- MIPS_BUILTIN_ANY_C_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_upper_c_sf_ps",
- MIPS_BUILTIN_UPPER_C_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_lower_c_sf_ps",
- MIPS_BUILTIN_LOWER_C_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_all_c_sf_ps",
- MIPS_BUILTIN_ALL_C_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_any_c_ngle_ps",
- MIPS_BUILTIN_ANY_C_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_upper_c_ngle_ps",
- MIPS_BUILTIN_UPPER_C_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_lower_c_ngle_ps",
- MIPS_BUILTIN_LOWER_C_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_all_c_ngle_ps",
- MIPS_BUILTIN_ALL_C_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_any_c_seq_ps",
- MIPS_BUILTIN_ANY_C_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_upper_c_seq_ps",
- MIPS_BUILTIN_UPPER_C_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_lower_c_seq_ps",
- MIPS_BUILTIN_LOWER_C_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_all_c_seq_ps",
- MIPS_BUILTIN_ALL_C_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_any_c_ngl_ps",
- MIPS_BUILTIN_ANY_C_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_upper_c_ngl_ps",
- MIPS_BUILTIN_UPPER_C_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_lower_c_ngl_ps",
- MIPS_BUILTIN_LOWER_C_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_all_c_ngl_ps",
- MIPS_BUILTIN_ALL_C_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_any_c_lt_ps",
- MIPS_BUILTIN_ANY_C_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_upper_c_lt_ps",
- MIPS_BUILTIN_UPPER_C_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_lower_c_lt_ps",
- MIPS_BUILTIN_LOWER_C_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_all_c_lt_ps",
- MIPS_BUILTIN_ALL_C_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_any_c_nge_ps",
- MIPS_BUILTIN_ANY_C_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_upper_c_nge_ps",
- MIPS_BUILTIN_UPPER_C_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_lower_c_nge_ps",
- MIPS_BUILTIN_LOWER_C_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_all_c_nge_ps",
- MIPS_BUILTIN_ALL_C_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_any_c_le_ps",
- MIPS_BUILTIN_ANY_C_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_upper_c_le_ps",
- MIPS_BUILTIN_UPPER_C_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_lower_c_le_ps",
- MIPS_BUILTIN_LOWER_C_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_all_c_le_ps",
- MIPS_BUILTIN_ALL_C_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_any_c_ngt_ps",
- MIPS_BUILTIN_ANY_C_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_upper_c_ngt_ps",
- MIPS_BUILTIN_UPPER_C_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_lower_c_ngt_ps",
- MIPS_BUILTIN_LOWER_C_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_all_c_ngt_ps",
- MIPS_BUILTIN_ALL_C_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
-
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_any_cabs_f_ps",
- MIPS_BUILTIN_ANY_CABS_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_upper_cabs_f_ps",
- MIPS_BUILTIN_UPPER_CABS_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_lower_cabs_f_ps",
- MIPS_BUILTIN_LOWER_CABS_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_all_cabs_f_ps",
- MIPS_BUILTIN_ALL_CABS_F_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_any_cabs_un_ps",
- MIPS_BUILTIN_ANY_CABS_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_upper_cabs_un_ps",
- MIPS_BUILTIN_UPPER_CABS_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_lower_cabs_un_ps",
- MIPS_BUILTIN_LOWER_CABS_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_all_cabs_un_ps",
- MIPS_BUILTIN_ALL_CABS_UN_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_any_cabs_eq_ps",
- MIPS_BUILTIN_ANY_CABS_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_upper_cabs_eq_ps",
- MIPS_BUILTIN_UPPER_CABS_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_lower_cabs_eq_ps",
- MIPS_BUILTIN_LOWER_CABS_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_all_cabs_eq_ps",
- MIPS_BUILTIN_ALL_CABS_EQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_any_cabs_ueq_ps",
- MIPS_BUILTIN_ANY_CABS_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_upper_cabs_ueq_ps",
- MIPS_BUILTIN_UPPER_CABS_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_lower_cabs_ueq_ps",
- MIPS_BUILTIN_LOWER_CABS_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_all_cabs_ueq_ps",
- MIPS_BUILTIN_ALL_CABS_UEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_any_cabs_olt_ps",
- MIPS_BUILTIN_ANY_CABS_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_upper_cabs_olt_ps",
- MIPS_BUILTIN_UPPER_CABS_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_lower_cabs_olt_ps",
- MIPS_BUILTIN_LOWER_CABS_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_all_cabs_olt_ps",
- MIPS_BUILTIN_ALL_CABS_OLT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_any_cabs_ult_ps",
- MIPS_BUILTIN_ANY_CABS_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_upper_cabs_ult_ps",
- MIPS_BUILTIN_UPPER_CABS_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_lower_cabs_ult_ps",
- MIPS_BUILTIN_LOWER_CABS_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_all_cabs_ult_ps",
- MIPS_BUILTIN_ALL_CABS_ULT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_any_cabs_ole_ps",
- MIPS_BUILTIN_ANY_CABS_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_upper_cabs_ole_ps",
- MIPS_BUILTIN_UPPER_CABS_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_lower_cabs_ole_ps",
- MIPS_BUILTIN_LOWER_CABS_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_all_cabs_ole_ps",
- MIPS_BUILTIN_ALL_CABS_OLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_any_cabs_ule_ps",
- MIPS_BUILTIN_ANY_CABS_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_upper_cabs_ule_ps",
- MIPS_BUILTIN_UPPER_CABS_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_lower_cabs_ule_ps",
- MIPS_BUILTIN_LOWER_CABS_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_all_cabs_ule_ps",
- MIPS_BUILTIN_ALL_CABS_ULE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_any_cabs_sf_ps",
- MIPS_BUILTIN_ANY_CABS_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_upper_cabs_sf_ps",
- MIPS_BUILTIN_UPPER_CABS_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_lower_cabs_sf_ps",
- MIPS_BUILTIN_LOWER_CABS_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_all_cabs_sf_ps",
- MIPS_BUILTIN_ALL_CABS_SF_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_any_cabs_ngle_ps",
- MIPS_BUILTIN_ANY_CABS_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_upper_cabs_ngle_ps",
- MIPS_BUILTIN_UPPER_CABS_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_lower_cabs_ngle_ps",
- MIPS_BUILTIN_LOWER_CABS_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_all_cabs_ngle_ps",
- MIPS_BUILTIN_ALL_CABS_NGLE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_any_cabs_seq_ps",
- MIPS_BUILTIN_ANY_CABS_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_upper_cabs_seq_ps",
- MIPS_BUILTIN_UPPER_CABS_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_lower_cabs_seq_ps",
- MIPS_BUILTIN_LOWER_CABS_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_all_cabs_seq_ps",
- MIPS_BUILTIN_ALL_CABS_SEQ_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_any_cabs_ngl_ps",
- MIPS_BUILTIN_ANY_CABS_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_upper_cabs_ngl_ps",
- MIPS_BUILTIN_UPPER_CABS_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_lower_cabs_ngl_ps",
- MIPS_BUILTIN_LOWER_CABS_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_all_cabs_ngl_ps",
- MIPS_BUILTIN_ALL_CABS_NGL_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_any_cabs_lt_ps",
- MIPS_BUILTIN_ANY_CABS_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_upper_cabs_lt_ps",
- MIPS_BUILTIN_UPPER_CABS_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_lower_cabs_lt_ps",
- MIPS_BUILTIN_LOWER_CABS_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_all_cabs_lt_ps",
- MIPS_BUILTIN_ALL_CABS_LT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_any_cabs_nge_ps",
- MIPS_BUILTIN_ANY_CABS_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_upper_cabs_nge_ps",
- MIPS_BUILTIN_UPPER_CABS_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_lower_cabs_nge_ps",
- MIPS_BUILTIN_LOWER_CABS_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_all_cabs_nge_ps",
- MIPS_BUILTIN_ALL_CABS_NGE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_any_cabs_le_ps",
- MIPS_BUILTIN_ANY_CABS_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_upper_cabs_le_ps",
- MIPS_BUILTIN_UPPER_CABS_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_lower_cabs_le_ps",
- MIPS_BUILTIN_LOWER_CABS_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_all_cabs_le_ps",
- MIPS_BUILTIN_ALL_CABS_LE_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_any_cabs_ngt_ps",
- MIPS_BUILTIN_ANY_CABS_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_upper_cabs_ngt_ps",
- MIPS_BUILTIN_UPPER_CABS_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_lower_cabs_ngt_ps",
- MIPS_BUILTIN_LOWER_CABS_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_all_cabs_ngt_ps",
- MIPS_BUILTIN_ALL_CABS_NGT_PS, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D },
-
- { CODE_FOR_mips_c_f_4s, "__builtin_mips_any_c_f_4s",
- MIPS_BUILTIN_ANY_C_F_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_f_4s, "__builtin_mips_all_c_f_4s",
- MIPS_BUILTIN_ALL_C_F_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, MASK_MIPS3D },
- { CODE_FOR_mips_c_un_4s, "__builtin_mips_any_c_un_4s",
- MIPS_BUILTIN_ANY_C_UN_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_un_4s, "__builtin_mips_all_c_un_4s",
- MIPS_BUILTIN_ALL_C_UN_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_eq_4s, "__builtin_mips_any_c_eq_4s",
- MIPS_BUILTIN_ANY_C_EQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_eq_4s, "__builtin_mips_all_c_eq_4s",
- MIPS_BUILTIN_ALL_C_EQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ueq_4s, "__builtin_mips_any_c_ueq_4s",
- MIPS_BUILTIN_ANY_C_UEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ueq_4s, "__builtin_mips_all_c_ueq_4s",
- MIPS_BUILTIN_ALL_C_UEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_olt_4s, "__builtin_mips_any_c_olt_4s",
- MIPS_BUILTIN_ANY_C_OLT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_olt_4s, "__builtin_mips_all_c_olt_4s",
- MIPS_BUILTIN_ALL_C_OLT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ult_4s, "__builtin_mips_any_c_ult_4s",
- MIPS_BUILTIN_ANY_C_ULT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ult_4s, "__builtin_mips_all_c_ult_4s",
- MIPS_BUILTIN_ALL_C_ULT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ole_4s, "__builtin_mips_any_c_ole_4s",
- MIPS_BUILTIN_ANY_C_OLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ole_4s, "__builtin_mips_all_c_ole_4s",
- MIPS_BUILTIN_ALL_C_OLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ule_4s, "__builtin_mips_any_c_ule_4s",
- MIPS_BUILTIN_ANY_C_ULE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ule_4s, "__builtin_mips_all_c_ule_4s",
- MIPS_BUILTIN_ALL_C_ULE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_sf_4s, "__builtin_mips_any_c_sf_4s",
- MIPS_BUILTIN_ANY_C_SF_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_sf_4s, "__builtin_mips_all_c_sf_4s",
- MIPS_BUILTIN_ALL_C_SF_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngle_4s, "__builtin_mips_any_c_ngle_4s",
- MIPS_BUILTIN_ANY_C_NGLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngle_4s, "__builtin_mips_all_c_ngle_4s",
- MIPS_BUILTIN_ALL_C_NGLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_seq_4s, "__builtin_mips_any_c_seq_4s",
- MIPS_BUILTIN_ANY_C_SEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_seq_4s, "__builtin_mips_all_c_seq_4s",
- MIPS_BUILTIN_ALL_C_SEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngl_4s, "__builtin_mips_any_c_ngl_4s",
- MIPS_BUILTIN_ANY_C_NGL_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngl_4s, "__builtin_mips_all_c_ngl_4s",
- MIPS_BUILTIN_ALL_C_NGL_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_lt_4s, "__builtin_mips_any_c_lt_4s",
- MIPS_BUILTIN_ANY_C_LT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_lt_4s, "__builtin_mips_all_c_lt_4s",
- MIPS_BUILTIN_ALL_C_LT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_nge_4s, "__builtin_mips_any_c_nge_4s",
- MIPS_BUILTIN_ANY_C_NGE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_nge_4s, "__builtin_mips_all_c_nge_4s",
- MIPS_BUILTIN_ALL_C_NGE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_le_4s, "__builtin_mips_any_c_le_4s",
- MIPS_BUILTIN_ANY_C_LE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_le_4s, "__builtin_mips_all_c_le_4s",
- MIPS_BUILTIN_ALL_C_LE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngt_4s, "__builtin_mips_any_c_ngt_4s",
- MIPS_BUILTIN_ANY_C_NGT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_ngt_4s, "__builtin_mips_all_c_ngt_4s",
- MIPS_BUILTIN_ALL_C_NGT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
-
- { CODE_FOR_mips_cabs_f_4s, "__builtin_mips_any_cabs_f_4s",
- MIPS_BUILTIN_ANY_CABS_F_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_f_4s, "__builtin_mips_all_cabs_f_4s",
- MIPS_BUILTIN_ALL_CABS_F_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_4s, "__builtin_mips_any_cabs_un_4s",
- MIPS_BUILTIN_ANY_CABS_UN_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_4s, "__builtin_mips_all_cabs_un_4s",
- MIPS_BUILTIN_ALL_CABS_UN_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_4s, "__builtin_mips_any_cabs_eq_4s",
- MIPS_BUILTIN_ANY_CABS_EQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_4s, "__builtin_mips_all_cabs_eq_4s",
- MIPS_BUILTIN_ALL_CABS_EQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_4s, "__builtin_mips_any_cabs_ueq_4s",
- MIPS_BUILTIN_ANY_CABS_UEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_4s, "__builtin_mips_all_cabs_ueq_4s",
- MIPS_BUILTIN_ALL_CABS_UEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_4s, "__builtin_mips_any_cabs_olt_4s",
- MIPS_BUILTIN_ANY_CABS_OLT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_4s, "__builtin_mips_all_cabs_olt_4s",
- MIPS_BUILTIN_ALL_CABS_OLT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_4s, "__builtin_mips_any_cabs_ult_4s",
- MIPS_BUILTIN_ANY_CABS_ULT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_4s, "__builtin_mips_all_cabs_ult_4s",
- MIPS_BUILTIN_ALL_CABS_ULT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_4s, "__builtin_mips_any_cabs_ole_4s",
- MIPS_BUILTIN_ANY_CABS_OLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_4s, "__builtin_mips_all_cabs_ole_4s",
- MIPS_BUILTIN_ALL_CABS_OLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_4s, "__builtin_mips_any_cabs_ule_4s",
- MIPS_BUILTIN_ANY_CABS_ULE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_4s, "__builtin_mips_all_cabs_ule_4s",
- MIPS_BUILTIN_ALL_CABS_ULE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_4s, "__builtin_mips_any_cabs_sf_4s",
- MIPS_BUILTIN_ANY_CABS_SF_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_4s, "__builtin_mips_all_cabs_sf_4s",
- MIPS_BUILTIN_ALL_CABS_SF_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_4s, "__builtin_mips_any_cabs_ngle_4s",
- MIPS_BUILTIN_ANY_CABS_NGLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_4s, "__builtin_mips_all_cabs_ngle_4s",
- MIPS_BUILTIN_ALL_CABS_NGLE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_4s, "__builtin_mips_any_cabs_seq_4s",
- MIPS_BUILTIN_ANY_CABS_SEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_4s, "__builtin_mips_all_cabs_seq_4s",
- MIPS_BUILTIN_ALL_CABS_SEQ_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_4s, "__builtin_mips_any_cabs_ngl_4s",
- MIPS_BUILTIN_ANY_CABS_NGL_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_4s, "__builtin_mips_all_cabs_ngl_4s",
- MIPS_BUILTIN_ALL_CABS_NGL_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_4s, "__builtin_mips_any_cabs_lt_4s",
- MIPS_BUILTIN_ANY_CABS_LT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_4s, "__builtin_mips_all_cabs_lt_4s",
- MIPS_BUILTIN_ALL_CABS_LT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_4s, "__builtin_mips_any_cabs_nge_4s",
- MIPS_BUILTIN_ANY_CABS_NGE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_4s, "__builtin_mips_all_cabs_nge_4s",
- MIPS_BUILTIN_ALL_CABS_NGE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_4s, "__builtin_mips_any_cabs_le_4s",
- MIPS_BUILTIN_ANY_CABS_LE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_4s, "__builtin_mips_all_cabs_le_4s",
- MIPS_BUILTIN_ALL_CABS_LE_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_4s, "__builtin_mips_any_cabs_ngt_4s",
- MIPS_BUILTIN_ANY_CABS_NGT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_4s, "__builtin_mips_all_cabs_ngt_4s",
- MIPS_BUILTIN_ALL_CABS_NGT_4S, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
-
- { CODE_FOR_mips_cabs_f_s, "__builtin_mips_cabs_f_s",
- MIPS_BUILTIN_CABS_F_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_s, "__builtin_mips_cabs_un_s",
- MIPS_BUILTIN_CABS_UN_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_s, "__builtin_mips_cabs_eq_s",
- MIPS_BUILTIN_CABS_EQ_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_s, "__builtin_mips_cabs_ueq_s",
- MIPS_BUILTIN_CABS_UEQ_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_s, "__builtin_mips_cabs_olt_s",
- MIPS_BUILTIN_CABS_OLT_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_s, "__builtin_mips_cabs_ult_s",
- MIPS_BUILTIN_CABS_ULT_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_s, "__builtin_mips_cabs_ole_s",
- MIPS_BUILTIN_CABS_OLE_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_s, "__builtin_mips_cabs_ule_s",
- MIPS_BUILTIN_CABS_ULE_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_s, "__builtin_mips_cabs_sf_s",
- MIPS_BUILTIN_CABS_SF_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_s, "__builtin_mips_cabs_ngle_s",
- MIPS_BUILTIN_CABS_NGLE_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_s, "__builtin_mips_cabs_seq_s",
- MIPS_BUILTIN_CABS_SEQ_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_s, "__builtin_mips_cabs_ngl_s",
- MIPS_BUILTIN_CABS_NGL_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_s, "__builtin_mips_cabs_lt_s",
- MIPS_BUILTIN_CABS_LT_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_s, "__builtin_mips_cabs_nge_s",
- MIPS_BUILTIN_CABS_NGE_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_s, "__builtin_mips_cabs_le_s",
- MIPS_BUILTIN_CABS_LE_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_s, "__builtin_mips_cabs_ngt_s",
- MIPS_BUILTIN_CABS_NGT_S, MIPS_INT_FTYPE_SF_SF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_f_d, "__builtin_mips_cabs_f_d",
- MIPS_BUILTIN_CABS_F_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_d, "__builtin_mips_cabs_un_d",
- MIPS_BUILTIN_CABS_UN_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_d, "__builtin_mips_cabs_eq_d",
- MIPS_BUILTIN_CABS_EQ_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_d, "__builtin_mips_cabs_ueq_d",
- MIPS_BUILTIN_CABS_UEQ_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_d, "__builtin_mips_cabs_olt_d",
- MIPS_BUILTIN_CABS_OLT_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_d, "__builtin_mips_cabs_ult_d",
- MIPS_BUILTIN_CABS_ULT_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_d, "__builtin_mips_cabs_ole_d",
- MIPS_BUILTIN_CABS_OLE_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_d, "__builtin_mips_cabs_ule_d",
- MIPS_BUILTIN_CABS_ULE_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_d, "__builtin_mips_cabs_sf_d",
- MIPS_BUILTIN_CABS_SF_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_d, "__builtin_mips_cabs_ngle_d",
- MIPS_BUILTIN_CABS_NGLE_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_d, "__builtin_mips_cabs_seq_d",
- MIPS_BUILTIN_CABS_SEQ_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_d, "__builtin_mips_cabs_ngl_d",
- MIPS_BUILTIN_CABS_NGL_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_d, "__builtin_mips_cabs_lt_d",
- MIPS_BUILTIN_CABS_LT_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_d, "__builtin_mips_cabs_nge_d",
- MIPS_BUILTIN_CABS_NGE_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_d, "__builtin_mips_cabs_le_d",
- MIPS_BUILTIN_CABS_LE_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_d, "__builtin_mips_cabs_ngt_d",
- MIPS_BUILTIN_CABS_NGT_D, MIPS_INT_FTYPE_DF_DF, MASK_MIPS3D },
-
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_movt_c_f_ps",
- MIPS_BUILTIN_MOVT_C_F_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_movt_c_un_ps",
- MIPS_BUILTIN_MOVT_C_UN_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_movt_c_eq_ps",
- MIPS_BUILTIN_MOVT_C_EQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_movt_c_ueq_ps",
- MIPS_BUILTIN_MOVT_C_UEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_movt_c_olt_ps",
- MIPS_BUILTIN_MOVT_C_OLT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_movt_c_ult_ps",
- MIPS_BUILTIN_MOVT_C_ULT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_movt_c_ole_ps",
- MIPS_BUILTIN_MOVT_C_OLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_movt_c_ule_ps",
- MIPS_BUILTIN_MOVT_C_ULE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_movt_c_sf_ps",
- MIPS_BUILTIN_MOVT_C_SF_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_movt_c_ngle_ps",
- MIPS_BUILTIN_MOVT_C_NGLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_movt_c_seq_ps",
- MIPS_BUILTIN_MOVT_C_SEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_movt_c_ngl_ps",
- MIPS_BUILTIN_MOVT_C_NGL_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_movt_c_lt_ps",
- MIPS_BUILTIN_MOVT_C_LT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_movt_c_nge_ps",
- MIPS_BUILTIN_MOVT_C_NGE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_movt_c_le_ps",
- MIPS_BUILTIN_MOVT_C_LE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_movt_c_ngt_ps",
- MIPS_BUILTIN_MOVT_C_NGT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_movt_cabs_f_ps",
- MIPS_BUILTIN_MOVT_CABS_F_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_movt_cabs_un_ps",
- MIPS_BUILTIN_MOVT_CABS_UN_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_movt_cabs_eq_ps",
- MIPS_BUILTIN_MOVT_CABS_EQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_movt_cabs_ueq_ps",
- MIPS_BUILTIN_MOVT_CABS_UEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_movt_cabs_olt_ps",
- MIPS_BUILTIN_MOVT_CABS_OLT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_movt_cabs_ult_ps",
- MIPS_BUILTIN_MOVT_CABS_ULT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_movt_cabs_ole_ps",
- MIPS_BUILTIN_MOVT_CABS_OLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_movt_cabs_ule_ps",
- MIPS_BUILTIN_MOVT_CABS_ULE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_movt_cabs_sf_ps",
- MIPS_BUILTIN_MOVT_CABS_SF_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_movt_cabs_ngle_ps",
- MIPS_BUILTIN_MOVT_CABS_NGLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_movt_cabs_seq_ps",
- MIPS_BUILTIN_MOVT_CABS_SEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_movt_cabs_ngl_ps",
- MIPS_BUILTIN_MOVT_CABS_NGL_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_movt_cabs_lt_ps",
- MIPS_BUILTIN_MOVT_CABS_LT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_movt_cabs_nge_ps",
- MIPS_BUILTIN_MOVT_CABS_NGE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_movt_cabs_le_ps",
- MIPS_BUILTIN_MOVT_CABS_LE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_movt_cabs_ngt_ps",
- MIPS_BUILTIN_MOVT_CABS_NGT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_c_f_ps, "__builtin_mips_movf_c_f_ps",
- MIPS_BUILTIN_MOVF_C_F_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_un_ps, "__builtin_mips_movf_c_un_ps",
- MIPS_BUILTIN_MOVF_C_UN_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_eq_ps, "__builtin_mips_movf_c_eq_ps",
- MIPS_BUILTIN_MOVF_C_EQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ueq_ps, "__builtin_mips_movf_c_ueq_ps",
- MIPS_BUILTIN_MOVF_C_UEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_olt_ps, "__builtin_mips_movf_c_olt_ps",
- MIPS_BUILTIN_MOVF_C_OLT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ult_ps, "__builtin_mips_movf_c_ult_ps",
- MIPS_BUILTIN_MOVF_C_ULT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ole_ps, "__builtin_mips_movf_c_ole_ps",
- MIPS_BUILTIN_MOVF_C_OLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ule_ps, "__builtin_mips_movf_c_ule_ps",
- MIPS_BUILTIN_MOVF_C_ULE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_sf_ps, "__builtin_mips_movf_c_sf_ps",
- MIPS_BUILTIN_MOVF_C_SF_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngle_ps, "__builtin_mips_movf_c_ngle_ps",
- MIPS_BUILTIN_MOVF_C_NGLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_seq_ps, "__builtin_mips_movf_c_seq_ps",
- MIPS_BUILTIN_MOVF_C_SEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngl_ps, "__builtin_mips_movf_c_ngl_ps",
- MIPS_BUILTIN_MOVF_C_NGL_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_lt_ps, "__builtin_mips_movf_c_lt_ps",
- MIPS_BUILTIN_MOVF_C_LT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_nge_ps, "__builtin_mips_movf_c_nge_ps",
- MIPS_BUILTIN_MOVF_C_NGE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_le_ps, "__builtin_mips_movf_c_le_ps",
- MIPS_BUILTIN_MOVF_C_LE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_c_ngt_ps, "__builtin_mips_movf_c_ngt_ps",
- MIPS_BUILTIN_MOVF_C_NGT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_PAIRED_SINGLE },
- { CODE_FOR_mips_cabs_f_ps, "__builtin_mips_movf_cabs_f_ps",
- MIPS_BUILTIN_MOVF_CABS_F_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_un_ps, "__builtin_mips_movf_cabs_un_ps",
- MIPS_BUILTIN_MOVF_CABS_UN_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_eq_ps, "__builtin_mips_movf_cabs_eq_ps",
- MIPS_BUILTIN_MOVF_CABS_EQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ueq_ps, "__builtin_mips_movf_cabs_ueq_ps",
- MIPS_BUILTIN_MOVF_CABS_UEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_olt_ps, "__builtin_mips_movf_cabs_olt_ps",
- MIPS_BUILTIN_MOVF_CABS_OLT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ult_ps, "__builtin_mips_movf_cabs_ult_ps",
- MIPS_BUILTIN_MOVF_CABS_ULT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ole_ps, "__builtin_mips_movf_cabs_ole_ps",
- MIPS_BUILTIN_MOVF_CABS_OLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ule_ps, "__builtin_mips_movf_cabs_ule_ps",
- MIPS_BUILTIN_MOVF_CABS_ULE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_sf_ps, "__builtin_mips_movf_cabs_sf_ps",
- MIPS_BUILTIN_MOVF_CABS_SF_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngle_ps, "__builtin_mips_movf_cabs_ngle_ps",
- MIPS_BUILTIN_MOVF_CABS_NGLE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_seq_ps, "__builtin_mips_movf_cabs_seq_ps",
- MIPS_BUILTIN_MOVF_CABS_SEQ_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngl_ps, "__builtin_mips_movf_cabs_ngl_ps",
- MIPS_BUILTIN_MOVF_CABS_NGL_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_lt_ps, "__builtin_mips_movf_cabs_lt_ps",
- MIPS_BUILTIN_MOVF_CABS_LT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_nge_ps, "__builtin_mips_movf_cabs_nge_ps",
- MIPS_BUILTIN_MOVF_CABS_NGE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_le_ps, "__builtin_mips_movf_cabs_le_ps",
- MIPS_BUILTIN_MOVF_CABS_LE_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
- { CODE_FOR_mips_cabs_ngt_ps, "__builtin_mips_movf_cabs_ngt_ps",
- MIPS_BUILTIN_MOVF_CABS_NGT_PS, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
- MASK_MIPS3D },
-
+ DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (puu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_ps_s, MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_s_pl, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_s_pu, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (abs_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+
+ DIRECT_BUILTIN (alnv_ps, MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
+ MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (addr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (mulr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (cvt_pw_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (cvt_ps_pw, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+
+ DIRECT_BUILTIN (recip1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+
+ DIRECT_BUILTIN (rsqrt1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+
+ MIPS_FP_CONDITIONS (CMP_BUILTINS)
};
+/* Builtin functions for the SB-1 processor. */
-/* Expand builtin functions. This is called from TARGET_EXPAND_BUILTIN. */
+#define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
-rtx
-mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- int ignore ATTRIBUTE_UNUSED)
+static const struct builtin_description sb1_bdesc[] =
{
- rtx pat;
- enum insn_code icode;
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
- unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- tree arg0;
- tree arg1;
- tree arg2;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- enum machine_mode mode2;
- rtx op0;
- rtx op1;
- rtx op2;
-
- switch (fcode)
- {
- /* Two Operands. */
- case MIPS_BUILTIN_PLL_PS:
- case MIPS_BUILTIN_PUL_PS:
- case MIPS_BUILTIN_PLU_PS:
- case MIPS_BUILTIN_PUU_PS:
- case MIPS_BUILTIN_CVT_PS_S:
- case MIPS_BUILTIN_ADDR_PS:
- case MIPS_BUILTIN_MULR_PS:
- case MIPS_BUILTIN_RECIP2_S:
- case MIPS_BUILTIN_RECIP2_D:
- case MIPS_BUILTIN_RECIP2_PS:
- case MIPS_BUILTIN_RSQRT2_S:
- case MIPS_BUILTIN_RSQRT2_D:
- case MIPS_BUILTIN_RSQRT2_PS:
-
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
-
- if (target == 0
- || GET_MODE (target) != tmode
- || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
-
- 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);
-
- pat = GEN_FCN (icode) (target, op0, op1);
- if (!pat)
- return 0;
-
- emit_insn (pat);
- return target;
-
- /* One Operand. */
- case MIPS_BUILTIN_CVT_S_PL:
- case MIPS_BUILTIN_CVT_S_PU:
- case MIPS_BUILTIN_ABS_PS:
- case MIPS_BUILTIN_CVT_PW_PS:
- case MIPS_BUILTIN_CVT_PS_PW:
- case MIPS_BUILTIN_RECIP1_S:
- case MIPS_BUILTIN_RECIP1_D:
- case MIPS_BUILTIN_RECIP1_PS:
- case MIPS_BUILTIN_RSQRT1_S:
- case MIPS_BUILTIN_RSQRT1_D:
- case MIPS_BUILTIN_RSQRT1_PS:
-
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
-
- if (target == 0
- || GET_MODE (target) != tmode
- || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
-
- 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;
-
- /* Three Operands. */
- case MIPS_BUILTIN_ALNV_PS:
-
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
- mode2 = insn_data[icode].operand[3].mode;
-
- if (target == 0
- || GET_MODE (target) != tmode
- || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
-
- 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 (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
- op2 = copy_to_mode_reg (mode2, op2);
-
- pat = GEN_FCN (icode) (target, op0, op1, op2);
- if (!pat)
- return 0;
-
- emit_insn (pat);
- return target;
-
- /* Paired Single Comparison. */
- case MIPS_BUILTIN_ANY_C_F_PS:
- case MIPS_BUILTIN_ANY_C_UN_PS:
- case MIPS_BUILTIN_ANY_C_EQ_PS:
- case MIPS_BUILTIN_ANY_C_UEQ_PS:
- case MIPS_BUILTIN_ANY_C_OLT_PS:
- case MIPS_BUILTIN_ANY_C_ULT_PS:
- case MIPS_BUILTIN_ANY_C_OLE_PS:
- case MIPS_BUILTIN_ANY_C_ULE_PS:
- case MIPS_BUILTIN_ANY_C_SF_PS:
- case MIPS_BUILTIN_ANY_C_NGLE_PS:
- case MIPS_BUILTIN_ANY_C_SEQ_PS:
- case MIPS_BUILTIN_ANY_C_NGL_PS:
- case MIPS_BUILTIN_ANY_C_LT_PS:
- case MIPS_BUILTIN_ANY_C_NGE_PS:
- case MIPS_BUILTIN_ANY_C_LE_PS:
- case MIPS_BUILTIN_ANY_C_NGT_PS:
- case MIPS_BUILTIN_ANY_CABS_F_PS:
- case MIPS_BUILTIN_ANY_CABS_UN_PS:
- case MIPS_BUILTIN_ANY_CABS_EQ_PS:
- case MIPS_BUILTIN_ANY_CABS_UEQ_PS:
- case MIPS_BUILTIN_ANY_CABS_OLT_PS:
- case MIPS_BUILTIN_ANY_CABS_ULT_PS:
- case MIPS_BUILTIN_ANY_CABS_OLE_PS:
- case MIPS_BUILTIN_ANY_CABS_ULE_PS:
- case MIPS_BUILTIN_ANY_CABS_SF_PS:
- case MIPS_BUILTIN_ANY_CABS_NGLE_PS:
- case MIPS_BUILTIN_ANY_CABS_SEQ_PS:
- case MIPS_BUILTIN_ANY_CABS_NGL_PS:
- case MIPS_BUILTIN_ANY_CABS_LT_PS:
- case MIPS_BUILTIN_ANY_CABS_NGE_PS:
- case MIPS_BUILTIN_ANY_CABS_LE_PS:
- case MIPS_BUILTIN_ANY_CABS_NGT_PS:
- return mips_expand_ps_compare_builtin (MIPS_CMP_ANY, target,
- fcode, arglist);
-
- /* Paired Single Comparison. */
- case MIPS_BUILTIN_UPPER_C_F_PS:
- case MIPS_BUILTIN_UPPER_C_UN_PS:
- case MIPS_BUILTIN_UPPER_C_EQ_PS:
- case MIPS_BUILTIN_UPPER_C_UEQ_PS:
- case MIPS_BUILTIN_UPPER_C_OLT_PS:
- case MIPS_BUILTIN_UPPER_C_ULT_PS:
- case MIPS_BUILTIN_UPPER_C_OLE_PS:
- case MIPS_BUILTIN_UPPER_C_ULE_PS:
- case MIPS_BUILTIN_UPPER_C_SF_PS:
- case MIPS_BUILTIN_UPPER_C_NGLE_PS:
- case MIPS_BUILTIN_UPPER_C_SEQ_PS:
- case MIPS_BUILTIN_UPPER_C_NGL_PS:
- case MIPS_BUILTIN_UPPER_C_LT_PS:
- case MIPS_BUILTIN_UPPER_C_NGE_PS:
- case MIPS_BUILTIN_UPPER_C_LE_PS:
- case MIPS_BUILTIN_UPPER_C_NGT_PS:
- case MIPS_BUILTIN_UPPER_CABS_F_PS:
- case MIPS_BUILTIN_UPPER_CABS_UN_PS:
- case MIPS_BUILTIN_UPPER_CABS_EQ_PS:
- case MIPS_BUILTIN_UPPER_CABS_UEQ_PS:
- case MIPS_BUILTIN_UPPER_CABS_OLT_PS:
- case MIPS_BUILTIN_UPPER_CABS_ULT_PS:
- case MIPS_BUILTIN_UPPER_CABS_OLE_PS:
- case MIPS_BUILTIN_UPPER_CABS_ULE_PS:
- case MIPS_BUILTIN_UPPER_CABS_SF_PS:
- case MIPS_BUILTIN_UPPER_CABS_NGLE_PS:
- case MIPS_BUILTIN_UPPER_CABS_SEQ_PS:
- case MIPS_BUILTIN_UPPER_CABS_NGL_PS:
- case MIPS_BUILTIN_UPPER_CABS_LT_PS:
- case MIPS_BUILTIN_UPPER_CABS_NGE_PS:
- case MIPS_BUILTIN_UPPER_CABS_LE_PS:
- case MIPS_BUILTIN_UPPER_CABS_NGT_PS:
- return mips_expand_ps_compare_builtin (MIPS_CMP_UPPER, target,
- fcode, arglist);
-
- /* Paired Single Comparison. */
- case MIPS_BUILTIN_LOWER_C_F_PS:
- case MIPS_BUILTIN_LOWER_C_UN_PS:
- case MIPS_BUILTIN_LOWER_C_EQ_PS:
- case MIPS_BUILTIN_LOWER_C_UEQ_PS:
- case MIPS_BUILTIN_LOWER_C_OLT_PS:
- case MIPS_BUILTIN_LOWER_C_ULT_PS:
- case MIPS_BUILTIN_LOWER_C_OLE_PS:
- case MIPS_BUILTIN_LOWER_C_ULE_PS:
- case MIPS_BUILTIN_LOWER_C_SF_PS:
- case MIPS_BUILTIN_LOWER_C_NGLE_PS:
- case MIPS_BUILTIN_LOWER_C_SEQ_PS:
- case MIPS_BUILTIN_LOWER_C_NGL_PS:
- case MIPS_BUILTIN_LOWER_C_LT_PS:
- case MIPS_BUILTIN_LOWER_C_NGE_PS:
- case MIPS_BUILTIN_LOWER_C_LE_PS:
- case MIPS_BUILTIN_LOWER_C_NGT_PS:
- case MIPS_BUILTIN_LOWER_CABS_F_PS:
- case MIPS_BUILTIN_LOWER_CABS_UN_PS:
- case MIPS_BUILTIN_LOWER_CABS_EQ_PS:
- case MIPS_BUILTIN_LOWER_CABS_UEQ_PS:
- case MIPS_BUILTIN_LOWER_CABS_OLT_PS:
- case MIPS_BUILTIN_LOWER_CABS_ULT_PS:
- case MIPS_BUILTIN_LOWER_CABS_OLE_PS:
- case MIPS_BUILTIN_LOWER_CABS_ULE_PS:
- case MIPS_BUILTIN_LOWER_CABS_SF_PS:
- case MIPS_BUILTIN_LOWER_CABS_NGLE_PS:
- case MIPS_BUILTIN_LOWER_CABS_SEQ_PS:
- case MIPS_BUILTIN_LOWER_CABS_NGL_PS:
- case MIPS_BUILTIN_LOWER_CABS_LT_PS:
- case MIPS_BUILTIN_LOWER_CABS_NGE_PS:
- case MIPS_BUILTIN_LOWER_CABS_LE_PS:
- case MIPS_BUILTIN_LOWER_CABS_NGT_PS:
- return mips_expand_ps_compare_builtin (MIPS_CMP_LOWER, target,
- fcode, arglist);
-
- /* Paired Single Comparison. */
- case MIPS_BUILTIN_ALL_C_F_PS:
- case MIPS_BUILTIN_ALL_C_UN_PS:
- case MIPS_BUILTIN_ALL_C_EQ_PS:
- case MIPS_BUILTIN_ALL_C_UEQ_PS:
- case MIPS_BUILTIN_ALL_C_OLT_PS:
- case MIPS_BUILTIN_ALL_C_ULT_PS:
- case MIPS_BUILTIN_ALL_C_OLE_PS:
- case MIPS_BUILTIN_ALL_C_ULE_PS:
- case MIPS_BUILTIN_ALL_C_SF_PS:
- case MIPS_BUILTIN_ALL_C_NGLE_PS:
- case MIPS_BUILTIN_ALL_C_SEQ_PS:
- case MIPS_BUILTIN_ALL_C_NGL_PS:
- case MIPS_BUILTIN_ALL_C_LT_PS:
- case MIPS_BUILTIN_ALL_C_NGE_PS:
- case MIPS_BUILTIN_ALL_C_LE_PS:
- case MIPS_BUILTIN_ALL_C_NGT_PS:
- case MIPS_BUILTIN_ALL_CABS_F_PS:
- case MIPS_BUILTIN_ALL_CABS_UN_PS:
- case MIPS_BUILTIN_ALL_CABS_EQ_PS:
- case MIPS_BUILTIN_ALL_CABS_UEQ_PS:
- case MIPS_BUILTIN_ALL_CABS_OLT_PS:
- case MIPS_BUILTIN_ALL_CABS_ULT_PS:
- case MIPS_BUILTIN_ALL_CABS_OLE_PS:
- case MIPS_BUILTIN_ALL_CABS_ULE_PS:
- case MIPS_BUILTIN_ALL_CABS_SF_PS:
- case MIPS_BUILTIN_ALL_CABS_NGLE_PS:
- case MIPS_BUILTIN_ALL_CABS_SEQ_PS:
- case MIPS_BUILTIN_ALL_CABS_NGL_PS:
- case MIPS_BUILTIN_ALL_CABS_LT_PS:
- case MIPS_BUILTIN_ALL_CABS_NGE_PS:
- case MIPS_BUILTIN_ALL_CABS_LE_PS:
- case MIPS_BUILTIN_ALL_CABS_NGT_PS:
- return mips_expand_ps_compare_builtin (MIPS_CMP_ALL, target,
- fcode, arglist);
-
- /* Four Single Comparison. */
- case MIPS_BUILTIN_ANY_C_F_4S:
- case MIPS_BUILTIN_ANY_C_UN_4S:
- case MIPS_BUILTIN_ANY_C_EQ_4S:
- case MIPS_BUILTIN_ANY_C_UEQ_4S:
- case MIPS_BUILTIN_ANY_C_OLT_4S:
- case MIPS_BUILTIN_ANY_C_ULT_4S:
- case MIPS_BUILTIN_ANY_C_OLE_4S:
- case MIPS_BUILTIN_ANY_C_ULE_4S:
- case MIPS_BUILTIN_ANY_C_SF_4S:
- case MIPS_BUILTIN_ANY_C_NGLE_4S:
- case MIPS_BUILTIN_ANY_C_SEQ_4S:
- case MIPS_BUILTIN_ANY_C_NGL_4S:
- case MIPS_BUILTIN_ANY_C_LT_4S:
- case MIPS_BUILTIN_ANY_C_NGE_4S:
- case MIPS_BUILTIN_ANY_C_LE_4S:
- case MIPS_BUILTIN_ANY_C_NGT_4S:
- case MIPS_BUILTIN_ANY_CABS_F_4S:
- case MIPS_BUILTIN_ANY_CABS_UN_4S:
- case MIPS_BUILTIN_ANY_CABS_EQ_4S:
- case MIPS_BUILTIN_ANY_CABS_UEQ_4S:
- case MIPS_BUILTIN_ANY_CABS_OLT_4S:
- case MIPS_BUILTIN_ANY_CABS_ULT_4S:
- case MIPS_BUILTIN_ANY_CABS_OLE_4S:
- case MIPS_BUILTIN_ANY_CABS_ULE_4S:
- case MIPS_BUILTIN_ANY_CABS_SF_4S:
- case MIPS_BUILTIN_ANY_CABS_NGLE_4S:
- case MIPS_BUILTIN_ANY_CABS_SEQ_4S:
- case MIPS_BUILTIN_ANY_CABS_NGL_4S:
- case MIPS_BUILTIN_ANY_CABS_LT_4S:
- case MIPS_BUILTIN_ANY_CABS_NGE_4S:
- case MIPS_BUILTIN_ANY_CABS_LE_4S:
- case MIPS_BUILTIN_ANY_CABS_NGT_4S:
- return mips_expand_4s_compare_builtin (MIPS_CMP_ANY, target,
- fcode, arglist);
-
- /* Four Single Comparison. */
- case MIPS_BUILTIN_ALL_C_F_4S:
- case MIPS_BUILTIN_ALL_C_UN_4S:
- case MIPS_BUILTIN_ALL_C_EQ_4S:
- case MIPS_BUILTIN_ALL_C_UEQ_4S:
- case MIPS_BUILTIN_ALL_C_OLT_4S:
- case MIPS_BUILTIN_ALL_C_ULT_4S:
- case MIPS_BUILTIN_ALL_C_OLE_4S:
- case MIPS_BUILTIN_ALL_C_ULE_4S:
- case MIPS_BUILTIN_ALL_C_SF_4S:
- case MIPS_BUILTIN_ALL_C_NGLE_4S:
- case MIPS_BUILTIN_ALL_C_SEQ_4S:
- case MIPS_BUILTIN_ALL_C_NGL_4S:
- case MIPS_BUILTIN_ALL_C_LT_4S:
- case MIPS_BUILTIN_ALL_C_NGE_4S:
- case MIPS_BUILTIN_ALL_C_LE_4S:
- case MIPS_BUILTIN_ALL_C_NGT_4S:
- case MIPS_BUILTIN_ALL_CABS_F_4S:
- case MIPS_BUILTIN_ALL_CABS_UN_4S:
- case MIPS_BUILTIN_ALL_CABS_EQ_4S:
- case MIPS_BUILTIN_ALL_CABS_UEQ_4S:
- case MIPS_BUILTIN_ALL_CABS_OLT_4S:
- case MIPS_BUILTIN_ALL_CABS_ULT_4S:
- case MIPS_BUILTIN_ALL_CABS_OLE_4S:
- case MIPS_BUILTIN_ALL_CABS_ULE_4S:
- case MIPS_BUILTIN_ALL_CABS_SF_4S:
- case MIPS_BUILTIN_ALL_CABS_NGLE_4S:
- case MIPS_BUILTIN_ALL_CABS_SEQ_4S:
- case MIPS_BUILTIN_ALL_CABS_NGL_4S:
- case MIPS_BUILTIN_ALL_CABS_LT_4S:
- case MIPS_BUILTIN_ALL_CABS_NGE_4S:
- case MIPS_BUILTIN_ALL_CABS_LE_4S:
- case MIPS_BUILTIN_ALL_CABS_NGT_4S:
- return mips_expand_4s_compare_builtin (MIPS_CMP_ALL, target,
- fcode, arglist);
-
- /* Single/Double Compare Absolute. */
- case MIPS_BUILTIN_CABS_F_S:
- case MIPS_BUILTIN_CABS_UN_S:
- case MIPS_BUILTIN_CABS_EQ_S:
- case MIPS_BUILTIN_CABS_UEQ_S:
- case MIPS_BUILTIN_CABS_OLT_S:
- case MIPS_BUILTIN_CABS_ULT_S:
- case MIPS_BUILTIN_CABS_OLE_S:
- case MIPS_BUILTIN_CABS_ULE_S:
- case MIPS_BUILTIN_CABS_SF_S:
- case MIPS_BUILTIN_CABS_NGLE_S:
- case MIPS_BUILTIN_CABS_SEQ_S:
- case MIPS_BUILTIN_CABS_NGL_S:
- case MIPS_BUILTIN_CABS_LT_S:
- case MIPS_BUILTIN_CABS_NGE_S:
- case MIPS_BUILTIN_CABS_LE_S:
- case MIPS_BUILTIN_CABS_NGT_S:
- case MIPS_BUILTIN_CABS_F_D:
- case MIPS_BUILTIN_CABS_UN_D:
- case MIPS_BUILTIN_CABS_EQ_D:
- case MIPS_BUILTIN_CABS_UEQ_D:
- case MIPS_BUILTIN_CABS_OLT_D:
- case MIPS_BUILTIN_CABS_ULT_D:
- case MIPS_BUILTIN_CABS_OLE_D:
- case MIPS_BUILTIN_CABS_ULE_D:
- case MIPS_BUILTIN_CABS_SF_D:
- case MIPS_BUILTIN_CABS_NGLE_D:
- case MIPS_BUILTIN_CABS_SEQ_D:
- case MIPS_BUILTIN_CABS_NGL_D:
- case MIPS_BUILTIN_CABS_LT_D:
- case MIPS_BUILTIN_CABS_NGE_D:
- case MIPS_BUILTIN_CABS_LE_D:
- case MIPS_BUILTIN_CABS_NGT_D:
- return mips_expand_compare_builtin (target, fcode, arglist);
-
- /* Conditional Move on True. */
- case MIPS_BUILTIN_MOVT_C_F_PS:
- case MIPS_BUILTIN_MOVT_C_UN_PS:
- case MIPS_BUILTIN_MOVT_C_EQ_PS:
- case MIPS_BUILTIN_MOVT_C_UEQ_PS:
- case MIPS_BUILTIN_MOVT_C_OLT_PS:
- case MIPS_BUILTIN_MOVT_C_ULT_PS:
- case MIPS_BUILTIN_MOVT_C_OLE_PS:
- case MIPS_BUILTIN_MOVT_C_ULE_PS:
- case MIPS_BUILTIN_MOVT_C_SF_PS:
- case MIPS_BUILTIN_MOVT_C_NGLE_PS:
- case MIPS_BUILTIN_MOVT_C_SEQ_PS:
- case MIPS_BUILTIN_MOVT_C_NGL_PS:
- case MIPS_BUILTIN_MOVT_C_LT_PS:
- case MIPS_BUILTIN_MOVT_C_NGE_PS:
- case MIPS_BUILTIN_MOVT_C_LE_PS:
- case MIPS_BUILTIN_MOVT_C_NGT_PS:
- case MIPS_BUILTIN_MOVT_CABS_F_PS:
- case MIPS_BUILTIN_MOVT_CABS_UN_PS:
- case MIPS_BUILTIN_MOVT_CABS_EQ_PS:
- case MIPS_BUILTIN_MOVT_CABS_UEQ_PS:
- case MIPS_BUILTIN_MOVT_CABS_OLT_PS:
- case MIPS_BUILTIN_MOVT_CABS_ULT_PS:
- case MIPS_BUILTIN_MOVT_CABS_OLE_PS:
- case MIPS_BUILTIN_MOVT_CABS_ULE_PS:
- case MIPS_BUILTIN_MOVT_CABS_SF_PS:
- case MIPS_BUILTIN_MOVT_CABS_NGLE_PS:
- case MIPS_BUILTIN_MOVT_CABS_SEQ_PS:
- case MIPS_BUILTIN_MOVT_CABS_NGL_PS:
- case MIPS_BUILTIN_MOVT_CABS_LT_PS:
- case MIPS_BUILTIN_MOVT_CABS_NGE_PS:
- case MIPS_BUILTIN_MOVT_CABS_LE_PS:
- case MIPS_BUILTIN_MOVT_CABS_NGT_PS:
- return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVT, target,
- fcode, arglist);
-
- /* Conditional Move on False. */
- case MIPS_BUILTIN_MOVF_C_F_PS:
- case MIPS_BUILTIN_MOVF_C_UN_PS:
- case MIPS_BUILTIN_MOVF_C_EQ_PS:
- case MIPS_BUILTIN_MOVF_C_UEQ_PS:
- case MIPS_BUILTIN_MOVF_C_OLT_PS:
- case MIPS_BUILTIN_MOVF_C_ULT_PS:
- case MIPS_BUILTIN_MOVF_C_OLE_PS:
- case MIPS_BUILTIN_MOVF_C_ULE_PS:
- case MIPS_BUILTIN_MOVF_C_SF_PS:
- case MIPS_BUILTIN_MOVF_C_NGLE_PS:
- case MIPS_BUILTIN_MOVF_C_SEQ_PS:
- case MIPS_BUILTIN_MOVF_C_NGL_PS:
- case MIPS_BUILTIN_MOVF_C_LT_PS:
- case MIPS_BUILTIN_MOVF_C_NGE_PS:
- case MIPS_BUILTIN_MOVF_C_LE_PS:
- case MIPS_BUILTIN_MOVF_C_NGT_PS:
- case MIPS_BUILTIN_MOVF_CABS_F_PS:
- case MIPS_BUILTIN_MOVF_CABS_UN_PS:
- case MIPS_BUILTIN_MOVF_CABS_EQ_PS:
- case MIPS_BUILTIN_MOVF_CABS_UEQ_PS:
- case MIPS_BUILTIN_MOVF_CABS_OLT_PS:
- case MIPS_BUILTIN_MOVF_CABS_ULT_PS:
- case MIPS_BUILTIN_MOVF_CABS_OLE_PS:
- case MIPS_BUILTIN_MOVF_CABS_ULE_PS:
- case MIPS_BUILTIN_MOVF_CABS_SF_PS:
- case MIPS_BUILTIN_MOVF_CABS_NGLE_PS:
- case MIPS_BUILTIN_MOVF_CABS_SEQ_PS:
- case MIPS_BUILTIN_MOVF_CABS_NGL_PS:
- case MIPS_BUILTIN_MOVF_CABS_LT_PS:
- case MIPS_BUILTIN_MOVF_CABS_NGE_PS:
- case MIPS_BUILTIN_MOVF_CABS_LE_PS:
- case MIPS_BUILTIN_MOVF_CABS_NGT_PS:
- return mips_expand_ps_cond_move_builtin (MIPS_CMP_MOVF, target,
- fcode, arglist);
-
- default:
- break;
- }
+ DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT)
+};
- return 0;
-}
+/* Builtin functions for DSP ASE. */
+
+#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3
+#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3
+#define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3
+#define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3
+
+/* Define a MIPS_BUILTIN_DIRECT_NO_TARGET function for instruction
+ CODE_FOR_mips_<INSN>. FUNCTION_TYPE and TARGET_FLAGS are
+ builtin_description fields. */
+#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
+ MIPS_BUILTIN_DIRECT_NO_TARGET, FUNCTION_TYPE, TARGET_FLAGS }
+
+/* Define __builtin_mips_bposge<VALUE>. <VALUE> is 32 for the MIPS32 DSP
+ branch instruction. TARGET_FLAGS is a builtin_description field. */
+#define BPOSGE_BUILTIN(VALUE, TARGET_FLAGS) \
+ { CODE_FOR_mips_bposge, 0, "__builtin_mips_bposge" #VALUE, \
+ MIPS_BUILTIN_BPOSGE ## VALUE, MIPS_SI_FTYPE_VOID, TARGET_FLAGS }
+
+static const struct builtin_description dsp_bdesc[] =
+{
+ DIRECT_BUILTIN (addq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (subu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addsc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addwc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (modsub, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (raddu_w_qb, MIPS_SI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_ph, MIPS_V2HI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_w, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_rs_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrqu_s_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phl, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phr, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (shll_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shrl_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbl, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbr, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulq_rs_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phl, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phr, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulsaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (bitrev, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (insv, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_qb, MIPS_V4QI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_ph, MIPS_V2HI_FTYPE_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_eq_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_lt_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_le_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_eq_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_lt_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_le_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_eq_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_lt_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_le_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (pick_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (pick_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (packrl_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (extr_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_r_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_rs_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_s_h, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (wrdsp, MIPS_VOID_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (rddsp, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (lbux, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lhx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lwx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ BPOSGE_BUILTIN (32, MASK_DSP)
+};
-/* Init builtin functions. This is called from TARGET_INIT_BUILTIN. */
+/* This helps provide a mapping from builtin function codes to bdesc
+ arrays. */
-void
-mips_init_builtins (void)
+struct bdesc_map
{
- const struct builtin_description *d;
- size_t i;
- tree v2sf_ftype_v2sf_v2sf;
- tree v2sf_ftype_sf_sf;
- tree sf_ftype_v2sf;
- tree v2sf_ftype_v2sf;
- tree int_ftype_v2sf_v2sf;
- tree int_ftype_v2sf_v2sf_v2sf_v2sf;
- tree v2sf_ftype_v2sf_v2sf_int;
- tree int_ftype_sf_sf;
- tree int_ftype_df_df;
- tree sf_ftype_sf;
- tree df_ftype_df;
- tree sf_ftype_sf_sf;
- tree df_ftype_df_df;
- tree v2sf_ftype_v2sf_v2sf_v2sf_v2sf;
- tree V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
-
- /* We have only builtins for -mpaired-single and -mips3d. */
- if (!TARGET_PAIRED_SINGLE_FLOAT)
- return;
+ /* The builtin function table that this entry describes. */
+ const struct builtin_description *bdesc;
- int_ftype_sf_sf
- = build_function_type_list (integer_type_node,
- float_type_node, float_type_node,
- NULL_TREE);
+ /* The number of entries in the builtin function table. */
+ unsigned int size;
- int_ftype_df_df
- = build_function_type_list (integer_type_node,
- double_type_node, double_type_node,
- NULL_TREE);
+ /* The target processor that supports these builtin functions.
+ PROCESSOR_MAX means we enable them for all processors. */
+ enum processor_type proc;
+};
- v2sf_ftype_v2sf_v2sf
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+static const struct bdesc_map bdesc_arrays[] =
+{
+ { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_MAX },
+ { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 },
+ { dsp_bdesc, ARRAY_SIZE (dsp_bdesc), PROCESSOR_MAX }
+};
- v2sf_ftype_sf_sf
- = build_function_type_list (V2SF_type_node,
- float_type_node, float_type_node,
- NULL_TREE);
+/* Take the head of argument list *ARGLIST and convert it into a form
+ suitable for input operand OP of instruction ICODE. Return the value
+ and point *ARGLIST at the next element of the list. */
- sf_ftype_v2sf
- = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
+static rtx
+mips_prepare_builtin_arg (enum insn_code icode,
+ unsigned int op, tree *arglist)
+{
+ rtx value;
+ enum machine_mode mode;
- v2sf_ftype_v2sf
- = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
+ value = expand_normal (TREE_VALUE (*arglist));
+ mode = insn_data[icode].operand[op].mode;
+ if (!insn_data[icode].operand[op].predicate (value, mode))
+ {
+ value = copy_to_mode_reg (mode, value);
+ /* Check the predicate again. */
+ if (!insn_data[icode].operand[op].predicate (value, mode))
+ {
+ error ("invalid argument to builtin function");
+ return const0_rtx;
+ }
+ }
- int_ftype_v2sf_v2sf
- = build_function_type_list (integer_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+ *arglist = TREE_CHAIN (*arglist);
+ return value;
+}
- int_ftype_v2sf_v2sf_v2sf_v2sf
- = build_function_type_list (integer_type_node,
- V2SF_type_node, V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+/* Return an rtx suitable for output operand OP of instruction ICODE.
+ If TARGET is non-null, try to use it where possible. */
- v2sf_ftype_v2sf_v2sf_v2sf_v2sf
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+static rtx
+mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
+{
+ enum machine_mode mode;
- v2sf_ftype_v2sf_v2sf_int
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node,
- integer_type_node, NULL_TREE);
+ mode = insn_data[icode].operand[op].mode;
+ if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
+ target = gen_reg_rtx (mode);
- sf_ftype_sf
- = build_function_type_list (float_type_node,
- float_type_node, NULL_TREE);
+ return target;
+}
- df_ftype_df
- = build_function_type_list (double_type_node,
- double_type_node, NULL_TREE);
+/* Expand builtin functions. This is called from TARGET_EXPAND_BUILTIN. */
- sf_ftype_sf_sf
- = build_function_type_list (float_type_node,
- float_type_node, float_type_node,
- NULL_TREE);
+rtx
+mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ enum insn_code icode;
+ enum mips_builtin_type type;
+ tree fndecl, arglist;
+ unsigned int fcode;
+ const struct builtin_description *bdesc;
+ const struct bdesc_map *m;
- df_ftype_df_df
- = build_function_type_list (double_type_node,
- double_type_node, double_type_node,
- NULL_TREE);
+ fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ arglist = TREE_OPERAND (exp, 1);
+ fcode = DECL_FUNCTION_CODE (fndecl);
- for (i = 0, d = mips_bdesc; i < ARRAY_SIZE (mips_bdesc); i++, d++)
+ bdesc = NULL;
+ for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
{
- if ((d->target_flags & MASK_PAIRED_SINGLE)
- && !TARGET_PAIRED_SINGLE_FLOAT)
- continue;
-
- if ((d->target_flags & MASK_MIPS3D)
- && !TARGET_MIPS3D)
- continue;
-
- switch (d->ftype)
+ if (fcode < m->size)
{
- case MIPS_V2SF_FTYPE_V2SF_V2SF:
- lang_hooks.builtin_function (d->name, v2sf_ftype_v2sf_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
+ bdesc = m->bdesc;
+ icode = bdesc[fcode].icode;
+ type = bdesc[fcode].builtin_type;
break;
+ }
+ fcode -= m->size;
+ }
+ if (bdesc == NULL)
+ return 0;
- case MIPS_V2SF_FTYPE_SF_SF:
- lang_hooks.builtin_function (d->name, v2sf_ftype_sf_sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ switch (type)
+ {
+ case MIPS_BUILTIN_DIRECT:
+ return mips_expand_builtin_direct (icode, target, arglist, true);
- case MIPS_SF_FTYPE_V2SF:
- lang_hooks.builtin_function (d->name, sf_ftype_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ case MIPS_BUILTIN_DIRECT_NO_TARGET:
+ return mips_expand_builtin_direct (icode, target, arglist, false);
- case MIPS_V2SF_FTYPE_V2SF:
- lang_hooks.builtin_function (d->name, v2sf_ftype_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ case MIPS_BUILTIN_MOVT:
+ case MIPS_BUILTIN_MOVF:
+ return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond,
+ target, arglist);
- case MIPS_INT_FTYPE_V2SF_V2SF:
- lang_hooks.builtin_function (d->name, int_ftype_v2sf_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ case MIPS_BUILTIN_CMP_ANY:
+ case MIPS_BUILTIN_CMP_ALL:
+ case MIPS_BUILTIN_CMP_UPPER:
+ case MIPS_BUILTIN_CMP_LOWER:
+ case MIPS_BUILTIN_CMP_SINGLE:
+ return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
+ target, arglist);
- case MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF:
- lang_hooks.builtin_function (d->name, int_ftype_v2sf_v2sf_v2sf_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ case MIPS_BUILTIN_BPOSGE32:
+ return mips_expand_builtin_bposge (type, target);
- case MIPS_V2SF_FTYPE_V2SF_V2SF_INT:
- lang_hooks.builtin_function (d->name, v2sf_ftype_v2sf_v2sf_int,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ default:
+ return 0;
+ }
+}
- case MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF:
- lang_hooks.builtin_function (d->name, v2sf_ftype_v2sf_v2sf_v2sf_v2sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+/* Init builtin functions. This is called from TARGET_INIT_BUILTIN. */
- case MIPS_SF_FTYPE_SF:
- lang_hooks.builtin_function (d->name, sf_ftype_sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+void
+mips_init_builtins (void)
+{
+ const struct builtin_description *d;
+ const struct bdesc_map *m;
+ tree types[(int) MIPS_MAX_FTYPE_MAX];
+ tree V2SF_type_node;
+ tree V2HI_type_node;
+ tree V4QI_type_node;
+ unsigned int offset;
+
+ /* We have only builtins for -mpaired-single, -mips3d and -mdsp. */
+ if (!TARGET_PAIRED_SINGLE_FLOAT && !TARGET_DSP)
+ return;
- case MIPS_DF_FTYPE_DF:
- lang_hooks.builtin_function (d->name, df_ftype_df,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ if (TARGET_PAIRED_SINGLE_FLOAT)
+ {
+ V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
- case MIPS_INT_FTYPE_SF_SF:
- lang_hooks.builtin_function (d->name, int_ftype_sf_sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ types[MIPS_V2SF_FTYPE_V2SF]
+ = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
- case MIPS_INT_FTYPE_DF_DF:
- lang_hooks.builtin_function (d->name, int_ftype_df_df,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- case MIPS_SF_FTYPE_SF_SF:
- lang_hooks.builtin_function (d->name, sf_ftype_sf_sf,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ integer_type_node, NULL_TREE);
- case MIPS_DF_FTYPE_DF_DF:
- lang_hooks.builtin_function (d->name, df_ftype_df_df,
- d->code, BUILT_IN_MD, NULL, NULL_TREE);
- break;
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- default:
- break;
- }
- }
-}
+ types[MIPS_V2SF_FTYPE_SF_SF]
+ = build_function_type_list (V2SF_type_node,
+ float_type_node, float_type_node, NULL_TREE);
-/* This performs a paired single compare, and then a conditional move based
- on the result of that compare. CMP_CHOICE is the kind of comparison we
- want. TARGET is a suggestion of where to put the result. FCODE is the
- function code. ARGLIST is the list of arguments. The return value is
- the result of the conditional move. */
+ types[MIPS_INT_FTYPE_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
-static rtx
-mips_expand_ps_cond_move_builtin (enum mips_cmp_choice cmp_choice,
- rtx target, unsigned int fcode,
- tree arglist)
-{
- rtx pat;
- enum insn_code icode;
- tree arg0;
- tree arg1;
- tree arg2;
- tree arg3;
- rtx op0;
- rtx op1;
- rtx op2;
- rtx op3;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- rtx temp_target;
- rtx src1;
- rtx src2;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
- op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
-
- icode = mips_bdesc[fcode].icode;
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
-
- 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);
-
- /* temp_target is the result of the comparison. */
- temp_target = gen_reg_rtx (tmode);
-
- pat = GEN_FCN (icode) (temp_target, op0, op1);
- if (!pat)
- return 0;
+ types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- emit_insn (pat);
+ types[MIPS_INT_FTYPE_SF_SF]
+ = build_function_type_list (integer_type_node,
+ float_type_node, float_type_node, NULL_TREE);
- icode = CODE_FOR_mips_cond_move_tf_ps;
- tmode = insn_data[icode].operand[0].mode;
+ types[MIPS_INT_FTYPE_DF_DF]
+ = build_function_type_list (integer_type_node,
+ double_type_node, double_type_node, NULL_TREE);
- if (target == 0
- || GET_MODE (target) != tmode
- || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
+ types[MIPS_SF_FTYPE_V2SF]
+ = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, float_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, double_type_node, NULL_TREE);
+ }
+
+ if (TARGET_DSP)
+ {
+ V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
+ V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode);
+
+ types[MIPS_V2HI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V4QI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_SI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI_SI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V4QI_V4QI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V2HI_V2HI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_SI]
+ = build_function_type_list (V4QI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V4QI_V4QI]
+ = build_function_type_list (void_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V2HI_V2HI]
+ = build_function_type_list (void_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_DI_SI]
+ = build_function_type_list (intSI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_SI_SI]
+ = build_function_type_list (void_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_PTR_SI]
+ = build_function_type_list (intSI_type_node,
+ ptr_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_VOID]
+ = build_function_type (intSI_type_node, void_list_node);
+ }
+
+ /* Iterate through all of the bdesc arrays, initializing all of the
+ builtin functions. */
+
+ offset = 0;
+ for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
+ {
+ if (m->proc == PROCESSOR_MAX || (m->proc == mips_arch))
+ for (d = m->bdesc; d < &m->bdesc[m->size]; d++)
+ if ((d->target_flags & target_flags) == d->target_flags)
+ lang_hooks.builtin_function (d->name, types[d->function_type],
+ d - m->bdesc + offset,
+ BUILT_IN_MD, NULL, NULL);
+ offset += m->size;
+ }
+}
+
+/* Expand a MIPS_BUILTIN_DIRECT function. ICODE is the code of the
+ .md pattern and ARGLIST is the list of function arguments. TARGET,
+ if nonnull, suggests a good place to put the result.
+ HAS_TARGET indicates the function must return something. */
- /* Let op2 be the same as the tmode */
- if (!(*insn_data[icode].operand[0].predicate) (op2, tmode))
- op2 = copy_to_mode_reg (tmode, op2);
+static rtx
+mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist,
+ bool has_target)
+{
+ rtx ops[MAX_RECOG_OPERANDS];
+ int i = 0;
- /* Let op3 be the same as the tmode */
- if (!(*insn_data[icode].operand[0].predicate) (op3, tmode))
- op3 = copy_to_mode_reg (tmode, op3);
+ if (has_target)
+ {
+ /* We save target to ops[0]. */
+ ops[0] = mips_prepare_builtin_target (icode, 0, target);
+ i = 1;
+ }
- /* Copy op2 to target */
- emit_insn (gen_rtx_SET (tmode, target, op2));
+ /* We need to test if arglist is not zero. Some instructions have extra
+ clobber registers. */
+ for (; i < insn_data[icode].n_operands && arglist != 0; i++)
+ ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
- switch (cmp_choice)
+ switch (i)
{
- case MIPS_CMP_MOVT:
- src1 = op3;
- src2 = target;
+ case 2:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
break;
- case MIPS_CMP_MOVF:
- src1 = target;
- src2 = op3;
+ case 3:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
+ break;
+
+ case 4:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
break;
default:
- return 0;
+ gcc_unreachable ();
}
+ return target;
+}
+
+/* Expand a __builtin_mips_movt_*_ps() or __builtin_mips_movf_*_ps()
+ function (TYPE says which). ARGLIST is the list of arguments to the
+ function, ICODE is the instruction that should be used to compare
+ the first two arguments, and COND is the condition it should test.
+ TARGET, if nonnull, suggests a good place to put the result. */
+
+static rtx
+mips_expand_builtin_movtf (enum mips_builtin_type type,
+ enum insn_code icode, enum mips_fp_condition cond,
+ rtx target, tree arglist)
+{
+ rtx cmp_result, op0, op1;
- emit_insn (gen_mips_cond_move_tf_ps (target, src1, src2, temp_target));
+ cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond)));
+ icode = CODE_FOR_mips_cond_move_tf_ps;
+ target = mips_prepare_builtin_target (icode, 0, target);
+ if (type == MIPS_BUILTIN_MOVT)
+ {
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ }
+ else
+ {
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ }
+ emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result));
return target;
}
-/* This performs two paired single compares, and returns an boolean value to
- represent the result of the compare. CMP_CHOICE is the kind of comparison
- we want. TARGET is a suggestion of where to put the result. FCODE is
- the builtin function code. ARGLIST is the list of arguments. The
- return value is the result of the compare. */
+/* Expand a comparison builtin of type BUILTIN_TYPE. ICODE is the code
+ of the comparison instruction and COND is the condition it should test.
+ ARGLIST is the list of function arguments and TARGET, if nonnull,
+ suggests a good place to put the boolean result. */
-rtx
-mips_expand_4s_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
- unsigned int fcode, tree arglist)
+static rtx
+mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
+ enum insn_code icode, enum mips_fp_condition cond,
+ rtx target, tree arglist)
{
- rtx pat;
- enum insn_code icode;
- tree arg0;
- tree arg1;
- tree arg2;
- tree arg3;
- rtx op0;
- rtx op1;
- rtx op2;
- rtx op3;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- enum machine_mode mode2;
- enum machine_mode mode3;
- rtx temp_target;
- rtx label1;
- rtx label2;
- rtx if_then_else;
- int compare_value;
+ rtx label1, label2, if_then_else;
+ rtx pat, cmp_result, ops[MAX_RECOG_OPERANDS];
+ rtx target_if_equal, target_if_unequal;
+ int cmp_value, i;
if (target == 0 || GET_MODE (target) != SImode)
target = gen_reg_rtx (SImode);
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
- op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
- mode2 = insn_data[icode].operand[3].mode;
- mode3 = insn_data[icode].operand[4].mode;
-
- temp_target = gen_reg_rtx (tmode);
-
- 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 (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
- op2 = copy_to_mode_reg (mode2, op2);
-
- if (!(*insn_data[icode].operand[4].predicate) (op3, mode3))
- op3 = copy_to_mode_reg (mode3, op3);
-
- pat = GEN_FCN (icode) (temp_target, op0, op1, op2, op3);
- if (!pat)
- return 0;
+ /* Prepare the operands to the comparison. */
+ cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+ for (i = 1; i < insn_data[icode].n_operands - 1; i++)
+ ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
- /* We fake the value of CCV4 to be:
- 0 if all registers are false.
- -1 if all registers are true.
- an indeterminate value otherse.
-
- Thus, we can map "enum mips_cmp_choice" to RTL comparison operators:
- MIPS_CMP_ANY -> (NE 0)
- MIPS_CMP_ALL -> (EQ -1).
-
- However, because MIPS doesn't have "branch_all" instructions,
- for MIPS_CMP_ALL, we will use (NE -1) and reverse the assignment of
- the target to 1 first and then 0. */
- switch (cmp_choice)
- {
- case MIPS_CMP_ANY:
- compare_value = 0;
+ switch (insn_data[icode].n_operands)
+ {
+ case 4:
+ pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond));
break;
- case MIPS_CMP_ALL:
- compare_value = -1;
+ case 6:
+ pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2],
+ ops[3], ops[4], GEN_INT (cond));
break;
default:
- return 0;
+ gcc_unreachable ();
}
- if (cmp_choice == MIPS_CMP_ALL)
- emit_move_insn (target, const1_rtx);
+ /* If the comparison sets more than one register, we define the result
+ to be 0 if all registers are false and -1 if all registers are true.
+ The value of the complete result is indeterminate otherwise. It is
+ possible to test individual registers using SUBREGs.
+
+ Set up CMP_RESULT, CMP_VALUE, TARGET_IF_EQUAL and TARGET_IF_UNEQUAL so
+ that the result should be TARGET_IF_EQUAL if (EQ CMP_RESULT CMP_VALUE)
+ and TARGET_IF_UNEQUAL otherwise. */
+ if (builtin_type == MIPS_BUILTIN_CMP_ALL)
+ {
+ cmp_value = -1;
+ target_if_equal = const1_rtx;
+ target_if_unequal = const0_rtx;
+ }
else
- emit_move_insn (target, const0_rtx);
+ {
+ cmp_value = 0;
+ target_if_equal = const0_rtx;
+ target_if_unequal = const1_rtx;
+ if (builtin_type == MIPS_BUILTIN_CMP_UPPER)
+ cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 4);
+ else if (builtin_type == MIPS_BUILTIN_CMP_LOWER)
+ cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 0);
+ }
- emit_insn (pat);
+ /* First assume that CMP_RESULT == CMP_VALUE. */
+ emit_move_insn (target, target_if_equal);
+ /* Branch to LABEL1 if CMP_RESULT != CMP_VALUE. */
+ emit_insn (pat);
label1 = gen_label_rtx ();
label2 = gen_label_rtx ();
- if_then_else
+ if_then_else
= gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_fmt_ee (NE, CCV4mode, temp_target,
- GEN_INT (compare_value)),
+ gen_rtx_fmt_ee (NE, GET_MODE (cmp_result),
+ cmp_result, GEN_INT (cmp_value)),
gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_LABEL_REF (VOIDmode, label2)));
-
emit_barrier ();
emit_label (label1);
- if (cmp_choice == MIPS_CMP_ALL)
- emit_move_insn (target, const0_rtx);
- else
- emit_move_insn (target, const1_rtx);
-
+ /* Fix TARGET for CMP_RESULT != CMP_VALUE. */
+ emit_move_insn (target, target_if_unequal);
emit_label (label2);
return target;
}
-/* This performs a single float or double float comparison. TARGET is a
- suggestion of where to put the result. FCODE is the builtin function code.
- ARGLIST is the list of arguments. The return value is the result of the
- compare. */
+/* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull,
+ suggests a good place to put the boolean result.
-rtx
-mips_expand_compare_builtin (rtx target, unsigned int fcode, tree arglist)
+ The sequence we want is
+
+ li target, 0
+ bposge* label1
+ j label2
+ label1:
+ li target, 1
+ label2: */
+
+static rtx
+mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
{
- rtx pat;
- enum insn_code icode;
- tree arg0;
- tree arg1;
- rtx op0;
- rtx op1;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- rtx temp_target;
- rtx label1;
- rtx label2;
- rtx if_then_else;
- enum rtx_code test_code;
+ rtx label1, label2, if_then_else;
+ rtx cmp_result;
+ int cmp_value;
if (target == 0 || GET_MODE (target) != SImode)
target = gen_reg_rtx (SImode);
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
-
- temp_target = gen_reg_rtx (tmode);
+ cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM);
- 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);
-
- pat = GEN_FCN (icode) (temp_target, op0, op1);
- if (!pat)
- return 0;
+ if (builtin_type == MIPS_BUILTIN_BPOSGE32)
+ cmp_value = 32;
+ else
+ gcc_assert (0);
+ /* Move 0 to target */
emit_move_insn (target, const0_rtx);
- emit_insn (pat);
+ /* Generate two labels */
label1 = gen_label_rtx ();
label2 = gen_label_rtx ();
- test_code = NE;
+ /* Generate if_then_else */
if_then_else
= gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_fmt_ee (test_code, CCmode,
- temp_target, const0_rtx),
+ gen_rtx_fmt_ee (GE, CCDSPmode,
+ cmp_result, GEN_INT (cmp_value)),
gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
- gen_rtx_LABEL_REF (VOIDmode, label2)));
-
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
emit_barrier ();
emit_label (label1);
emit_move_insn (target, const1_rtx);
return target;
}
+\f
+/* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL.
+ FIRST is true if this is the first time handling this decl. */
-/* This performs a paired single compare, and returns an boolean value to
- represent the result of the compare. CMP_CHOICE is the kind of comparison
- we want. TARGET is a suggestion of where to put the result. FCODE is
- the builtin function code. ARGLIST is the list of arguments. The
- return value is the result of the compare. */
-
-rtx
-mips_expand_ps_compare_builtin (enum mips_cmp_choice cmp_choice, rtx target,
- unsigned int fcode, tree arglist)
+static void
+mips_encode_section_info (tree decl, rtx rtl, int first)
{
- rtx pat;
- enum insn_code icode;
- tree arg0;
- tree arg1;
- rtx op0;
- rtx op1;
- enum machine_mode tmode;
- enum machine_mode mode0;
- enum machine_mode mode1;
- rtx temp_target;
- rtx label1;
- rtx label2;
- rtx if_then_else;
- int compare_value;
-
- if (target == 0 || GET_MODE (target) != SImode)
- target = gen_reg_rtx (SImode);
-
- icode = mips_bdesc[fcode].icode;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
-
- temp_target = gen_reg_rtx (tmode);
-
- 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);
+ default_encode_section_info (decl, rtl, first);
- pat = GEN_FCN (icode) (temp_target, op0, op1);
- if (!pat)
- return 0;
-
- /* We fake the value of CCV2 to be:
- 0 if all registers are false.
- -1 if all registers are true.
- an indeterminate value otherse.
-
- Thus, we can map "enum mips_cmp_choice" to RTL comparison operators:
- MIPS_CMP_ANY -> (NE 0)
- MIPS_CMP_ALL -> (EQ -1).
-
- However, because MIPS doesn't have "branch_all" instructions,
- for MIPS_CMP_ALL, we will use (NE -1) and reverse the assignment of
- the target to 1 first and then 0.
-
- We handle MIPS_CMP_LOWER and MIPS_CMP_UPPER by taking the appropriate
- CCmode subreg and comparing against zero in the normal way. */
- switch (cmp_choice)
- {
- case MIPS_CMP_ANY:
- compare_value = 0;
- break;
-
- case MIPS_CMP_UPPER:
- temp_target = simplify_gen_subreg (CCmode, temp_target, CCV2mode, 4);
- compare_value = 0;
- break;
-
- case MIPS_CMP_LOWER:
- temp_target = simplify_gen_subreg (CCmode, temp_target, CCV2mode, 0);
- compare_value = 0;
- break;
-
- case MIPS_CMP_ALL:
- compare_value = -1;
- break;
-
- default:
- return 0;
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+ {
+ rtx symbol = XEXP (rtl, 0);
+ SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
}
+}
- if (cmp_choice == MIPS_CMP_ALL)
- emit_move_insn (target, const1_rtx);
- else
- emit_move_insn (target, const0_rtx);
-
- emit_insn (pat);
-
- label1 = gen_label_rtx ();
- label2 = gen_label_rtx ();
-
- if_then_else
- = gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_fmt_ee (NE, GET_MODE (temp_target),
- temp_target,
- GEN_INT (compare_value)),
- gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
- gen_rtx_LABEL_REF (VOIDmode, label2)));
-
- emit_barrier ();
- emit_label (label1);
-
- if (cmp_choice == MIPS_CMP_ALL)
- emit_move_insn (target, const0_rtx);
- else
- emit_move_insn (target, const1_rtx);
-
- emit_label (label2);
+/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. TARGET_ABICALLS makes
+ PIC_FUNCTION_ADDR_REGNUM live on entry to a function. */
- return target;
+static void
+mips_extra_live_on_entry (bitmap regs)
+{
+ if (!TARGET_ABICALLS)
+ bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
}
+
\f
#include "gt-mips.h"