diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2006-05-04 11:10:03 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2006-05-04 11:10:03 +0000 |
commit | 42da70b76e5d7818e9c44c171b354b0ce3226dd0 (patch) | |
tree | cd49c6be4cebd67fb8344a92e4327ac7c26fb89c /gcc | |
parent | 554006bd1a4ac1a43bb386198b69682691c7496f (diff) | |
download | gcc-42da70b76e5d7818e9c44c171b354b0ce3226dd0.zip gcc-42da70b76e5d7818e9c44c171b354b0ce3226dd0.tar.gz gcc-42da70b76e5d7818e9c44c171b354b0ce3226dd0.tar.bz2 |
bfin.c: Include "optabs.h".
* config/bfin/bfin.c: Include "optabs.h".
(bfin_rtx_costs): Some costs for vector operations, to allow combine
to do more work.
(enum bfin_builtins): Add a number of fractional and vector builtins.
(bfin_init_builtins): Likewise.
(struct builtin_description, bdesc_2arg, bdesc_1arg): New.
(safe_vector_operand, bfin_expand_binop_builtin,
bfin_expand_unop_builtin): New functions.
(bfin_expand_builtin): Handle the new builtins.
* config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS): Define
__ADSPBLACKFIN__.
From-SVN: r113521
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.c | 462 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.h | 1 |
3 files changed, 474 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 14eb262..b74f0cb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -4,6 +4,18 @@ that this only matches CONST_INTs. All users changed to VOIDmode operands. + * config/bfin/bfin.c: Include "optabs.h". + (bfin_rtx_costs): Some costs for vector operations, to allow combine + to do more work. + (enum bfin_builtins): Add a number of fractional and vector builtins. + (bfin_init_builtins): Likewise. + (struct builtin_description, bdesc_2arg, bdesc_1arg): New. + (safe_vector_operand, bfin_expand_binop_builtin, + bfin_expand_unop_builtin): New functions. + (bfin_expand_builtin): Handle the new builtins. + * config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS): Define + __ADSPBLACKFIN__. + 2006-05-04 Leehod Baruch <leehod@il.ibm.com> * see.c: New file. diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index f451e91..c747711 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -43,6 +43,7 @@ #include "expr.h" #include "toplev.h" #include "recog.h" +#include "optabs.h" #include "ggc.h" #include "integrate.h" #include "cgraph.h" @@ -2283,6 +2284,12 @@ bfin_rtx_costs (rtx x, int code, int outer_code, int *total) *total = COSTS_N_INSNS (3); return false; + case VEC_CONCAT: + case VEC_SELECT: + if (outer_code == SET) + *total = cost2; + return true; + default: return false; } @@ -2963,6 +2970,56 @@ enum bfin_builtins { BFIN_BUILTIN_CSYNC, BFIN_BUILTIN_SSYNC, + BFIN_BUILTIN_COMPOSE_2X16, + BFIN_BUILTIN_EXTRACTLO, + BFIN_BUILTIN_EXTRACTHI, + + BFIN_BUILTIN_SSADD_2X16, + BFIN_BUILTIN_SSSUB_2X16, + BFIN_BUILTIN_SSADDSUB_2X16, + BFIN_BUILTIN_SSSUBADD_2X16, + BFIN_BUILTIN_MULT_2X16, + BFIN_BUILTIN_MULTR_2X16, + BFIN_BUILTIN_NEG_2X16, + BFIN_BUILTIN_ABS_2X16, + BFIN_BUILTIN_MIN_2X16, + BFIN_BUILTIN_MAX_2X16, + + BFIN_BUILTIN_SSADD_1X16, + BFIN_BUILTIN_SSSUB_1X16, + BFIN_BUILTIN_MULT_1X16, + BFIN_BUILTIN_MULTR_1X16, + BFIN_BUILTIN_NORM_1X16, + BFIN_BUILTIN_NEG_1X16, + BFIN_BUILTIN_ABS_1X16, + BFIN_BUILTIN_MIN_1X16, + BFIN_BUILTIN_MAX_1X16, + + BFIN_BUILTIN_DIFFHL_2X16, + BFIN_BUILTIN_DIFFLH_2X16, + + BFIN_BUILTIN_SSADD_1X32, + BFIN_BUILTIN_SSSUB_1X32, + BFIN_BUILTIN_NORM_1X32, + BFIN_BUILTIN_NEG_1X32, + BFIN_BUILTIN_MIN_1X32, + BFIN_BUILTIN_MAX_1X32, + BFIN_BUILTIN_MULT_1X32, + + BFIN_BUILTIN_MULHISILL, + BFIN_BUILTIN_MULHISILH, + BFIN_BUILTIN_MULHISIHL, + BFIN_BUILTIN_MULHISIHH, + + BFIN_BUILTIN_LSHIFT_1X16, + BFIN_BUILTIN_LSHIFT_2X16, + BFIN_BUILTIN_SSASHIFT_1X16, + BFIN_BUILTIN_SSASHIFT_2X16, + + BFIN_BUILTIN_CPLX_MUL_16, + BFIN_BUILTIN_CPLX_MAC_16, + BFIN_BUILTIN_CPLX_MSU_16, + BFIN_BUILTIN_MAX }; @@ -2976,12 +3033,306 @@ do { \ static void bfin_init_builtins (void) { + tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode); tree void_ftype_void = build_function_type (void_type_node, void_list_node); + tree short_ftype_short + = build_function_type_list (short_integer_type_node, short_integer_type_node, + NULL_TREE); + tree short_ftype_int_int + = build_function_type_list (short_integer_type_node, integer_type_node, + integer_type_node, NULL_TREE); + tree int_ftype_int_int + = build_function_type_list (integer_type_node, integer_type_node, + integer_type_node, NULL_TREE); + tree int_ftype_int + = build_function_type_list (integer_type_node, integer_type_node, + NULL_TREE); + tree short_ftype_int + = build_function_type_list (short_integer_type_node, integer_type_node, + NULL_TREE); + tree int_ftype_v2hi_v2hi + = build_function_type_list (integer_type_node, V2HI_type_node, + V2HI_type_node, NULL_TREE); + tree v2hi_ftype_v2hi_v2hi + = build_function_type_list (V2HI_type_node, V2HI_type_node, + V2HI_type_node, NULL_TREE); + tree v2hi_ftype_v2hi_v2hi_v2hi + = build_function_type_list (V2HI_type_node, V2HI_type_node, + V2HI_type_node, V2HI_type_node, NULL_TREE); + tree v2hi_ftype_int_int + = build_function_type_list (V2HI_type_node, integer_type_node, + integer_type_node, NULL_TREE); + tree v2hi_ftype_v2hi_int + = build_function_type_list (V2HI_type_node, V2HI_type_node, + integer_type_node, NULL_TREE); + tree int_ftype_short_short + = build_function_type_list (integer_type_node, short_integer_type_node, + short_integer_type_node, NULL_TREE); + tree v2hi_ftype_v2hi + = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE); + tree short_ftype_v2hi + = build_function_type_list (short_integer_type_node, V2HI_type_node, + NULL_TREE); /* Add the remaining MMX insns with somewhat more complicated types. */ def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC); def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC); + + def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int, + BFIN_BUILTIN_COMPOSE_2X16); + def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi, + BFIN_BUILTIN_EXTRACTHI); + def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi, + BFIN_BUILTIN_EXTRACTLO); + + def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_MIN_2X16); + def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_MAX_2X16); + + def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_SSADD_2X16); + def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_SSSUB_2X16); + def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_SSADDSUB_2X16); + def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_SSSUBADD_2X16); + def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULT_2X16); + def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULTR_2X16); + def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi, + BFIN_BUILTIN_NEG_2X16); + def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi, + BFIN_BUILTIN_ABS_2X16); + + def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_SSADD_1X16); + def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_SSSUB_1X16); + def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_MULT_1X16); + def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_MULTR_1X16); + def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short, + BFIN_BUILTIN_NEG_1X16); + def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short, + BFIN_BUILTIN_ABS_1X16); + def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int, + BFIN_BUILTIN_NORM_1X16); + + def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi, + BFIN_BUILTIN_DIFFHL_2X16); + def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi, + BFIN_BUILTIN_DIFFLH_2X16); + + def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULHISILL); + def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULHISIHL); + def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULHISILH); + def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi, + BFIN_BUILTIN_MULHISIHH); + + def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int, + BFIN_BUILTIN_SSADD_1X32); + def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int, + BFIN_BUILTIN_SSSUB_1X32); + def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int, + BFIN_BUILTIN_NEG_1X32); + def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int, + BFIN_BUILTIN_NORM_1X32); + def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short, + BFIN_BUILTIN_MULT_1X32); + + /* Shifts. */ + def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_SSASHIFT_1X16); + def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int, + BFIN_BUILTIN_SSASHIFT_2X16); + def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int, + BFIN_BUILTIN_LSHIFT_1X16); + def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int, + BFIN_BUILTIN_LSHIFT_2X16); + + /* Complex numbers. */ + def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi, + BFIN_BUILTIN_CPLX_MUL_16); + def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi, + BFIN_BUILTIN_CPLX_MAC_16); + def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi, + BFIN_BUILTIN_CPLX_MSU_16); +} + + +struct builtin_description +{ + const enum insn_code icode; + const char *const name; + const enum bfin_builtins code; + int macflag; +}; + +static const struct builtin_description bdesc_2arg[] = +{ + { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 }, + + { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 }, + { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 }, + { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 }, + { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 }, + + { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 }, + { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 }, + { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 }, + { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 }, + + { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 }, + { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 }, + { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 }, + { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 }, + + { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 }, + { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 }, + { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 }, + { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 }, + { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 }, + { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 }, + + { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE }, + { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T }, + { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE }, + { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T }, + { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE } +}; + +static const struct builtin_description bdesc_1arg[] = +{ + { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 }, + { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 }, + { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 }, + + { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 }, + { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 }, + + { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 }, + { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 }, + { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 }, + { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 } +}; + +/* Errors in the source file can cause expand_expr to return const0_rtx + where we expect a vector. To avoid crashing, use one of the vector + clear instructions. */ +static rtx +safe_vector_operand (rtx x, enum machine_mode mode) +{ + if (x != const0_rtx) + return x; + x = gen_reg_rtx (SImode); + + emit_insn (gen_movsi (x, CONST0_RTX (SImode))); + return gen_lowpart (mode, x); +} + +/* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1 + if this is a normal binary op, or one of the MACFLAG_xxx constants. */ + +static rtx +bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target, + int macflag) +{ + rtx pat; + tree arg0 = TREE_VALUE (arglist); + tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); + rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); + enum machine_mode op0mode = GET_MODE (op0); + enum machine_mode op1mode = GET_MODE (op1); + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode0 = insn_data[icode].operand[1].mode; + enum machine_mode mode1 = insn_data[icode].operand[2].mode; + + if (VECTOR_MODE_P (mode0)) + op0 = safe_vector_operand (op0, mode0); + if (VECTOR_MODE_P (mode1)) + op1 = safe_vector_operand (op1, mode1); + + if (! target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode) + { + op0mode = HImode; + op0 = gen_lowpart (HImode, op0); + } + if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode) + { + op1mode = HImode; + op1 = gen_lowpart (HImode, op1); + } + /* In case the insn wants input operands in modes different from + the result, abort. */ + gcc_assert ((op0mode == mode0 || op0mode == VOIDmode) + && (op1mode == mode1 || op1mode == VOIDmode)); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + if (macflag == -1) + pat = GEN_FCN (icode) (target, op0, op1); + else + pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag)); + if (! pat) + return 0; + + emit_insn (pat); + return target; +} + +/* Subroutine of bfin_expand_builtin to take care of unop insns. */ + +static rtx +bfin_expand_unop_builtin (enum insn_code icode, tree arglist, + rtx target) +{ + rtx pat; + tree arg0 = TREE_VALUE (arglist); + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); + enum machine_mode op0mode = GET_MODE (op0); + enum machine_mode tmode = insn_data[icode].operand[0].mode; + enum machine_mode mode0 = insn_data[icode].operand[1].mode; + + if (! target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (VECTOR_MODE_P (mode0)) + op0 = safe_vector_operand (op0, mode0); + + if (op0mode == SImode && mode0 == HImode) + { + op0mode = HImode; + op0 = gen_lowpart (HImode, op0); + } + gcc_assert (op0mode == mode0 || op0mode == VOIDmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (target, op0); + if (! pat) + return 0; + emit_insn (pat); + return target; } /* Expand an expression EXP that calls a built-in function, @@ -2996,8 +3347,15 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { + size_t i; + enum insn_code icode; + const struct builtin_description *d; tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree arglist = TREE_OPERAND (exp, 1); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + tree arg0, arg1, arg2; + rtx op0, op1, op2, accvec, pat, tmp1, tmp2; + enum machine_mode tmode, mode0; switch (fcode) { @@ -3008,9 +3366,111 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, emit_insn (gen_ssync ()); return 0; + case BFIN_BUILTIN_DIFFHL_2X16: + case BFIN_BUILTIN_DIFFLH_2X16: + arg0 = TREE_VALUE (arglist); + op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); + icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 + ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3); + tmode = insn_data[icode].operand[0].mode; + mode0 = insn_data[icode].operand[1].mode; + + if (! target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (VECTOR_MODE_P (mode0)) + op0 = safe_vector_operand (op0, mode0); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (target, op0, op0); + if (! pat) + return 0; + emit_insn (pat); + return target; + + case BFIN_BUILTIN_CPLX_MUL_16: + 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); + accvec = gen_reg_rtx (V2PDImode); + + if (! target + || GET_MODE (target) != V2HImode + || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) + target = gen_reg_rtx (tmode); + if (! register_operand (op0, GET_MODE (op0))) + op0 = copy_to_mode_reg (GET_MODE (op0), op0); + if (! register_operand (op1, GET_MODE (op1))) + op1 = copy_to_mode_reg (GET_MODE (op1), op1); + + emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx, + const0_rtx, const0_rtx, + const1_rtx, GEN_INT (MACFLAG_NONE))); + emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx, + const1_rtx, const1_rtx, + const0_rtx, accvec, const1_rtx, const0_rtx, + GEN_INT (MACFLAG_NONE), accvec)); + + return target; + + case BFIN_BUILTIN_CPLX_MAC_16: + case BFIN_BUILTIN_CPLX_MSU_16: + 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); + accvec = gen_reg_rtx (V2PDImode); + + if (! target + || GET_MODE (target) != V2HImode + || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) + target = gen_reg_rtx (tmode); + if (! register_operand (op0, GET_MODE (op0))) + op0 = copy_to_mode_reg (GET_MODE (op0), op0); + if (! register_operand (op1, GET_MODE (op1))) + op1 = copy_to_mode_reg (GET_MODE (op1), op1); + + tmp1 = gen_reg_rtx (SImode); + tmp2 = gen_reg_rtx (SImode); + emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16))); + emit_move_insn (tmp2, gen_lowpart (SImode, op2)); + emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx)); + emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2)); + emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx, + const0_rtx, const0_rtx, + const1_rtx, accvec, const0_rtx, + const0_rtx, + GEN_INT (MACFLAG_W32))); + tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx); + tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx); + emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx, + const1_rtx, const1_rtx, + const0_rtx, accvec, tmp1, tmp2, + GEN_INT (MACFLAG_NONE), accvec)); + + return target; + default: - gcc_unreachable (); + break; } + + for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) + if (d->code == fcode) + return bfin_expand_binop_builtin (d->icode, arglist, target, + d->macflag); + + for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) + if (d->code == fcode) + return bfin_expand_unop_builtin (d->icode, arglist, target); + + gcc_unreachable (); } #undef TARGET_INIT_BUILTINS diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 2d1cd39..21f1070 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -41,6 +41,7 @@ extern int target_flags; { \ builtin_define ("bfin"); \ builtin_define ("BFIN"); \ + builtin_define ("__ADSPBLACKFIN__"); \ if (TARGET_ID_SHARED_LIBRARY) \ builtin_define ("__ID_SHARED_LIB__"); \ } \ |