diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 84b62a9fdb3..a4d02b4b8ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,52 @@ +Mon Jul 1 19:55:17 2002 J"orn Rennecke + + * sh.c (langhooks.h): Include. + (sh_init_builtins, sh_media_init_builtins): New functions. + (sh_expand_builtin, arith_reg_dest,and_operand): Likewise. + (mextr_bit_offset, extend_reg_operand, zero_vec_operand): Likewise. + (sh_rep_vec, sh_1el_vec, sh_const_vec): Likewise. + (builtin_description): New struct tag. + (signature_args, bdesc): New arrays. + (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Undef / define. + (print_operand): Add 'N' modifier. + * sh.h (VECTOR_MODE_SUPPORTED_P): Add SHmedia vector modes. + (EXTRA_CONSTRAINT_U, EXTRA_CONSTRAINT_W): New macros. + (EXTRA_CONSTRAINT): Add 'U' and 'W' cases. + (CONST_COSTS): Add special case for SHmedia AND. + (PREDICATE_CODES): Add and_operand, arith_reg_dest, + extend_reg_operand, extend_reg_or_0_operand, mextr_bit_offset, + sh_const_vec, sh_1el_vec, sh_rep_vec, zero_vec_operand. + target_operand can also be const or unspec. + * sh.md (UNSPEC_INIT_TRAMP, UNSPEC_FCOSA UNSPEC_FSRRA): New constants. + (UNSPEC_FSINA, UNSPEC_NSB, UNSPEC_ALLOCO): Likewise. + (attribute type): Add new types. + (anddi3): Add splitter. + (movdi_const_16bit+1): Add code to handle vector constants and + bitmasks efficiently. + (shori_media): Have generator function made. + (movv8qi, movv8qi_i, movv8qi_i+1, movv8qi_i+2): New patterns. + (movv8qi_i+3, movv2hi, movv2hi_i, movv4hi, movv4hi_i): Likewise. + (movv2si, movv2si_i, absv2si2, absv4hi2, addv2si3, addv4hi3): Likewise. + (ssaddv2si3, usaddv8qi3, ssaddv4hi3, negcmpeqv8qi): Likewise. + (negcmpeqv2si, negcmpeqv4hi, negcmpgtuv8qi, negcmpgtv2si): Likewise. + (negcmpgtv4hi, mcmv, mcnvs_lw, mcnvs_wb, mcnvs_wub): Likewise. + (mextr_rl, mextr_lr, mextr1, mextr2, mextr3, mextr4, mextr5): Likewise. + (mextr6, mextr7, mmacfx_wl, mmacfx_wl_i, mmacnfx_wl): Likewise. + (mmacnfx_wl_i, mulv2si3, mulv4hi3, mmulfx_l, mmulfx_w): Likewise. + (mmulfxrp_w, mmulhi_wl, mmullo_wl, mmul23_wl, mmul01_wl): Likewise. + (mmulsum_wq, mmulsum_wq_i, mperm_w, mperm_w_little): LIkewise. + (mperm_w_big, mperm_w0, msad_ubq, msad_ubq_i, mshalds_l): Likewise. + (mshalds_w, ashrv2si3, ashrv4hi3, mshards_q, mshfhi_b): Likewise. + (mshflo_b, mshf4_b, mshf0_b, mshfhi_l, mshflo_l, mshf4_l): Likewsie. + (mshf0_l, mshfhi_w, mshflo_w, mshf4_w, mshf0_w, mshfhi_l_di): Likewise. + (mshfhi_l_di_rev, mshflo_l_di, mshflo_l_di_rev): Likewise. + (mshflo_l_di_x, mshflo_l_di_x_rev, ashlv2si3, ashlv4hi3): Likewise. + (lshrv2si3, lshrv4hi3, subv2si3, subv4hi3, sssubv2si3): Likewise. + (ussubv8qi3, sssubv4hi3, fcosa_s, fsina_s, fipr, fsrra_s): Likewise. + (ftrv): Likewise. + + (fpu_switch+1, fpu_switch+2): Remove constraint. + 2002-07-01 Aldy Hernandez * tree.c (build_function_type_list): Update function comment. diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index a489dcffd28..429eda6d1e0 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */ #include "target.h" #include "target-def.h" #include "real.h" +#include "langhooks.h" int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch; @@ -204,6 +205,10 @@ static bool sh_ms_bitfield_layout_p PARAMS ((tree)); static void sh_encode_section_info PARAMS ((tree, int)); static const char *sh_strip_name_encoding PARAMS ((const char *)); +static void sh_init_builtins (void); +static void sh_media_init_builtins (void); +static rtx sh_expand_builtin (tree, rtx, rtx, enum machine_mode, int); + /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE @@ -247,6 +252,11 @@ static const char *sh_strip_name_encoding PARAMS ((const char *)); #undef TARGET_STRIP_NAME_ENCODING #define TARGET_STRIP_NAME_ENCODING sh_strip_name_encoding +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS sh_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN sh_expand_builtin + struct gcc_target targetm = TARGET_INITIALIZER; /* Print the operand address in x to the stream. */ @@ -320,6 +330,7 @@ print_operand_address (stream, x) 'S' print the MSW of a dp value - changes if in little endian 'T' print the next word of a dp value - same as 'R' in big endian mode. 'M' print an `x' if `m' will print `base,index'. + 'N' print 'r63' if the operand is (const_int 0). 'm' print a pair `base,offset' or `base,index', for LD and ST. 'u' prints the lowest 16 bits of CONST_INT, as an unsigned value. 'o' output an operator. */ @@ -422,6 +433,13 @@ print_operand (stream, x, code) } break; + case 'N': + if (x == const0_rtx) + { + fprintf ((stream), "r63"); + break; + } + goto default_output; case 'u': if (GET_CODE (x) == CONST_INT) { @@ -430,6 +448,7 @@ print_operand (stream, x, code) } /* Fall through. */ + default_output: default: switch (GET_CODE (x)) { @@ -5846,6 +5865,20 @@ arith_reg_operand (op, mode) return 0; } +/* Like above, but for DImode destinations: forbid paradoxical DImode subregs, + because this would lead to missing sign extensions when truncating from + DImode to SImode. */ +int +arith_reg_dest (op, mode) + rtx op; + enum machine_mode mode; +{ + if (mode == DImode && GET_CODE (op) == SUBREG + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8) + return 0; + return arith_reg_operand (op, mode); +} + int fp_arith_reg_operand (op, mode) rtx op; @@ -5948,6 +5981,25 @@ logical_operand (op, mode) return 0; } +int +and_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (logical_operand (op, mode)) + return 1; + + /* Check mshflo.l / mshflhi.l opportunities. */ + if (TARGET_SHMEDIA + && mode == DImode + && GET_CODE (op) == CONST_INT + && (INTVAL (op) == (unsigned) 0xffffffff + || INTVAL (op) == (HOST_WIDE_INT) -1 << 32)) + return 1; + + return 0; +} + /* Nonzero if OP is a floating point value with value 0.0. */ int @@ -6129,6 +6181,135 @@ target_operand (op, mode) return target_reg_operand (op, mode); } +int +mextr_bit_offset (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + HOST_WIDE_INT i; + + if (GET_CODE (op) != CONST_INT) + return 0; + i = INTVAL (op); + return i >= 1*8 && i <= 7*8 && (i & 7) == 0; +} + +int +extend_reg_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == TRUNCATE + ? arith_operand + : arith_reg_operand) (op, mode); +} + +int +extend_reg_or_0_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == TRUNCATE + ? arith_operand + : arith_reg_or_0_operand) (op, mode); +} + +/* Return nonzero if V is a zero vector matching MODE. */ +int +zero_vec_operand (v, mode) + rtx v; + enum machine_mode mode; +{ + int i; + + if (GET_CODE (v) != PARALLEL + || (GET_MODE (v) != mode && mode != VOIDmode)) + return 0; + for (i = XVECLEN (v, 0) - 1; i >= 0; i--) + if (XVECEXP (v, 0, i) != const0_rtx) + return 0; + return 1; +} + +int +sh_rep_vec (v, mode) + rtx v; + enum machine_mode mode; +{ + int i; + rtx x, y; + + if ((GET_CODE (v) != CONST_VECTOR && GET_CODE (v) != PARALLEL) + || (GET_MODE (v) != mode && mode != VOIDmode)) + return 0; + i = XVECLEN (v, 0) - 2; + x = XVECEXP (v, 0, i + 1); + if (GET_MODE_UNIT_SIZE (mode) == 1) + { + y = XVECEXP (v, 0, i); + for (i -= 2 ; i >= 0; i -= 2) + if (! rtx_equal_p (XVECEXP (v, 0, i + 1), x) + || ! rtx_equal_p (XVECEXP (v, 0, i), y)) + return 0; + } + else + for (; i >= 0; i--) + if (XVECEXP (v, 0, i) != x) + return 0; + return 1; +} + +/* Determine if V is a constant vector matching MODE with only one element + that is not a sign extension. Two byte-sized elements count as one. */ +int +sh_1el_vec (v, mode) + rtx v; + enum machine_mode mode; +{ + int unit_size; + int i, last, least, sign_ix; + rtx sign; + + if (GET_CODE (v) != CONST_VECTOR + || (GET_MODE (v) != mode && mode != VOIDmode)) + return 0; + /* Determine numbers of last and of least significat elements. */ + last = XVECLEN (v, 0) - 1; + least = TARGET_LITTLE_ENDIAN ? 0 : last; + if (GET_CODE (XVECEXP (v, 0, least)) != CONST_INT) + return 0; + sign_ix = least; + if (GET_MODE_UNIT_SIZE (mode) == 1) + sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1; + if (GET_CODE (XVECEXP (v, 0, sign_ix)) != CONST_INT) + return 0; + unit_size = GET_MODE_UNIT_SIZE (GET_MODE (v)); + sign = (INTVAL (XVECEXP (v, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1) + ? constm1_rtx : const0_rtx); + i = XVECLEN (v, 0) - 1; + do + if (i != least && i != sign_ix && XVECEXP (v, 0, i) != sign) + return 0; + while (--i); + return 1; +} + +int +sh_const_vec (v, mode) + rtx v; + enum machine_mode mode; +{ + int i; + + if (GET_CODE (v) != CONST_VECTOR + || (GET_MODE (v) != mode && mode != VOIDmode)) + return 0; + i = XVECLEN (v, 0) - 1; + for (; i >= 0; i--) + if (GET_CODE (XVECEXP (v, 0, i)) != CONST_INT) + return 0; + return 1; +} /* Return the destination address of a branch. */ @@ -6446,8 +6627,8 @@ sh_insn_length_adjustment (insn) /* Instructions with unfilled delay slots take up an extra two bytes for the nop in the delay slot. */ if (((GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER) + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) || GET_CODE (insn) == CALL_INSN || (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC @@ -6588,7 +6769,8 @@ legitimize_pic_address (orig, mode, reg) /* Mark the use of a constant in the literal table. If the constant has multiple labels, make it unique. */ -static rtx mark_constant_pool_use (x) +static rtx +mark_constant_pool_use (x) rtx x; { rtx insn, lab, pattern; @@ -6848,4 +7030,299 @@ sh_strip_name_encoding (str) return str; } + +/* Machine specific built-in functions. */ + +struct builtin_description +{ + const enum insn_code icode; + const char *const name; + int signature; +}; + +/* describe number and signedness of arguments; arg[0] == result + (1: unsigned, 2: signed, 4: don't care, 8: pointer 0: no argument */ +static const char signature_args[][4] = +{ +#define SH_BLTIN_V2SI2 0 + { 4, 4 }, +#define SH_BLTIN_V4HI2 1 + { 4, 4 }, +#define SH_BLTIN_V2SI3 2 + { 4, 4, 4 }, +#define SH_BLTIN_V4HI3 3 + { 4, 4, 4 }, +#define SH_BLTIN_V8QI3 4 + { 4, 4, 4 }, +#define SH_BLTIN_MAC_HISI 5 + { 1, 4, 4, 1 }, +#define SH_BLTIN_SH_HI 6 + { 4, 4, 1 }, +#define SH_BLTIN_SH_SI 7 + { 4, 4, 1 }, +#define SH_BLTIN_V4HI2V2SI 8 + { 4, 4, 4 }, +#define SH_BLTIN_V4HI2V8QI 9 + { 4, 4, 4 }, +#define SH_BLTIN_SISF 10 + { 4, 2 }, +#define SH_BLTIN_LDUA_L 11 + { 2, 8 }, +#define SH_BLTIN_LDUA_Q 12 + { 1, 8 }, +#define SH_BLTIN_STUA_L 13 + { 0, 8, 2 }, +#define SH_BLTIN_STUA_Q 14 + { 0, 8, 1 }, +#define SH_BLTIN_NUM_SHARED_SIGNATURES 15 +#define SH_BLTIN_2 15 +#define SH_BLTIN_SU 15 + { 1, 2 }, +#define SH_BLTIN_3 16 +#define SH_BLTIN_SUS 16 + { 2, 2, 1 }, +#define SH_BLTIN_PSSV 17 + { 0, 8, 2, 2 }, +#define SH_BLTIN_XXUU 18 +#define SH_BLTIN_UUUU 18 + { 1, 1, 1, 1 }, +#define SH_BLTIN_PV 19 + { 0, 8 }, +}; +/* mcmv: operands considered unsigned. */ +/* mmulsum_wq, msad_ubq: result considered unsigned long long. */ +/* mperm: control value considered unsigned int. */ +/* mshalds, mshard, mshards, mshlld, mshlrd: shift count is unsigned int. */ +/* mshards_q: returns signed short. */ +/* nsb: takes long long arg, returns unsigned char. */ +static const struct builtin_description bdesc[] = +{ + { CODE_FOR_absv2si2, "__builtin_absv2si2", SH_BLTIN_V2SI2 }, + { CODE_FOR_absv4hi2, "__builtin_absv4hi2", SH_BLTIN_V4HI2 }, + { CODE_FOR_addv2si3, "__builtin_addv2si3", SH_BLTIN_V2SI3 }, + { CODE_FOR_addv4hi3, "__builtin_addv4hi3", SH_BLTIN_V4HI3 }, + { CODE_FOR_ssaddv2si3,"__builtin_ssaddv2si3", SH_BLTIN_V2SI3 }, + { CODE_FOR_usaddv8qi3,"__builtin_usaddv8qi3", SH_BLTIN_V8QI3 }, + { CODE_FOR_ssaddv4hi3,"__builtin_ssaddv4hi3", SH_BLTIN_V4HI3 }, +#if 0 + { CODE_FOR_alloco32, "__builtin_sh_media_ALLOCO", SH_BLTIN_PV }, + { CODE_FOR_alloco64, "__builtin_sh_media_ALLOCO", SH_BLTIN_PV }, +#endif + { CODE_FOR_negcmpeqv8qi,"__builtin_sh_media_MCMPEQ_B", SH_BLTIN_V8QI3 }, + { CODE_FOR_negcmpeqv2si,"__builtin_sh_media_MCMPEQ_L", SH_BLTIN_V2SI3 }, + { CODE_FOR_negcmpeqv4hi,"__builtin_sh_media_MCMPEQ_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_negcmpgtuv8qi,"__builtin_sh_media_MCMPGT_UB", SH_BLTIN_V8QI3 }, + { CODE_FOR_negcmpgtv2si,"__builtin_sh_media_MCMPGT_L", SH_BLTIN_V2SI3 }, + { CODE_FOR_negcmpgtv4hi,"__builtin_sh_media_MCMPGT_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_mcmv, "__builtin_sh_media_MCMV", SH_BLTIN_UUUU }, + { CODE_FOR_mcnvs_lw, "__builtin_sh_media_MCNVS_LW", SH_BLTIN_3 }, + { CODE_FOR_mcnvs_wb, "__builtin_sh_media_MCNVS_WB", SH_BLTIN_V4HI2V8QI }, + { CODE_FOR_mcnvs_wub, "__builtin_sh_media_MCNVS_WUB", SH_BLTIN_V4HI2V8QI }, + { CODE_FOR_mextr1, "__builtin_sh_media_MEXTR1", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr2, "__builtin_sh_media_MEXTR2", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr3, "__builtin_sh_media_MEXTR3", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr4, "__builtin_sh_media_MEXTR4", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr5, "__builtin_sh_media_MEXTR5", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr6, "__builtin_sh_media_MEXTR6", SH_BLTIN_V8QI3 }, + { CODE_FOR_mextr7, "__builtin_sh_media_MEXTR7", SH_BLTIN_V8QI3 }, + { CODE_FOR_mmacfx_wl, "__builtin_sh_media_MMACFX_WL", SH_BLTIN_MAC_HISI }, + { CODE_FOR_mmacnfx_wl,"__builtin_sh_media_MMACNFX_WL", SH_BLTIN_MAC_HISI }, + { CODE_FOR_mulv2si3, "__builtin_mulv2si3", SH_BLTIN_V2SI3, }, + { CODE_FOR_mulv4hi3, "__builtin_mulv4hi3", SH_BLTIN_V4HI3 }, + { CODE_FOR_mmulfx_l, "__builtin_sh_media_MMULFX_L", SH_BLTIN_V2SI3 }, + { CODE_FOR_mmulfx_w, "__builtin_sh_media_MMULFX_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_mmulfxrp_w,"__builtin_sh_media_MMULFXRP_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_mmulhi_wl, "__builtin_sh_media_MMULHI_WL", SH_BLTIN_V4HI2V2SI }, + { CODE_FOR_mmullo_wl, "__builtin_sh_media_MMULLO_WL", SH_BLTIN_V4HI2V2SI }, + { CODE_FOR_mmulsum_wq,"__builtin_sh_media_MMULSUM_WQ", SH_BLTIN_XXUU }, + { CODE_FOR_mperm_w, "__builtin_sh_media_MPERM_W", SH_BLTIN_SH_HI }, + { CODE_FOR_msad_ubq, "__builtin_sh_media_MSAD_UBQ", SH_BLTIN_XXUU }, + { CODE_FOR_mshalds_l, "__builtin_sh_media_MSHALDS_L", SH_BLTIN_SH_SI }, + { CODE_FOR_mshalds_w, "__builtin_sh_media_MSHALDS_W", SH_BLTIN_SH_HI }, + { CODE_FOR_ashrv2si3, "__builtin_ashrv2si3", SH_BLTIN_SH_SI }, + { CODE_FOR_ashrv4hi3, "__builtin_ashrv4hi3", SH_BLTIN_SH_HI }, + { CODE_FOR_mshards_q, "__builtin_sh_media_MSHARDS_Q", SH_BLTIN_SUS }, + { CODE_FOR_mshfhi_b, "__builtin_sh_media_MSHFHI_B", SH_BLTIN_V8QI3 }, + { CODE_FOR_mshfhi_l, "__builtin_sh_media_MSHFHI_L", SH_BLTIN_V2SI3 }, + { CODE_FOR_mshfhi_w, "__builtin_sh_media_MSHFHI_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_mshflo_b, "__builtin_sh_media_MSHFLO_B", SH_BLTIN_V8QI3 }, + { CODE_FOR_mshflo_l, "__builtin_sh_media_MSHFLO_L", SH_BLTIN_V2SI3 }, + { CODE_FOR_mshflo_w, "__builtin_sh_media_MSHFLO_W", SH_BLTIN_V4HI3 }, + { CODE_FOR_ashlv2si3, "__builtin_ashlv2si3", SH_BLTIN_SH_SI }, + { CODE_FOR_ashlv4hi3, "__builtin_ashlv4hi3", SH_BLTIN_SH_HI }, + { CODE_FOR_lshrv2si3, "__builtin_lshrv2si3", SH_BLTIN_SH_SI }, + { CODE_FOR_lshrv4hi3, "__builtin_lshrv4hi3", SH_BLTIN_SH_HI }, + { CODE_FOR_subv2si3, "__builtin_subv2si3", SH_BLTIN_V2SI3 }, + { CODE_FOR_subv4hi3, "__builtin_subv4hi3", SH_BLTIN_V4HI3 }, + { CODE_FOR_sssubv2si3,"__builtin_sssubv2si3", SH_BLTIN_V2SI3 }, + { CODE_FOR_ussubv8qi3,"__builtin_ussubv8qi3", SH_BLTIN_V8QI3 }, + { CODE_FOR_sssubv4hi3,"__builtin_sssubv4hi3", SH_BLTIN_V4HI3 }, + { CODE_FOR_fcosa_s, "__builtin_sh_media_FCOSA_S", SH_BLTIN_SISF }, + { CODE_FOR_fsina_s, "__builtin_sh_media_FSINA_S", SH_BLTIN_SISF }, + { CODE_FOR_fipr, "__builtin_sh_media_FIPR_S", SH_BLTIN_3 }, + { CODE_FOR_ftrv, "__builtin_sh_media_FTRV_S", SH_BLTIN_3 }, + { CODE_FOR_fsrra_s, "__builtin_sh_media_FSRRA_S", SH_BLTIN_2 }, +#if 0 + { CODE_FOR_ldhi_l, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L }, + { CODE_FOR_ldhi_q, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q }, + { CODE_FOR_ldlo_l, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L }, + { CODE_FOR_ldlo_q, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q }, + { CODE_FOR_sthi_l, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L }, + { CODE_FOR_sthi_q, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q }, + { CODE_FOR_stlo_l, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L }, + { CODE_FOR_stlo_q, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q }, + { CODE_FOR_ldhi_l64, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L }, + { CODE_FOR_ldhi_q64, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q }, + { CODE_FOR_ldlo_l64, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L }, + { CODE_FOR_ldlo_q64, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q }, + { CODE_FOR_sthi_l64, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L }, + { CODE_FOR_sthi_q64, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q }, + { CODE_FOR_stlo_l64, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L }, + { CODE_FOR_stlo_q64, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q }, + { CODE_FOR_nsb, "__builtin_sh_media_NSB", SH_BLTIN_SU }, + { CODE_FOR_byterev, "__builtin_sh_media_BYTEREV", SH_BLTIN_2 }, + { CODE_FOR_prefetch32,"__builtin_sh_media_PREFO", SH_BLTIN_PSSV }, + { CODE_FOR_prefetch64,"__builtin_sh_media_PREFO", SH_BLTIN_PSSV } +#endif +}; + +static void +sh_media_init_builtins () +{ + tree shared[SH_BLTIN_NUM_SHARED_SIGNATURES]; + const struct builtin_description *d; + + bzero (shared, sizeof shared); + for (d = bdesc; d - bdesc < sizeof bdesc / sizeof bdesc[0]; d++) + { + tree type, arg_type; + int signature = d->signature; + int i; + + if (signature < SH_BLTIN_NUM_SHARED_SIGNATURES && shared[signature]) + type = shared[signature]; + else + { + int has_result = signature_args[signature][0] != 0; + + if (signature_args[signature][1] == 8 + && (insn_data[d->icode].operand[has_result].mode != Pmode)) + continue; + if (! TARGET_FPU_ANY + && FLOAT_MODE_P (insn_data[d->icode].operand[0].mode)) + continue; + type = void_list_node; + for (i = 3; ; i--) + { + int arg = signature_args[signature][i]; + int opno = i - 1 + has_result; + + if (arg == 8) + arg_type = ptr_type_node; + else if (arg) + arg_type = ((*lang_hooks.types.type_for_mode) + (insn_data[d->icode].operand[opno].mode, + (arg & 1))); + else if (i) + continue; + else + arg_type = void_type_node; + if (i == 0) + break; + type = tree_cons (NULL_TREE, arg_type, type); + } + type = build_function_type (arg_type, type); + if (signature < SH_BLTIN_NUM_SHARED_SIGNATURES) + shared[signature] = type; + } + builtin_function (d->name, type, d - bdesc, BUILT_IN_MD, NULL); + } +} + +static void +sh_init_builtins () +{ + if (TARGET_SHMEDIA) + sh_media_init_builtins (); +} + +/* Expand an expression EXP that calls a built-in function, + with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ + +static rtx +sh_expand_builtin (exp, target, subtarget, mode, ignore) + tree exp; + rtx target; + rtx subtarget ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; + int ignore; +{ + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree arglist = TREE_OPERAND (exp, 1); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + const struct builtin_description *d = &bdesc[fcode]; + enum insn_code icode = d->icode; + int signature = d->signature; + enum machine_mode tmode = VOIDmode; + int nop = 0, i; + rtx op[4]; + rtx pat; + + if (signature_args[signature][0]) + { + if (ignore) + return 0; + + tmode = insn_data[icode].operand[0].mode; + if (! target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + op[nop++] = target; + } + else + target = 0; + + for (i = 1; i <= 3; i++, nop++) + { + tree arg; + enum machine_mode opmode, argmode; + + if (! signature_args[signature][i]) + break; + arg = TREE_VALUE (arglist); + arglist = TREE_CHAIN (arglist); + opmode = insn_data[icode].operand[nop].mode; + argmode = TYPE_MODE (TREE_TYPE (arg)); + if (argmode != opmode) + arg = build1 (NOP_EXPR, + (*lang_hooks.types.type_for_mode) (opmode, 0), arg); + op[nop] = expand_expr (arg, NULL_RTX, opmode, 0); + if (! (*insn_data[icode].operand[nop].predicate) (op[nop], opmode)) + op[nop] = copy_to_mode_reg (opmode, op[nop]); + } + + switch (nop) + { + case 1: + pat = (*insn_data[d->icode].genfun) (op[0]); + break; + case 2: + pat = (*insn_data[d->icode].genfun) (op[0], op[1]); + break; + case 3: + pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2]); + break; + case 4: + pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2], op[3]); + break; + } + if (! pat) + return 0; + emit_insn (pat); + return target; +} #include "gt-sh.h" diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index faf030c3612..abf9945a330 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -924,8 +924,11 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \ /* Value is 1 if MODE is a supported vector mode. */ #define VECTOR_MODE_SUPPORTED_P(MODE) \ - (TARGET_FPU_ANY \ - && ((MODE) == V2SFmode || (MODE) == V4SFmode || (MODE) == V16SFmode)) + ((TARGET_FPU_ANY \ + && ((MODE) == V2SFmode || (MODE) == V4SFmode || (MODE) == V16SFmode)) \ + || (TARGET_SHMEDIA \ + && ((MODE) == V8QImode || (MODE) == V2HImode || (MODE) == V4HImode \ + || (MODE) == V2SImode))) /* Value is 1 if it is a good idea to tie two pseudo registers when one has mode MODE1 and one has mode MODE2. @@ -2312,10 +2315,27 @@ while (0) #define EXTRA_CONSTRAINT_T(OP) \ (NON_PIC_REFERENCE_P (OP)) +/* A zero in any shape or form. */ +#define EXTRA_CONSTRAINT_U(OP) \ + ((OP) == const0_rtx \ + || (GET_CODE (OP) == SUBREG && VECTOR_MODE_SUPPORTED_P(GET_MODE (OP)) \ + && SUBREG_REG (OP) == const0_rtx && SUBREG_BYTE (OP) == 0) \ + || GET_CODE (OP) == CONST_VECTOR && zero_vec_operand ((OP), VOIDmode)) + +/* Any vector constant we can handle. */ +#define EXTRA_CONSTRAINT_W(OP) \ + (GET_CODE (OP) == CONST_VECTOR \ + && (sh_rep_vec ((OP), VOIDmode) \ + || (HOST_BITS_PER_WIDE_INT >= 64 \ + ? sh_const_vec ((OP), VOIDmode) \ + : sh_1el_vec ((OP), VOIDmode)))) + #define EXTRA_CONSTRAINT(OP, C) \ ((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP) \ : (C) == 'S' ? EXTRA_CONSTRAINT_S (OP) \ : (C) == 'T' ? EXTRA_CONSTRAINT_T (OP) \ + : (C) == 'U' ? EXTRA_CONSTRAINT_U (OP) \ + : (C) == 'W' ? EXTRA_CONSTRAINT_W (OP) \ : 0) /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression @@ -2669,6 +2689,8 @@ while (0) case CONST_INT: \ if (TARGET_SHMEDIA) \ { \ + if ((OUTER_CODE) == AND && and_operand ((RTX), DImode)) \ + return 0; \ if (CONST_OK_FOR_J (INTVAL (RTX))) \ return COSTS_N_INSNS (1); \ else if (CONST_OK_FOR_J (INTVAL (RTX) >> 16)) \ @@ -3188,7 +3210,6 @@ extern int current_function_interrupt; extern struct rtx_def *sp_switch; extern int rtx_equal_function_value_matters; -extern struct rtx_def *fpscr_rtx; /* Instructions with unfilled delay slots take up an @@ -3200,23 +3221,32 @@ extern struct rtx_def *fpscr_rtx; /* Define the codes that are matched by predicates in sh.c. */ #define PREDICATE_CODES \ + {"and_operand", {SUBREG, REG, CONST_INT}}, \ {"arith_operand", {SUBREG, REG, CONST_INT}}, \ + {"arith_reg_dest", {SUBREG, REG}}, \ {"arith_reg_operand", {SUBREG, REG}}, \ {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ {"binary_float_operator", {PLUS, MULT}}, \ {"commutative_float_operator", {PLUS, MULT}}, \ + {"extend_reg_operand", {SUBREG, REG, TRUNCATE}}, \ + {"extend_reg_or_0_operand", {SUBREG, REG, TRUNCATE, CONST_INT}}, \ {"fp_arith_reg_operand", {SUBREG, REG}}, \ {"fpscr_operand", {REG}}, \ {"fpul_operand", {REG}}, \ {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \ {"general_movdst_operand", {SUBREG, REG, MEM}}, \ {"logical_operand", {SUBREG, REG, CONST_INT}}, \ + {"mextr_bit_offset", {CONST_INT}}, \ {"noncommutative_float_operator", {MINUS, DIV}}, \ {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}}, \ {"target_reg_operand", {SUBREG, REG}}, \ - {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF}}, \ + {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\ {"register_operand", {SUBREG, REG}}, \ - {"symbol_ref_operand", {SYMBOL_REF}}, + {"sh_const_vec", {CONST_VECTOR}}, \ + {"sh_1el_vec", {CONST_VECTOR, PARALLEL}}, \ + {"sh_rep_vec", {CONST_VECTOR, PARALLEL}}, \ + {"symbol_ref_operand", {SYMBOL_REF}}, \ + {"zero_vec_operand", {CONST_VECTOR}}, /* Define this macro if it is advisable to hold scalars in registers in a wider mode than that declared by the program. In such cases, diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index d4508936b06..8303c962886 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -129,6 +129,12 @@ (UNSPEC_CALLER 10) (UNSPEC_GOTPLT 11) (UNSPEC_ICACHE 12) + (UNSPEC_INIT_TRAMP 13) + (UNSPEC_FCOSA 14) + (UNSPEC_FSRRA 15) + (UNSPEC_FSINA 16) + (UNSPEC_NSB 17) + (UNSPEC_ALLOCO 18) ;; These are used with unspec_volatile. (UNSPECV_BLOCKAGE 0) @@ -197,7 +203,7 @@ ;; nil no-op move, will be deleted. (define_attr "type" - "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pt,ptabs,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,nil" + "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt,ptabs,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other" (const_string "other")) ;; We define a new attribute namely "insn_class".We use @@ -1984,14 +1990,26 @@ } }") -(define_insn "anddi3" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") - (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") - (match_operand:DI 2 "logical_operand" "r,P")))] +(define_insn_and_split "anddi3" + [(set (match_operand:DI 0 "arith_reg_operand" "=r,r,r") + (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r") + (match_operand:DI 2 "and_operand" "r,P,n")))] "TARGET_SHMEDIA" "@ and %1, %2, %0 - andi %1, %2, %0") + andi %1, %2, %0 + #" + "reload_completed + && ! logical_operand (operands[2], DImode)" + [(const_int 0)] + " +{ + if (INTVAL (operands[2]) == (unsigned) 0xffffffff) + emit_insn (gen_mshflo_l_di (operands[0], operands[1], CONST0_RTX (DImode))); + else + emit_insn (gen_mshfhi_l_di (operands[0], CONST0_RTX (DImode), operands[1])); + DONE; +}") (define_insn "*andcdi3" [(set (match_operand:DI 0 "arith_reg_operand" "=r") @@ -3626,28 +3644,95 @@ && GET_CODE (operands[1]) == CONST_INT && ! CONST_OK_FOR_J (INTVAL (operands[1]))" [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) - (ior:DI (ashift:DI (match_dup 0) (const_int 16)) - (zero_extend:DI (truncate:HI (match_dup 1)))))] + (match_dup 1)] " { - unsigned HOST_WIDE_INT low = INTVAL (operands[1]); - unsigned HOST_WIDE_INT val = low; + unsigned HOST_WIDE_INT val = INTVAL (operands[1]); + unsigned HOST_WIDE_INT low = val; + unsigned HOST_WIDE_INT high = val; unsigned HOST_WIDE_INT sign; + unsigned HOST_WIDE_INT val2 = val ^ (val-1); /* Sign-extend the 16 least-significant bits. */ - val &= 0xffff; - val ^= 0x8000; - val -= 0x8000; - operands[1] = GEN_INT (val); + low &= 0xffff; + low ^= 0x8000; + low -= 0x8000; /* Arithmetic shift right the word by 16 bits. */ - low >>= 16; + high >>= 16; sign = 1; sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); - low ^= sign; - low -= sign; - operands[2] = GEN_INT (low); + high ^= sign; + high -= sign; + do + { + /* If we can't generate the constant with a two-insn movi / shori + sequence, try some other strategies. */ + if (! CONST_OK_FOR_J (high)) + { + /* Try constant load / left shift. We know VAL != 0. */ + val2 = val ^ (val-1); + if (val2 > 0x1ffff) + { + int trailing_zeroes = exact_log2 ((val2 >> 16) + 1) + 15; + + if (CONST_OK_FOR_J (val >> trailing_zeroes) + || (! CONST_OK_FOR_J (high >> 16) + && CONST_OK_FOR_J (val >> (trailing_zeroes + 16)))) + { + val2 = (HOST_WIDE_INT) val >> trailing_zeroes; + operands[1] = gen_ashldi3_media (operands[0], operands[0], + GEN_INT (trailing_zeroes)); + break; + } + } + /* Try constant load / right shift. */ + val2 = (val >> 15) + 1; + if (val2 == (val2 & -val2)) + { + int shift = 49 - exact_log2 (val2); + + val2 = trunc_int_for_mode (val << shift, DImode); + if (CONST_OK_FOR_J (val2)) + { + operands[1] = gen_lshrdi3_media (operands[0], operands[0], + GEN_INT (shift)); + break; + } + } + /* Try mperm.w . */ + val2 = val & 0xffff; + if ((val >> 16 & 0xffff) == val2 + && (val >> 32 & 0xffff) == val2 + && (val >> 48 & 0xffff) == val2) + { + val2 = (HOST_WIDE_INT) val >> 48; + operands[1] = gen_rtx_REG (V4HImode, true_regnum (operands[0])); + operands[1] = gen_mperm_w0 (operands[1], operands[1]); + break; + } + /* Try movi / mshflo.l */ + val2 = (HOST_WIDE_INT) val >> 32; + if (val2 == trunc_int_for_mode (val, SImode)) + { + operands[1] = gen_mshflo_l_di (operands[0], operands[0], + operands[0]); + break; + } + /* Try movi / mshflo.l w/ r63. */ + val2 = val + ((HOST_WIDE_INT) -1 << 32); + if ((HOST_WIDE_INT) val2 < 0 && CONST_OK_FOR_J (val2)) + { + operands[1] = gen_mshflo_l_di (operands[0], operands[0], + GEN_INT (0)); + break; + } + } + val2 = high; + operands[1] = gen_shori_media (operands[0], operands[0], GEN_INT (low)); + } + while (0); + operands[2] = GEN_INT (val2); }") (define_split @@ -3690,7 +3775,7 @@ operands[2] = immed_double_const (low, high, DImode); }") -(define_insn "*shori_media" +(define_insn "shori_media" [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0") (const_int 16)) @@ -7507,7 +7592,7 @@ (define_split [(set (reg:PSI FPSCR_REG) - (mem:PSI (match_operand:SI 0 "register_operand" "r")))] + (mem:PSI (match_operand:SI 0 "register_operand" "")))] "TARGET_SH4 && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))" [(set (match_dup 0) (match_dup 0))] " @@ -7521,7 +7606,7 @@ (define_split [(set (reg:PSI FPSCR_REG) - (mem:PSI (match_operand:SI 0 "register_operand" "r")))] + (mem:PSI (match_operand:SI 0 "register_operand" "")))] "TARGET_SH4" [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))] " @@ -8646,6 +8731,1126 @@ "mov.l @r15+,r15\;mov.l @r15+,r0" [(set_attr "length" "4")]) +;; Integer vector moves + +(define_expand "movv8qi" + [(set (match_operand:V8QI 0 "general_movdst_operand" "") + (match_operand:V8QI 1 "general_movsrc_operand" ""))] + "TARGET_SHMEDIA" + "{ if (prepare_move_operands (operands, V8QImode)) DONE; }") + +(define_insn "movv8qi_i" + [(set (match_operand:V8QI 0 "general_movdst_operand" "=r,r,r,rl,m") + (match_operand:V8QI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))] + "TARGET_SHMEDIA + && (register_operand (operands[0], V8QImode) + || register_operand (operands[1], V8QImode))" + "@ + add %1, r63, %0 + movi %1, %0 + # + ld%M1.q %m1, %0 + st%M0.q %m0, %1" + [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") + (set_attr "length" "4,4,16,4,4")]) + +(define_split + [(set (match_operand:V8QI 0 "arith_reg_dest" "") + (subreg:V8QI (const_int 0) 0))] + "TARGET_SHMEDIA" + [(set (match_dup 0) + (const_vector:V8QI [(const_int 0) (const_int 0) (const_int 0) + (const_int 0) (const_int 0) (const_int 0) + (const_int 0) (const_int 0)]))]) + +(define_split + [(set (match_operand 0 "arith_reg_dest" "") + (match_operand 1 "sh_rep_vec" ""))] + "TARGET_SHMEDIA && reload_completed + && GET_MODE (operands[0]) == GET_MODE (operands[1]) + && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0])) + && GET_MODE_SIZE (GET_MODE (operands[0])) == 8 + && (XVECEXP (operands[1], 0, 0) != const0_rtx + || XVECEXP (operands[1], 0, 1) != const0_rtx)" + [(set (match_dup 0) (match_dup 1)) + (match_dup 2)] + " +{ + int unit_size = GET_MODE_UNIT_SIZE (GET_MODE (operands[1])); + rtx elt1 = XVECEXP (operands[1], 0, 1); + + if (unit_size > 2) + operands[2] = gen_mshflo_l (operands[0], operands[0], operands[0]); + else + operands[2] = gen_mperm_w0 (operands[0], operands[0]); + operands[0] = gen_rtx_REG (DImode, true_regnum (operands[0])); + operands[1] = XVECEXP (operands[1], 0, 0); + if (unit_size < 2) + { + if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (elt1) == CONST_INT) + operands[1] = GEN_INT (TARGET_LITTLE_ENDIAN + ? INTVAL (operands[1]) + (INTVAL (elt1) << 8) + : (INTVAL (operands[1]) << 8) + INTVAL (elt1)); + else + { + operands[0] = gen_rtx_REG (V2QImode, true_regnum (operands[0])); + operands[1] + = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, operands[1], elt1)); + } + } +}") + +(define_split + [(set (match_operand 0 "arith_reg_dest" "") + (match_operand 1 "sh_const_vec" ""))] + "TARGET_SHMEDIA && reload_completed + && GET_MODE (operands[0]) == GET_MODE (operands[1]) + && VECTOR_MODE_SUPPORTED_P (GET_MODE (operands[0])) + && XVECEXP (operands[1], 0, 0) != const0_rtx + && (HOST_BITS_PER_WIDE_INT >= 64 + || HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (GET_MODE (operands[0])) + || sh_1el_vec (operands[1], VOIDmode))" + [(set (match_dup 0) (match_dup 1))] + " +{ + rtx v = operands[1]; + enum machine_mode new_mode + = mode_for_size (GET_MODE_BITSIZE (GET_MODE (v)), MODE_INT, 0); + + operands[0] = gen_rtx_REG (new_mode, true_regnum (operands[0])); + operands[1] + = simplify_subreg (new_mode, operands[1], GET_MODE (operands[0]), 0); +}") + +(define_expand "movv2hi" + [(set (match_operand:V2HI 0 "general_movdst_operand" "") + (match_operand:V2HI 1 "general_movsrc_operand" ""))] + "TARGET_SHMEDIA" + "{ if (prepare_move_operands (operands, V2HImode)) DONE; }") + +(define_insn "movv2hi_i" + [(set (match_operand:V2HI 0 "general_movdst_operand" "=r,r,r,rl,m") + (match_operand:V2HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))] + "TARGET_SHMEDIA + && (register_operand (operands[0], V2HImode) + || register_operand (operands[1], V2HImode))" + "@ + addz.l %1, r63, %0 + movi %1, %0 + # + ld%M1.l %m1, %0 + st%M0.l %m0, %1" + [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") + (set_attr "length" "4,4,16,4,4")]) + +(define_expand "movv4hi" + [(set (match_operand:V4HI 0 "general_movdst_operand" "") + (match_operand:V4HI 1 "general_movsrc_operand" ""))] + "TARGET_SHMEDIA" + "{ if (prepare_move_operands (operands, V4HImode)) DONE; }") + +(define_insn "movv4hi_i" + [(set (match_operand:V4HI 0 "general_movdst_operand" "=r,r,r,rl,m") + (match_operand:V4HI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))] + "TARGET_SHMEDIA + && (register_operand (operands[0], V4HImode) + || register_operand (operands[1], V4HImode))" + "@ + add %1, r63, %0 + movi %1, %0 + # + ld%M1.q %m1, %0 + st%M0.q %m0, %1" + [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") + (set_attr "length" "4,4,16,4,4")]) + +(define_expand "movv2si" + [(set (match_operand:V2SI 0 "general_movdst_operand" "") + (match_operand:V2SI 1 "general_movsrc_operand" ""))] + "TARGET_SHMEDIA" + "{ if (prepare_move_operands (operands, V2SImode)) DONE; }") + +(define_insn "movv2si_i" + [(set (match_operand:V2SI 0 "general_movdst_operand" "=r,r,r,rl,m") + (match_operand:V2SI 1 "general_movsrc_operand" "r,JSU,nW,m,rl"))] + "TARGET_SHMEDIA + && (register_operand (operands[0], V2SImode) + || register_operand (operands[1], V2SImode))" + "@ + add %1, r63, %0 + movi %1, %0 + # + ld%M1.q %m1, %0 + st%M0.q %m0, %1" + [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") + (set_attr "length" "4,4,16,4,4")]) + +;; Multimedia Intrinsics + +(define_insn "absv2si2" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mabs.l %1, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "absv4hi2" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mabs.w %1, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "addv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") + (match_operand:V2SI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "madd.l %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "addv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") + (match_operand:V4HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "madd.w %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "ssaddv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_plus:V2SI (match_operand:V2SI 1 "arith_reg_operand" "%r") + (match_operand:V2SI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "madds.l %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "usaddv8qi3" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (us_plus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "%r") + (match_operand:V8QI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "madds.ub %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "ssaddv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ss_plus:V4HI (match_operand:V4HI 1 "arith_reg_operand" "%r") + (match_operand:V4HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "madds.w %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpeqv8qi" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (neg:V8QI (eq:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpeq.b %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpeqv2si" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (neg:V2SI (eq:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpeq.l %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpeqv4hi" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (neg:V4HI (eq:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpeq.w %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpgtuv8qi" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (neg:V8QI (gtu:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpgt.ub %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpgtv2si" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (neg:V2SI (gt:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpgt.l %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "negcmpgtv4hi" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (neg:V4HI (gt:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "%rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcmpgt.w %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "mcmv" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (match_operand:DI 2 "arith_reg_operand" "r")) + (and:DI (match_operand:DI 3 "arith_reg_operand" "0") + (not:DI (match_dup 2)))))] + "TARGET_SHMEDIA" + "mcmv %N1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "mcnvs_lw" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_concat:V4HI + (ss_truncate:V2HI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU")) + (ss_truncate:V2HI (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcnvs.lw %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "mcnvs_wb" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (vec_concat:V8QI + (ss_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")) + (ss_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcnvs.wb %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "mcnvs_wub" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (vec_concat:V8QI + (us_truncate:V4QI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU")) + (us_truncate:V4QI (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mcnvs.wub %N1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "mextr_rl" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (match_operand:HI 3 "mextr_bit_offset" "i")) + (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (match_operand:HI 4 "mextr_bit_offset" "i"))))] + "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" + "* +{ + static char templ[16]; + + sprintf (templ, \"mextr%d\\t%%N1, %%N2, %%0\", + (int) INTVAL (operands[3]) >> 3); + return templ; +}" + [(set_attr "type" "arith_media")]) + +(define_insn "*mextr_lr" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (match_operand:HI 3 "mextr_bit_offset" "i")) + (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (match_operand:HI 4 "mextr_bit_offset" "i"))))] + "TARGET_SHMEDIA && INTVAL (operands[3]) + INTVAL (operands[4]) == 64" + "* +{ + static char templ[16]; + + sprintf (templ, \"mextr%d\\t%%N2, %%N1, %%0\", + (int) INTVAL (operands[4]) >> 3); + return templ; +}" + [(set_attr "type" "arith_media")]) + +; mextrN can be modelled with vec_select / vec_concat, but the selection +; vector then varies depending on endianness. +(define_expand "mextr1" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (1 * 8), GEN_INT (7 * 8))); + DONE; +}") + +(define_expand "mextr2" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (2 * 8), GEN_INT (6 * 8))); + DONE; +}") + +(define_expand "mextr3" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (3 * 8), GEN_INT (5 * 8))); + DONE; +}") + +(define_expand "mextr4" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (4 * 8), GEN_INT (4 * 8))); + DONE; +}") + +(define_expand "mextr5" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (5 * 8), GEN_INT (3 * 8))); + DONE; +}") + +(define_expand "mextr6" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (6 * 8), GEN_INT (2 * 8))); + DONE; +}") + +(define_expand "mextr7" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mextr_rl (operands[0], operands[1], operands[3], + GEN_INT (7 * 8), GEN_INT (1 * 8))); + DONE; +}") + +(define_expand "mmacfx_wl" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V2HI 1 "extend_reg_operand" "") + (match_operand:V2HI 2 "extend_reg_operand" "") + (match_operand:V2SI 3 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mmacfx_wl_i (operands[0], operands[3], + operands[1], operands[2])); + DONE; +}") + +(define_insn "mmacfx_wl_i" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_plus:V2SI + (match_operand:V2SI 1 "arith_reg_operand" "0") + (ss_truncate:V2SI + (ashift:V2DI + (sign_extend:V2DI + (mult:V2SI + (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) + (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) + (const_int 1)))))] + "TARGET_SHMEDIA" + "mmacfx.wl %2, %3, %0" + [(set_attr "type" "mac_media")]) + +(define_expand "mmacnfx_wl" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V2HI 1 "extend_reg_operand" "") + (match_operand:V2HI 2 "extend_reg_operand" "") + (match_operand:V2SI 3 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mmacnfx_wl_i (operands[0], operands[3], + operands[1], operands[2])); + DONE; +}") + +(define_insn "mmacnfx_wl_i" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_minus:V2SI + (match_operand:V2SI 1 "arith_reg_operand" "0") + (ss_truncate:V2SI + (ashift:V2DI + (sign_extend:V2DI + (mult:V2SI + (sign_extend:V2SI (match_operand:V2HI 2 "extend_reg_operand" "r")) + (sign_extend:V2SI (match_operand:V2HI 3 "extend_reg_operand" "r")))) + (const_int 1)))))] + "TARGET_SHMEDIA" + "mmacnfx.wl %2, %3, %0" + [(set_attr "type" "mac_media")]) + +(define_insn "mulv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (mult:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") + (match_operand:V2SI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mmul.l %1, %2, %0" + [(set_attr "type" "d2mpy_media")]) + +(define_insn "mulv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (mult:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") + (match_operand:V4HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mmul.w %1, %2, %0" + [(set_attr "type" "dmpy_media")]) + +(define_insn "mmulfx_l" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_truncate:V2SI + (ashiftrt:V2DI + (mult:V2DI + (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) + (sign_extend:V2DI (match_operand:V2SI 2 "arith_reg_operand" "r"))) + (const_int 31))))] + "TARGET_SHMEDIA" + "mmulfx.l %1, %2, %0" + [(set_attr "type" "d2mpy_media")]) + +(define_insn "mmulfx_w" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ss_truncate:V4HI + (ashiftrt:V4SI + (mult:V4SI + (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) + (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) + (const_int 15))))] + "TARGET_SHMEDIA" + "mmulfx.w %1, %2, %0" + [(set_attr "type" "dmpy_media")]) + +(define_insn "mmulfxrp_w" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ss_truncate:V4HI + (ashiftrt:V4SI + (plus:V4SI + (mult:V4SI + (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) + (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) + (const_int 16384)) + (const_int 15))))] + "TARGET_SHMEDIA" + "mmulfxrp.w %1, %2, %0" + [(set_attr "type" "dmpy_media")]) + +(define_expand "mmulhi_wl" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V4HI 1 "arith_reg_operand" "") + (match_operand:V4HI 2 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul23_wl : gen_mmul01_wl) + (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_expand "mmullo_wl" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V4HI 1 "arith_reg_operand" "") + (match_operand:V4HI 2 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mmul01_wl : gen_mmul23_wl) + (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_insn "mmul23_wl" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (vec_select:V2SI + (mult:V4SI + (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) + (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) + (const_vector [(const_int 2) (const_int 3)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mmulhi.wl %1, %2, %0\" + : \"mmullo.wl %1, %2, %0\");" + [(set_attr "type" "dmpy_media")]) + +(define_insn "mmul01_wl" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (vec_select:V2SI + (mult:V4SI + (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) + (sign_extend:V4SI (match_operand:V4HI 2 "arith_reg_operand" "r"))) + (const_vector [(const_int 0) (const_int 1)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mmullo.wl %1, %2, %0\" + : \"mmulhi.wl %1, %2, %0\");" + [(set_attr "type" "dmpy_media")]) + +(define_expand "mmulsum_wq" + [(match_operand:DI 0 "arith_reg_dest" "") + (match_operand:V4HI 1 "arith_reg_operand" "") + (match_operand:V4HI 2 "arith_reg_operand" "") + (match_operand:DI 3 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_mmulsum_wq_i (operands[0], operands[3], + operands[1], operands[2])); + DONE; +}") + +(define_insn "mmulsum_wq_i" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (plus:DI (match_operand:DI 1 "arith_reg_operand" "0") + (plus:DI + (plus:DI + (vec_select:DI + (mult:V4DI + (sign_extend:V4DI (match_operand:V4HI 2 "arith_reg_operand" "r")) + (sign_extend:V4DI (match_operand:V4HI 3 "arith_reg_operand" "r"))) + (const_vector [(const_int 0)])) + (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) + (sign_extend:V4DI (match_dup 3))) + (const_vector [(const_int 1)]))) + (plus:DI + (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) + (sign_extend:V4DI (match_dup 3))) + (const_vector [(const_int 2)])) + (vec_select:DI (mult:V4DI (sign_extend:V4DI (match_dup 2)) + (sign_extend:V4DI (match_dup 3))) + (const_vector [(const_int 3)]))))))] + "TARGET_SHMEDIA" + "mmulsum.wq %2, %3, %0" + [(set_attr "type" "mac_media")]) + +(define_expand "mperm_w" + [(match_operand:V4HI 0 "arith_reg_dest" "=r") + (match_operand:V4HI 1 "arith_reg_operand" "r") + (match_operand:QI 2 "extend_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mperm_w_little : gen_mperm_w_big) + (operands[0], operands[1], operands[2])); +}") + +; This use of vec_select isn't exactly correct according to rtl.texi +; (because not constant), but it seems a straightforward extension. +(define_insn "mperm_w_little" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_select:V4HI + (match_operand:V4HI 1 "arith_reg_operand" "r") + (parallel + [(zero_extract (match_operand:QI 2 "extend_reg_or_0_operand" "rU") + (const_int 2) (const_int 0)) + (zero_extract (match_dup 2) (const_int 2) (const_int 2)) + (zero_extract (match_dup 2) (const_int 2) (const_int 4)) + (zero_extract (match_dup 2) (const_int 2) (const_int 6))])))] + "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" + "mperm.w %1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "mperm_w_big" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_select:V4HI + (match_operand:V4HI 1 "arith_reg_operand" "r") + (parallel + [(zero_extract (not:QI (match_operand:QI 2 + "extend_reg_or_0_operand" "rU")) + (const_int 2) (const_int 0)) + (zero_extract (not:QI (match_dup 2)) (const_int 2) (const_int 2)) + (zero_extract (not:QI (match_dup 2)) (const_int 2) (const_int 4)) + (zero_extract (not:QI (match_dup 2)) (const_int 2) (const_int 6))])))] + "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" + "mperm.w %1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "mperm_w0" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_duplicate:V4HI (truncate:HI (match_operand 1 + "extend_reg_operand" "r"))))] + "TARGET_SHMEDIA" + "mperm.w %1, r63, %0" + [(set_attr "type" "arith_media")]) + +(define_expand "msad_ubq" + [(match_operand:DI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "") + (match_operand:DI 3 "arith_reg_operand" "")] + "TARGET_SHMEDIA" + " +{ + emit_insn (gen_msad_ubq_i (operands[0], operands[3], + operands[1], operands[2])); + DONE; +}") + +(define_insn "msad_ubq_i" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (plus:DI + (plus:DI + (plus:DI + (plus:DI + (match_operand:DI 1 "arith_reg_operand" "0") + (abs:DI (vec_select:DI + (minus:V8DI + (zero_extend:V8DI + (match_operand:V8QI 2 "arith_reg_or_0_operand" "r")) + (zero_extend:V8DI + (match_operand:V8QI 3 "arith_reg_or_0_operand" "r"))) + (const_vector [(const_int 0)])))) + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 1)])))) + (plus:DI + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 2)]))) + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 3)]))))) + (plus:DI + (plus:DI + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 4)]))) + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 5)])))) + (plus:DI + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 6)]))) + (abs:DI (vec_select:DI (minus:V8DI (zero_extend:V8DI (match_dup 2)) + (zero_extend:V8DI (match_dup 3))) + (const_vector [(const_int 7)])))))))] + "TARGET_SHMEDIA" + "msad.ubq %N2, %N3, %0" + [(set_attr "type" "mac_media")]) + +(define_insn "mshalds_l" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_truncate:V2SI + (ashift:V2DI + (sign_extend:V2DI (match_operand:V2SI 1 "arith_reg_operand" "r")) + (and:DI (match_operand:DI 2 "arith_reg_operand" "r") + (const_int 31)))))] + "TARGET_SHMEDIA" + "mshalds.l %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "mshalds_w" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ss_truncate:V4HI + (ashift:V4SI + (sign_extend:V4SI (match_operand:V4HI 1 "arith_reg_operand" "r")) + (and:DI (match_operand:DI 2 "arith_reg_operand" "r") + (const_int 15)))))] + "TARGET_SHMEDIA" + "mshalds.w %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "ashrv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ashiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshard.l %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "ashrv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ashiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshard.w %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "mshards_q" + [(set (match_operand:HI 0 "arith_reg_dest" "=r") + (ss_truncate:HI + (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_or_0_operand" "rU"))))] + "TARGET_SHMEDIA" + "mshards.q %1, %N2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_expand "mshfhi_b" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_b : gen_mshf0_b) + (operands[0], operands[1], operands[2])); +}") + +(define_expand "mshflo_b" + [(match_operand:V8QI 0 "arith_reg_dest" "") + (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_b : gen_mshf4_b) + (operands[0], operands[1], operands[2])); +}") + +(define_insn "mshf4_b" + [(set + (match_operand:V8QI 0 "arith_reg_dest" "=r") + (vec_select:V8QI + (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 4) (const_int 12) (const_int 5) (const_int 13) + (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshfhi.b %N1, %N2, %0\" + : \"mshflo.b %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +(define_insn "mshf0_b" + [(set + (match_operand:V8QI 0 "arith_reg_dest" "=r") + (vec_select:V8QI + (vec_concat:V16QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V8QI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 0) (const_int 8) (const_int 1) (const_int 9) + (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshflo.b %N1, %N2, %0\" + : \"mshfhi.b %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +(define_expand "mshfhi_l" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_l : gen_mshf0_l) + (operands[0], operands[1], operands[2])); +}") + +(define_expand "mshflo_l" + [(match_operand:V2SI 0 "arith_reg_dest" "") + (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_l : gen_mshf4_l) + (operands[0], operands[1], operands[2])); +}") + +(define_insn "mshf4_l" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (vec_select:V2SI + (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 1) (const_int 3)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshfhi.l %N1, %N2, %0\" + : \"mshflo.l %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +(define_insn "mshf0_l" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (vec_select:V2SI + (vec_concat:V4SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 0) (const_int 2)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshflo.l %N1, %N2, %0\" + : \"mshfhi.l %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +(define_expand "mshfhi_w" + [(match_operand:V4HI 0 "arith_reg_dest" "") + (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf4_w : gen_mshf0_w) + (operands[0], operands[1], operands[2])); +}") + +(define_expand "mshflo_w" + [(match_operand:V4HI 0 "arith_reg_dest" "") + (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")] + "TARGET_SHMEDIA" + " +{ + emit_insn ((TARGET_LITTLE_ENDIAN ? gen_mshf0_w : gen_mshf4_w) + (operands[0], operands[1], operands[2])); +}") + +(define_insn "mshf4_w" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_select:V4HI + (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshfhi.w %N1, %N2, %0\" + : \"mshflo.w %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +(define_insn "mshf0_w" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (vec_select:V4HI + (vec_concat:V8HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_or_0_operand" "rU")) + (const_vector [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] + "TARGET_SHMEDIA" + "* return (TARGET_LITTLE_ENDIAN + ? \"mshflo.w %N1, %N2, %0\" + : \"mshfhi.w %N1, %N2, %0\");" + [(set_attr "type" "arith_media")]) + +/* These are useful to expand ANDs and as combiner patterns. */ +(define_insn "mshfhi_l_di" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (const_int 32)) + (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (const_int -4294967296))))] + "TARGET_SHMEDIA" + "mshfhi.l %N1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "*mshfhi_l_di_rev" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (const_int -4294967296)) + (lshiftrt:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (const_int 32))))] + "TARGET_SHMEDIA" + "mshfhi.l %N2, %N1, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "mshflo_l_di" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (and:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (const_int 4294967295)) + (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (const_int 32))))] + + "TARGET_SHMEDIA" + "mshflo.l %N1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "*mshflo_l_di_rev" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (const_int 32)) + (and:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (const_int 4294967295))))] + + "TARGET_SHMEDIA" + "mshflo.l %N2, %N1, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "*mshflo_l_di_x" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_or_0_operand" "rU")) + (ashift:DI (match_operand:DI 2 "arith_reg_or_0_operand" "rU") + (const_int 32))))] + + "TARGET_SHMEDIA" + "mshflo.l %N1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "*mshflo_l_di_x_rev" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rU") + (const_int 32)) + (zero_extend:DI (match_operand:SI 2 "extend_reg_or_0_operand" "rU"))))] + + "TARGET_SHMEDIA" + "mshflo.l %N2, %N1, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "ashlv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshlld.l %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "ashlv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshlld.w %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "lshrv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshlrd.l %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "lshrv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "mshlrd.w %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "subv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "msub.l %N1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "subv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "msub.w %N1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "sssubv2si3" + [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") + (ss_minus:V2SI (match_operand:V2SI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V2SI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "msubs.l %N1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "ussubv8qi3" + [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") + (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r") + (match_operand:V8QI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "msubs.ub %1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +(define_insn "sssubv4hi3" + [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") + (ss_minus:V4HI (match_operand:V4HI 1 "arith_reg_or_0_operand" "rU") + (match_operand:V4HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "msubs.w %N1, %2, %0" + [(set_attr "type" "mcmp_media")]) + +;; Floating Point Intrinsics + +(define_insn "fcosa_s" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] + UNSPEC_FCOSA))] + "TARGET_SHMEDIA" + "fcosa.s %1, %0" + [(set_attr "type" "atrans_media")]) + +(define_insn "fsina_s" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (unspec:SF [(match_operand:SI 1 "fp_arith_reg_operand" "f")] + UNSPEC_FSINA))] + "TARGET_SHMEDIA" + "fsina.s %1, %0" + [(set_attr "type" "atrans_media")]) + +(define_insn "fipr" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (plus:SF (plus:SF (vec_select:SF (mult:V4SF (match_operand:V4SF 1 + "fp_arith_reg_operand" "f") + (match_operand:V4SF 2 + "fp_arith_reg_operand" "f")) + (const_vector [(const_int 0)])) + (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) + (const_vector [(const_int 1)]))) + (plus:SF (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) + (const_vector [(const_int 2)])) + (vec_select:SF (mult:V4SF (match_dup 1) (match_dup 2)) + (const_vector [(const_int 3)])))))] + "TARGET_SHMEDIA" + "fipr %1, %2, %0" + [(set_attr "type" "fparith_media")]) + +(define_insn "fsrra_s" + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (unspec:SF [(match_operand:SF 1 "fp_arith_reg_operand" "f")] + UNSPEC_FSRRA))] + "TARGET_SHMEDIA" + "fsrra.s %1, %0" + [(set_attr "type" "atrans_media")]) + +(define_insn "ftrv" + [(set (match_operand:V4SF 0 "fp_arith_reg_operand" "=f") + (plus:V4SF + (plus:V4SF + (mult:V4SF + (vec_select:V4SF (match_operand:V16SF 1 "fp_arith_reg_operand" "f") + (const_vector [(const_int 0) (const_int 5) + (const_int 10) (const_int 15)])) + (match_operand:V4SF 2 "fp_arith_reg_operand" "f")) + (mult:V4SF + (vec_select:V4SF (match_dup 1) + (const_vector [(const_int 4) (const_int 9) + (const_int 14) (const_int 3)])) + (vec_select:V4SF (match_dup 2) + (const_vector [(const_int 1) (const_int 2) + (const_int 3) (const_int 0)])))) + (plus:V4SF + (mult:V4SF + (vec_select:V4SF (match_dup 1) + (const_vector [(const_int 8) (const_int 13) + (const_int 2) (const_int 7)])) + (vec_select:V4SF (match_dup 2) + (const_vector [(const_int 2) (const_int 3) + (const_int 0) (const_int 1)]))) + (mult:V4SF + (vec_select:V4SF (match_dup 1) + (const_vector [(const_int 12) (const_int 1) + (const_int 6) (const_int 11)])) + (vec_select:V4SF (match_dup 2) + (const_vector [(const_int 3) (const_int 0) + (const_int 1) (const_int 2)]))))))] + "TARGET_SHMEDIA" + "ftrv %1, %2, %0" + [(set_attr "type" "fparith_media")]) + ;; The following description models the ;; SH4 pipeline using the DFA based scheduler. ;; The DFA based description is better way to model