diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-06 11:31:56 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-06 11:31:56 +0000 |
commit | d0e8b42e19303eaa9b433a341ac6d42c9ac945ed (patch) | |
tree | 696751ad82b90968d6718287d90a84b3fe9b59ba /gcc/config/sparc | |
parent | 098f44bcc537e52bb5436cb6599346391f3d77b3 (diff) | |
download | gcc-d0e8b42e19303eaa9b433a341ac6d42c9ac945ed.tar.gz |
PR target/59316
* config/sparc/sparc.h (SPARC_LOW_FE_EXCEPT_VALUES): Define.
* config/sparc/sol2.h (SPARC_LOW_FE_EXCEPT_VALUES): Redefine.
* config/sparc/sparc.c (TARGET_INIT_BUILTINS): Move around.
(TARGET_BUILTIN_DECL): Define.
(TARGET_ATOMIC_ASSIGN_EXPAND_FENV): Likewise.
(sparc32_initialize_trampoline): Adjust call to gen_flush.
(enum sparc_builtins): New enumeral type.
(sparc_builtins): New static array.
(sparc_builtins_icode): Likewise.
(def_builtin): Accept a separate icode and save the result.
(def_builtin_const): Likewise.
(sparc_fpu_init_builtins): New function.
(sparc_vis_init_builtins): Pass the builtin code.
(sparc_init_builtins): Call it if TARGET_FPU.
(sparc_builtin_decl): New function.
(sparc_expand_builtin): Deal with SPARC_BUILTIN_{LD,ST}FSR.
(sparc_handle_vis_mul8x16): Use the builtin code.
(sparc_fold_builtin): Likewise. Deal with SPARC_BUILTIN_{LD,ST}FSR
and SPARC_BUILTIN_PDISTN.
(compound_expr): New helper function.
(sparc_atomic_assign_expand_fenv): New function.
* config/sparc/sparc.md (unspecv): Reorder values, add UNSPECV_LDFSR
and UNSPECV_STFSR.
(flush, flushdi): Merge into single pattern.
(ldfsr): New instruction.
(stfsr): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205735 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r-- | gcc/config/sparc/sol2.h | 3 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 701 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 3 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 42 |
4 files changed, 520 insertions, 229 deletions
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h index 4010939df6e..c9a3f43fd40 100644 --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -406,3 +406,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #undef SUN_INTEGER_MULTIPLY_64 #define SUN_INTEGER_MULTIPLY_64 1 + +#undef SPARC_LOW_FE_EXCEPT_VALUES +#define SPARC_LOW_FE_EXCEPT_VALUES 1 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 983f2fab726..d7456722568 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -570,11 +570,11 @@ static void emit_hard_tfmode_operation (enum rtx_code, rtx *); static bool sparc_function_ok_for_sibcall (tree, tree); static void sparc_init_libfuncs (void); static void sparc_init_builtins (void); +static void sparc_fpu_init_builtins (void); static void sparc_vis_init_builtins (void); +static tree sparc_builtin_decl (unsigned, bool); static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static tree sparc_fold_builtin (tree, int, tree *, bool); -static int sparc_vis_mul8x16 (int, int); -static void sparc_handle_vis_mul8x16 (tree *, int, tree, tree, tree); static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT, @@ -638,6 +638,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t, enum machine_mode, secondary_reload_info *); static enum machine_mode sparc_cstore_mode (enum insn_code icode); +static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *); #ifdef SUBTARGET_ATTRIBUTE_TABLE /* Table of valid machine attributes. */ @@ -693,8 +694,6 @@ char sparc_hard_reg_printed[8]; #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS sparc_init_libfuncs -#undef TARGET_INIT_BUILTINS -#define TARGET_INIT_BUILTINS sparc_init_builtins #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS sparc_legitimize_address @@ -703,6 +702,10 @@ char sparc_hard_reg_printed[8]; #undef TARGET_MODE_DEPENDENT_ADDRESS_P #define TARGET_MODE_DEPENDENT_ADDRESS_P sparc_mode_dependent_address_p +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS sparc_init_builtins +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL sparc_builtin_decl #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN sparc_expand_builtin #undef TARGET_FOLD_BUILTIN @@ -843,6 +846,9 @@ char sparc_hard_reg_printed[8]; #undef TARGET_CSTORE_MODE #define TARGET_CSTORE_MODE sparc_cstore_mode +#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV +#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV sparc_atomic_assign_expand_fenv + struct gcc_target targetm = TARGET_INITIALIZER; /* Return the memory reference contained in X if any, zero otherwise. */ @@ -9237,14 +9243,14 @@ sparc32_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt) /* On UltraSPARC a flush flushes an entire cache line. The trampoline is aligned on a 16 byte boundary so one flush clears it all. */ - emit_insn (gen_flush (validize_mem (adjust_address (m_tramp, SImode, 0)))); + emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 0)))); if (sparc_cpu != PROCESSOR_ULTRASPARC && sparc_cpu != PROCESSOR_ULTRASPARC3 && sparc_cpu != PROCESSOR_NIAGARA && sparc_cpu != PROCESSOR_NIAGARA2 && sparc_cpu != PROCESSOR_NIAGARA3 && sparc_cpu != PROCESSOR_NIAGARA4) - emit_insn (gen_flush (validize_mem (adjust_address (m_tramp, SImode, 8)))); + emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 8)))); /* Call __enable_execute_stack after writing onto the stack to make sure the stack address is accessible. */ @@ -9969,15 +9975,145 @@ sparc_init_libfuncs (void) } } -static tree def_builtin(const char *name, int code, tree type) +/* SPARC builtins. */ +enum sparc_builtins +{ + /* FPU builtins. */ + SPARC_BUILTIN_LDFSR, + SPARC_BUILTIN_STFSR, + + /* VIS 1.0 builtins. */ + SPARC_BUILTIN_FPACK16, + SPARC_BUILTIN_FPACK32, + SPARC_BUILTIN_FPACKFIX, + SPARC_BUILTIN_FEXPAND, + SPARC_BUILTIN_FPMERGE, + SPARC_BUILTIN_FMUL8X16, + SPARC_BUILTIN_FMUL8X16AU, + SPARC_BUILTIN_FMUL8X16AL, + SPARC_BUILTIN_FMUL8SUX16, + SPARC_BUILTIN_FMUL8ULX16, + SPARC_BUILTIN_FMULD8SUX16, + SPARC_BUILTIN_FMULD8ULX16, + SPARC_BUILTIN_FALIGNDATAV4HI, + SPARC_BUILTIN_FALIGNDATAV8QI, + SPARC_BUILTIN_FALIGNDATAV2SI, + SPARC_BUILTIN_FALIGNDATADI, + SPARC_BUILTIN_WRGSR, + SPARC_BUILTIN_RDGSR, + SPARC_BUILTIN_ALIGNADDR, + SPARC_BUILTIN_ALIGNADDRL, + SPARC_BUILTIN_PDIST, + SPARC_BUILTIN_EDGE8, + SPARC_BUILTIN_EDGE8L, + SPARC_BUILTIN_EDGE16, + SPARC_BUILTIN_EDGE16L, + SPARC_BUILTIN_EDGE32, + SPARC_BUILTIN_EDGE32L, + SPARC_BUILTIN_FCMPLE16, + SPARC_BUILTIN_FCMPLE32, + SPARC_BUILTIN_FCMPNE16, + SPARC_BUILTIN_FCMPNE32, + SPARC_BUILTIN_FCMPGT16, + SPARC_BUILTIN_FCMPGT32, + SPARC_BUILTIN_FCMPEQ16, + SPARC_BUILTIN_FCMPEQ32, + SPARC_BUILTIN_FPADD16, + SPARC_BUILTIN_FPADD16S, + SPARC_BUILTIN_FPADD32, + SPARC_BUILTIN_FPADD32S, + SPARC_BUILTIN_FPSUB16, + SPARC_BUILTIN_FPSUB16S, + SPARC_BUILTIN_FPSUB32, + SPARC_BUILTIN_FPSUB32S, + SPARC_BUILTIN_ARRAY8, + SPARC_BUILTIN_ARRAY16, + SPARC_BUILTIN_ARRAY32, + + /* VIS 2.0 builtins. */ + SPARC_BUILTIN_EDGE8N, + SPARC_BUILTIN_EDGE8LN, + SPARC_BUILTIN_EDGE16N, + SPARC_BUILTIN_EDGE16LN, + SPARC_BUILTIN_EDGE32N, + SPARC_BUILTIN_EDGE32LN, + SPARC_BUILTIN_BMASK, + SPARC_BUILTIN_BSHUFFLEV4HI, + SPARC_BUILTIN_BSHUFFLEV8QI, + SPARC_BUILTIN_BSHUFFLEV2SI, + SPARC_BUILTIN_BSHUFFLEDI, + + /* VIS 3.0 builtins. */ + SPARC_BUILTIN_CMASK8, + SPARC_BUILTIN_CMASK16, + SPARC_BUILTIN_CMASK32, + SPARC_BUILTIN_FCHKSM16, + SPARC_BUILTIN_FSLL16, + SPARC_BUILTIN_FSLAS16, + SPARC_BUILTIN_FSRL16, + SPARC_BUILTIN_FSRA16, + SPARC_BUILTIN_FSLL32, + SPARC_BUILTIN_FSLAS32, + SPARC_BUILTIN_FSRL32, + SPARC_BUILTIN_FSRA32, + SPARC_BUILTIN_PDISTN, + SPARC_BUILTIN_FMEAN16, + SPARC_BUILTIN_FPADD64, + SPARC_BUILTIN_FPSUB64, + SPARC_BUILTIN_FPADDS16, + SPARC_BUILTIN_FPADDS16S, + SPARC_BUILTIN_FPSUBS16, + SPARC_BUILTIN_FPSUBS16S, + SPARC_BUILTIN_FPADDS32, + SPARC_BUILTIN_FPADDS32S, + SPARC_BUILTIN_FPSUBS32, + SPARC_BUILTIN_FPSUBS32S, + SPARC_BUILTIN_FUCMPLE8, + SPARC_BUILTIN_FUCMPNE8, + SPARC_BUILTIN_FUCMPGT8, + SPARC_BUILTIN_FUCMPEQ8, + SPARC_BUILTIN_FHADDS, + SPARC_BUILTIN_FHADDD, + SPARC_BUILTIN_FHSUBS, + SPARC_BUILTIN_FHSUBD, + SPARC_BUILTIN_FNHADDS, + SPARC_BUILTIN_FNHADDD, + SPARC_BUILTIN_UMULXHI, + SPARC_BUILTIN_XMULX, + SPARC_BUILTIN_XMULXHI, + + SPARC_BUILTIN_MAX +}; + +static GTY (()) tree sparc_builtins[(int) SPARC_BUILTIN_MAX]; +static enum insn_code sparc_builtins_icode[(int) SPARC_BUILTIN_MAX]; + +/* Add a SPARC builtin function with NAME, ICODE, CODE and TYPE. Return the + function decl or NULL_TREE if the builtin was not added. */ + +static tree +def_builtin (const char *name, enum insn_code icode, enum sparc_builtins code, + tree type) { - return add_builtin_function(name, type, code, BUILT_IN_MD, NULL, - NULL_TREE); + tree t + = add_builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE); + + if (t) + { + sparc_builtins[code] = t; + sparc_builtins_icode[code] = icode; + } + + return t; } -static tree def_builtin_const(const char *name, int code, tree type) +/* Likewise, but also marks the function as "const". */ + +static tree +def_builtin_const (const char *name, enum insn_code icode, + enum sparc_builtins code, tree type) { - tree t = def_builtin(name, code, type); + tree t = def_builtin (name, icode, code, type); if (t) TREE_READONLY (t) = 1; @@ -9991,11 +10127,28 @@ static tree def_builtin_const(const char *name, int code, tree type) static void sparc_init_builtins (void) { + if (TARGET_FPU) + sparc_fpu_init_builtins (); + if (TARGET_VIS) sparc_vis_init_builtins (); } -/* Create builtin functions for VIS 1.0 instructions. */ +/* Create builtin functions for FPU instructions. */ + +static void +sparc_fpu_init_builtins (void) +{ + tree ftype + = build_function_type_list (void_type_node, + build_pointer_type (unsigned_type_node), 0); + def_builtin ("__builtin_load_fsr", CODE_FOR_ldfsr, + SPARC_BUILTIN_LDFSR, ftype); + def_builtin ("__builtin_store_fsr", CODE_FOR_stfsr, + SPARC_BUILTIN_STFSR, ftype); +} + +/* Create builtin functions for VIS instructions. */ static void sparc_vis_init_builtins (void) @@ -10069,223 +10222,225 @@ sparc_vis_init_builtins (void) /* Packing and expanding vectors. */ def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis, - v4qi_ftype_v4hi); + SPARC_BUILTIN_FPACK16, v4qi_ftype_v4hi); def_builtin ("__builtin_vis_fpack32", CODE_FOR_fpack32_vis, - v8qi_ftype_v2si_v8qi); + SPARC_BUILTIN_FPACK32, v8qi_ftype_v2si_v8qi); def_builtin ("__builtin_vis_fpackfix", CODE_FOR_fpackfix_vis, - v2hi_ftype_v2si); + SPARC_BUILTIN_FPACKFIX, v2hi_ftype_v2si); def_builtin_const ("__builtin_vis_fexpand", CODE_FOR_fexpand_vis, - v4hi_ftype_v4qi); + SPARC_BUILTIN_FEXPAND, v4hi_ftype_v4qi); def_builtin_const ("__builtin_vis_fpmerge", CODE_FOR_fpmerge_vis, - v8qi_ftype_v4qi_v4qi); + SPARC_BUILTIN_FPMERGE, v8qi_ftype_v4qi_v4qi); /* Multiplications. */ def_builtin_const ("__builtin_vis_fmul8x16", CODE_FOR_fmul8x16_vis, - v4hi_ftype_v4qi_v4hi); + SPARC_BUILTIN_FMUL8X16, v4hi_ftype_v4qi_v4hi); def_builtin_const ("__builtin_vis_fmul8x16au", CODE_FOR_fmul8x16au_vis, - v4hi_ftype_v4qi_v2hi); + SPARC_BUILTIN_FMUL8X16AU, v4hi_ftype_v4qi_v2hi); def_builtin_const ("__builtin_vis_fmul8x16al", CODE_FOR_fmul8x16al_vis, - v4hi_ftype_v4qi_v2hi); + SPARC_BUILTIN_FMUL8X16AL, v4hi_ftype_v4qi_v2hi); def_builtin_const ("__builtin_vis_fmul8sux16", CODE_FOR_fmul8sux16_vis, - v4hi_ftype_v8qi_v4hi); + SPARC_BUILTIN_FMUL8SUX16, v4hi_ftype_v8qi_v4hi); def_builtin_const ("__builtin_vis_fmul8ulx16", CODE_FOR_fmul8ulx16_vis, - v4hi_ftype_v8qi_v4hi); + SPARC_BUILTIN_FMUL8ULX16, v4hi_ftype_v8qi_v4hi); def_builtin_const ("__builtin_vis_fmuld8sux16", CODE_FOR_fmuld8sux16_vis, - v2si_ftype_v4qi_v2hi); + SPARC_BUILTIN_FMULD8SUX16, v2si_ftype_v4qi_v2hi); def_builtin_const ("__builtin_vis_fmuld8ulx16", CODE_FOR_fmuld8ulx16_vis, - v2si_ftype_v4qi_v2hi); + SPARC_BUILTIN_FMULD8ULX16, v2si_ftype_v4qi_v2hi); /* Data aligning. */ def_builtin ("__builtin_vis_faligndatav4hi", CODE_FOR_faligndatav4hi_vis, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FALIGNDATAV4HI, v4hi_ftype_v4hi_v4hi); def_builtin ("__builtin_vis_faligndatav8qi", CODE_FOR_faligndatav8qi_vis, - v8qi_ftype_v8qi_v8qi); + SPARC_BUILTIN_FALIGNDATAV8QI, v8qi_ftype_v8qi_v8qi); def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FALIGNDATAV2SI, v2si_ftype_v2si_v2si); def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatav1di_vis, - di_ftype_di_di); + SPARC_BUILTIN_FALIGNDATADI, di_ftype_di_di); def_builtin ("__builtin_vis_write_gsr", CODE_FOR_wrgsr_vis, - void_ftype_di); + SPARC_BUILTIN_WRGSR, void_ftype_di); def_builtin ("__builtin_vis_read_gsr", CODE_FOR_rdgsr_vis, - di_ftype_void); + SPARC_BUILTIN_RDGSR, di_ftype_void); if (TARGET_ARCH64) { def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrdi_vis, - ptr_ftype_ptr_di); + SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_di); def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrldi_vis, - ptr_ftype_ptr_di); + SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_di); } else { def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrsi_vis, - ptr_ftype_ptr_si); + SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_si); def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrlsi_vis, - ptr_ftype_ptr_si); + SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_si); } /* Pixel distance. */ def_builtin_const ("__builtin_vis_pdist", CODE_FOR_pdist_vis, - di_ftype_v8qi_v8qi_di); + SPARC_BUILTIN_PDIST, di_ftype_v8qi_v8qi_di); /* Edge handling. */ if (TARGET_ARCH64) { def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8di_vis, - di_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE8, di_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8ldi_vis, - di_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE8L, di_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16di_vis, - di_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE16, di_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16ldi_vis, - di_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE16L, di_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32di_vis, - di_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE32, di_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32ldi_vis, - di_ftype_ptr_ptr); - if (TARGET_VIS2) - { - def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis, - di_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis, - di_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis, - di_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis, - di_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis, - di_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis, - di_ftype_ptr_ptr); - } + SPARC_BUILTIN_EDGE32L, di_ftype_ptr_ptr); } else { def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8si_vis, - si_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE8, si_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8lsi_vis, - si_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE8L, si_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16si_vis, - si_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE16, si_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16lsi_vis, - si_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE16L, si_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32si_vis, - si_ftype_ptr_ptr); + SPARC_BUILTIN_EDGE32, si_ftype_ptr_ptr); def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32lsi_vis, - si_ftype_ptr_ptr); - if (TARGET_VIS2) - { - def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis, - si_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis, - si_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis, - si_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis, - si_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis, - si_ftype_ptr_ptr); - def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis, - si_ftype_ptr_ptr); - } + SPARC_BUILTIN_EDGE32L, si_ftype_ptr_ptr); } /* Pixel compare. */ if (TARGET_ARCH64) { def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16di_vis, - di_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPLE16, di_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32di_vis, - di_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPLE32, di_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16di_vis, - di_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPNE16, di_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32di_vis, - di_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPNE32, di_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16di_vis, - di_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPGT16, di_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32di_vis, - di_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPGT32, di_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16di_vis, - di_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPEQ16, di_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32di_vis, - di_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPEQ32, di_ftype_v2si_v2si); } else { def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16si_vis, - si_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPLE16, si_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32si_vis, - si_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPLE32, si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16si_vis, - si_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPNE16, si_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32si_vis, - si_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPNE32, si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16si_vis, - si_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPGT16, si_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32si_vis, - si_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPGT32, si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16si_vis, - si_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCMPEQ16, si_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32si_vis, - si_ftype_v2si_v2si); + SPARC_BUILTIN_FCMPEQ32, si_ftype_v2si_v2si); } /* Addition and subtraction. */ def_builtin_const ("__builtin_vis_fpadd16", CODE_FOR_addv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FPADD16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fpadd16s", CODE_FOR_addv2hi3, - v2hi_ftype_v2hi_v2hi); + SPARC_BUILTIN_FPADD16S, v2hi_ftype_v2hi_v2hi); def_builtin_const ("__builtin_vis_fpadd32", CODE_FOR_addv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FPADD32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addv1si3, - v1si_ftype_v1si_v1si); + SPARC_BUILTIN_FPADD32S, v1si_ftype_v1si_v1si); def_builtin_const ("__builtin_vis_fpsub16", CODE_FOR_subv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FPSUB16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fpsub16s", CODE_FOR_subv2hi3, - v2hi_ftype_v2hi_v2hi); + SPARC_BUILTIN_FPSUB16S, v2hi_ftype_v2hi_v2hi); def_builtin_const ("__builtin_vis_fpsub32", CODE_FOR_subv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FPSUB32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subv1si3, - v1si_ftype_v1si_v1si); + SPARC_BUILTIN_FPSUB32S, v1si_ftype_v1si_v1si); /* Three-dimensional array addressing. */ if (TARGET_ARCH64) { def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8di_vis, - di_ftype_di_di); + SPARC_BUILTIN_ARRAY8, di_ftype_di_di); def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16di_vis, - di_ftype_di_di); + SPARC_BUILTIN_ARRAY16, di_ftype_di_di); def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32di_vis, - di_ftype_di_di); + SPARC_BUILTIN_ARRAY32, di_ftype_di_di); } else { def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8si_vis, - si_ftype_si_si); + SPARC_BUILTIN_ARRAY8, si_ftype_si_si); def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16si_vis, - si_ftype_si_si); + SPARC_BUILTIN_ARRAY16, si_ftype_si_si); def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32si_vis, - si_ftype_si_si); - } + SPARC_BUILTIN_ARRAY32, si_ftype_si_si); + } if (TARGET_VIS2) { - /* Byte mask and shuffle */ + /* Edge handling. */ + if (TARGET_ARCH64) + { + def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis, + SPARC_BUILTIN_EDGE8N, di_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis, + SPARC_BUILTIN_EDGE8LN, di_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis, + SPARC_BUILTIN_EDGE16N, di_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis, + SPARC_BUILTIN_EDGE16LN, di_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis, + SPARC_BUILTIN_EDGE32N, di_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis, + SPARC_BUILTIN_EDGE32LN, di_ftype_ptr_ptr); + } + else + { + def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis, + SPARC_BUILTIN_EDGE8N, si_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis, + SPARC_BUILTIN_EDGE8LN, si_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis, + SPARC_BUILTIN_EDGE16N, si_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis, + SPARC_BUILTIN_EDGE16LN, si_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis, + SPARC_BUILTIN_EDGE32N, si_ftype_ptr_ptr); + def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis, + SPARC_BUILTIN_EDGE32LN, si_ftype_ptr_ptr); + } + + /* Byte mask and shuffle. */ if (TARGET_ARCH64) def_builtin ("__builtin_vis_bmask", CODE_FOR_bmaskdi_vis, - di_ftype_di_di); + SPARC_BUILTIN_BMASK, di_ftype_di_di); else def_builtin ("__builtin_vis_bmask", CODE_FOR_bmasksi_vis, - si_ftype_si_si); + SPARC_BUILTIN_BMASK, si_ftype_si_si); def_builtin ("__builtin_vis_bshufflev4hi", CODE_FOR_bshufflev4hi_vis, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_BSHUFFLEV4HI, v4hi_ftype_v4hi_v4hi); def_builtin ("__builtin_vis_bshufflev8qi", CODE_FOR_bshufflev8qi_vis, - v8qi_ftype_v8qi_v8qi); + SPARC_BUILTIN_BSHUFFLEV8QI, v8qi_ftype_v8qi_v8qi); def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_BSHUFFLEV2SI, v2si_ftype_v2si_v2si); def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshufflev1di_vis, - di_ftype_di_di); + SPARC_BUILTIN_BSHUFFLEDI, di_ftype_di_di); } if (TARGET_VIS3) @@ -10293,120 +10448,130 @@ sparc_vis_init_builtins (void) if (TARGET_ARCH64) { def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8di_vis, - void_ftype_di); + SPARC_BUILTIN_CMASK8, void_ftype_di); def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16di_vis, - void_ftype_di); + SPARC_BUILTIN_CMASK16, void_ftype_di); def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32di_vis, - void_ftype_di); + SPARC_BUILTIN_CMASK32, void_ftype_di); } else { def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8si_vis, - void_ftype_si); + SPARC_BUILTIN_CMASK8, void_ftype_si); def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16si_vis, - void_ftype_si); + SPARC_BUILTIN_CMASK16, void_ftype_si); def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32si_vis, - void_ftype_si); + SPARC_BUILTIN_CMASK32, void_ftype_si); } def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FCHKSM16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_vashlv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FSLL16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_vssashlv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FSLAS16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_vlshrv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FSRL16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_vashrv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FSRA16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_vashlv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FSLL32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_vssashlv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FSLAS32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_vlshrv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FSRL32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_vashrv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FSRA32, v2si_ftype_v2si_v2si); if (TARGET_ARCH64) def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistndi_vis, - di_ftype_v8qi_v8qi); + SPARC_BUILTIN_PDISTN, di_ftype_v8qi_v8qi); else def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistnsi_vis, - si_ftype_v8qi_v8qi); + SPARC_BUILTIN_PDISTN, si_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fmean16", CODE_FOR_fmean16_vis, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FMEAN16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fpadd64", CODE_FOR_fpadd64_vis, - di_ftype_di_di); + SPARC_BUILTIN_FPADD64, di_ftype_di_di); def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis, - di_ftype_di_di); + SPARC_BUILTIN_FPSUB64, di_ftype_di_di); def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_ssaddv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FPADDS16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_ssaddv2hi3, - v2hi_ftype_v2hi_v2hi); + SPARC_BUILTIN_FPADDS16S, v2hi_ftype_v2hi_v2hi); def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_sssubv4hi3, - v4hi_ftype_v4hi_v4hi); + SPARC_BUILTIN_FPSUBS16, v4hi_ftype_v4hi_v4hi); def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_sssubv2hi3, - v2hi_ftype_v2hi_v2hi); + SPARC_BUILTIN_FPSUBS16S, v2hi_ftype_v2hi_v2hi); def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_ssaddv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FPADDS32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_ssaddv1si3, - v1si_ftype_v1si_v1si); + SPARC_BUILTIN_FPADDS32S, v1si_ftype_v1si_v1si); def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_sssubv2si3, - v2si_ftype_v2si_v2si); + SPARC_BUILTIN_FPSUBS32, v2si_ftype_v2si_v2si); def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_sssubv1si3, - v1si_ftype_v1si_v1si); + SPARC_BUILTIN_FPSUBS32S, v1si_ftype_v1si_v1si); if (TARGET_ARCH64) { def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8di_vis, - di_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPLE8, di_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8di_vis, - di_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPNE8, di_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8di_vis, - di_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPGT8, di_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8di_vis, - di_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPEQ8, di_ftype_v8qi_v8qi); } else { def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8si_vis, - si_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPLE8, si_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8si_vis, - si_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPNE8, si_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8si_vis, - si_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPGT8, si_ftype_v8qi_v8qi); def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8si_vis, - si_ftype_v8qi_v8qi); + SPARC_BUILTIN_FUCMPEQ8, si_ftype_v8qi_v8qi); } def_builtin_const ("__builtin_vis_fhadds", CODE_FOR_fhaddsf_vis, - sf_ftype_sf_sf); + SPARC_BUILTIN_FHADDS, sf_ftype_sf_sf); def_builtin_const ("__builtin_vis_fhaddd", CODE_FOR_fhadddf_vis, - df_ftype_df_df); + SPARC_BUILTIN_FHADDD, df_ftype_df_df); def_builtin_const ("__builtin_vis_fhsubs", CODE_FOR_fhsubsf_vis, - sf_ftype_sf_sf); + SPARC_BUILTIN_FHSUBS, sf_ftype_sf_sf); def_builtin_const ("__builtin_vis_fhsubd", CODE_FOR_fhsubdf_vis, - df_ftype_df_df); + SPARC_BUILTIN_FHSUBD, df_ftype_df_df); def_builtin_const ("__builtin_vis_fnhadds", CODE_FOR_fnhaddsf_vis, - sf_ftype_sf_sf); + SPARC_BUILTIN_FNHADDS, sf_ftype_sf_sf); def_builtin_const ("__builtin_vis_fnhaddd", CODE_FOR_fnhadddf_vis, - df_ftype_df_df); + SPARC_BUILTIN_FNHADDD, df_ftype_df_df); def_builtin_const ("__builtin_vis_umulxhi", CODE_FOR_umulxhi_vis, - di_ftype_di_di); + SPARC_BUILTIN_UMULXHI, di_ftype_di_di); def_builtin_const ("__builtin_vis_xmulx", CODE_FOR_xmulx_vis, - di_ftype_di_di); + SPARC_BUILTIN_XMULX, di_ftype_di_di); def_builtin_const ("__builtin_vis_xmulxhi", CODE_FOR_xmulxhi_vis, - di_ftype_di_di); + SPARC_BUILTIN_XMULXHI, di_ftype_di_di); } } -/* Handle TARGET_EXPAND_BUILTIN target hook. - Expand builtin functions for sparc intrinsics. */ +/* Implement TARGET_BUILTIN_DECL hook. */ + +static tree +sparc_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) +{ + if (code >= SPARC_BUILTIN_MAX) + return error_mark_node; + + return sparc_builtins[code]; +} + +/* Implemented TARGET_EXPAND_BUILTIN hook. */ static rtx sparc_expand_builtin (tree exp, rtx target, @@ -10414,15 +10579,14 @@ sparc_expand_builtin (tree exp, rtx target, enum machine_mode tmode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { - tree arg; - call_expr_arg_iterator iter; tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - unsigned int icode = DECL_FUNCTION_CODE (fndecl); - rtx pat, op[4]; + enum sparc_builtins code = (enum sparc_builtins) DECL_FUNCTION_CODE (fndecl); + enum insn_code icode = sparc_builtins_icode[code]; + bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + call_expr_arg_iterator iter; int arg_count = 0; - bool nonvoid; - - nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + rtx pat, op[4]; + tree arg; if (nonvoid) { @@ -10434,6 +10598,7 @@ sparc_expand_builtin (tree exp, rtx target, else op[0] = target; } + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) { const struct insn_operand_data *insn_op; @@ -10447,11 +10612,22 @@ sparc_expand_builtin (tree exp, rtx target, insn_op = &insn_data[icode].operand[idx]; op[arg_count] = expand_normal (arg); - if (insn_op->mode == V1DImode - && GET_MODE (op[arg_count]) == DImode) + if (code == SPARC_BUILTIN_LDFSR || code == SPARC_BUILTIN_STFSR) + { + if (!address_operand (op[arg_count], SImode)) + { + op[arg_count] = convert_memory_address (Pmode, op[arg_count]); + op[arg_count] = copy_addr_to_reg (op[arg_count]); + } + op[arg_count] = gen_rtx_MEM (SImode, op[arg_count]); + } + + else if (insn_op->mode == V1DImode + && GET_MODE (op[arg_count]) == DImode) op[arg_count] = gen_lowpart (V1DImode, op[arg_count]); + else if (insn_op->mode == V1SImode - && GET_MODE (op[arg_count]) == SImode) + && GET_MODE (op[arg_count]) == SImode) op[arg_count] = gen_lowpart (V1SImode, op[arg_count]); if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count], @@ -10485,12 +10661,11 @@ sparc_expand_builtin (tree exp, rtx target, emit_insn (pat); - if (nonvoid) - return op[0]; - else - return const0_rtx; + return (nonvoid ? op[0] : const0_rtx); } +/* Return the upper 16 bits of the 8x16 multiplication. */ + static int sparc_vis_mul8x16 (int e8, int e16) { @@ -10501,15 +10676,15 @@ sparc_vis_mul8x16 (int e8, int e16) the result into the array N_ELTS, whose elements are of INNER_TYPE. */ static void -sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type, - tree cst0, tree cst1) +sparc_handle_vis_mul8x16 (tree *n_elts, enum sparc_builtins fncode, + tree inner_type, tree cst0, tree cst1) { unsigned i, num = VECTOR_CST_NELTS (cst0); int scale; switch (fncode) { - case CODE_FOR_fmul8x16_vis: + case SPARC_BUILTIN_FMUL8X16: for (i = 0; i < num; ++i) { int val @@ -10519,7 +10694,7 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type, } break; - case CODE_FOR_fmul8x16au_vis: + case SPARC_BUILTIN_FMUL8X16AU: scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 0)); for (i = 0; i < num; ++i) @@ -10531,7 +10706,7 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type, } break; - case CODE_FOR_fmul8x16al_vis: + case SPARC_BUILTIN_FMUL8X16AL: scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 1)); for (i = 0; i < num; ++i) @@ -10548,7 +10723,8 @@ sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type, } } -/* Handle TARGET_FOLD_BUILTIN target hook. +/* Implement TARGET_FOLD_BUILTIN hook. + Fold builtin functions for SPARC intrinsics. If IGNORE is true the result of the function call is ignored. NULL_TREE is returned if the function could not be folded. */ @@ -10557,34 +10733,30 @@ static tree sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args, bool ignore) { - tree arg0, arg1, arg2; + enum sparc_builtins code = (enum sparc_builtins) DECL_FUNCTION_CODE (fndecl); tree rtype = TREE_TYPE (TREE_TYPE (fndecl)); - enum insn_code icode = (enum insn_code) DECL_FUNCTION_CODE (fndecl); + tree arg0, arg1, arg2; if (ignore) - { - /* Note that a switch statement instead of the sequence of tests would - be incorrect as many of the CODE_FOR values could be CODE_FOR_nothing - and that would yield multiple alternatives with identical values. */ - if (icode == CODE_FOR_alignaddrsi_vis - || icode == CODE_FOR_alignaddrdi_vis - || icode == CODE_FOR_wrgsr_vis - || icode == CODE_FOR_bmasksi_vis - || icode == CODE_FOR_bmaskdi_vis - || icode == CODE_FOR_cmask8si_vis - || icode == CODE_FOR_cmask8di_vis - || icode == CODE_FOR_cmask16si_vis - || icode == CODE_FOR_cmask16di_vis - || icode == CODE_FOR_cmask32si_vis - || icode == CODE_FOR_cmask32di_vis) - ; - else + switch (code) + { + case SPARC_BUILTIN_LDFSR: + case SPARC_BUILTIN_STFSR: + case SPARC_BUILTIN_ALIGNADDR: + case SPARC_BUILTIN_WRGSR: + case SPARC_BUILTIN_BMASK: + case SPARC_BUILTIN_CMASK8: + case SPARC_BUILTIN_CMASK16: + case SPARC_BUILTIN_CMASK32: + break; + + default: return build_zero_cst (rtype); - } + } - switch (icode) + switch (code) { - case CODE_FOR_fexpand_vis: + case SPARC_BUILTIN_FEXPAND: arg0 = args[0]; STRIP_NOPS (arg0); @@ -10603,9 +10775,9 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, } break; - case CODE_FOR_fmul8x16_vis: - case CODE_FOR_fmul8x16au_vis: - case CODE_FOR_fmul8x16al_vis: + case SPARC_BUILTIN_FMUL8X16: + case SPARC_BUILTIN_FMUL8X16AU: + case SPARC_BUILTIN_FMUL8X16AL: arg0 = args[0]; arg1 = args[1]; STRIP_NOPS (arg0); @@ -10615,12 +10787,12 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, { tree inner_type = TREE_TYPE (rtype); tree *n_elts = XALLOCAVEC (tree, VECTOR_CST_NELTS (arg0)); - sparc_handle_vis_mul8x16 (n_elts, icode, inner_type, arg0, arg1); + sparc_handle_vis_mul8x16 (n_elts, code, inner_type, arg0, arg1); return build_vector (rtype, n_elts); } break; - case CODE_FOR_fpmerge_vis: + case SPARC_BUILTIN_FPMERGE: arg0 = args[0]; arg1 = args[1]; STRIP_NOPS (arg0); @@ -10640,13 +10812,19 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, } break; - case CODE_FOR_pdist_vis: + case SPARC_BUILTIN_PDIST: + case SPARC_BUILTIN_PDISTN: arg0 = args[0]; arg1 = args[1]; - arg2 = args[2]; STRIP_NOPS (arg0); STRIP_NOPS (arg1); - STRIP_NOPS (arg2); + if (code == SPARC_BUILTIN_PDIST) + { + arg2 = args[2]; + STRIP_NOPS (arg2); + } + else + arg2 = integer_zero_node; if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST @@ -12325,9 +12503,106 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) return true; } -static enum machine_mode sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED) +/* Implement TARGET_CSTORE_MODE. */ + +static enum machine_mode +sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED) { return (TARGET_ARCH64 ? DImode : SImode); } +/* Return the compound expression made of T1 and T2. */ + +static inline tree +compound_expr (tree t1, tree t2) +{ + return build2 (COMPOUND_EXPR, void_type_node, t1, t2); +} + +/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV hook. */ + +static void +sparc_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) +{ + if (!TARGET_FPU) + return; + + const unsigned HOST_WIDE_INT accrued_exception_mask = 0x1f << 5; + const unsigned HOST_WIDE_INT trap_enable_mask = 0x1f << 23; + + /* We generate the equivalent of feholdexcept (&fenv_var): + + unsigned int fenv_var; + __builtin_store_fsr (&fenv_var); + + unsigned int tmp1_var; + tmp1_var = fenv_var & ~(accrued_exception_mask | trap_enable_mask); + + __builtin_load_fsr (&tmp1_var); */ + + tree fenv_var = create_tmp_var (unsigned_type_node, NULL); + mark_addressable (fenv_var); + tree fenv_addr = build_fold_addr_expr (fenv_var); + tree stfsr = sparc_builtins[SPARC_BUILTIN_STFSR]; + tree hold_stfsr = build_call_expr (stfsr, 1, fenv_addr); + + tree tmp1_var = create_tmp_var (unsigned_type_node, NULL); + mark_addressable (tmp1_var); + tree masked_fenv_var + = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, + build_int_cst (unsigned_type_node, + ~(accrued_exception_mask | trap_enable_mask))); + tree hold_mask + = build2 (MODIFY_EXPR, void_type_node, tmp1_var, masked_fenv_var); + + tree tmp1_addr = build_fold_addr_expr (tmp1_var); + tree ldfsr = sparc_builtins[SPARC_BUILTIN_LDFSR]; + tree hold_ldfsr = build_call_expr (ldfsr, 1, tmp1_addr); + + *hold = compound_expr (compound_expr (hold_stfsr, hold_mask), hold_ldfsr); + + /* We reload the value of tmp1_var to clear the exceptions: + + __builtin_load_fsr (&tmp1_var); */ + + *clear = build_call_expr (ldfsr, 1, tmp1_addr); + + /* We generate the equivalent of feupdateenv (&fenv_var): + + unsigned int tmp2_var; + __builtin_store_fsr (&tmp2_var); + + __builtin_load_fsr (&fenv_var); + + if (SPARC_LOW_FE_EXCEPT_VALUES) + tmp2_var >>= 5; + __atomic_feraiseexcept ((int) tmp2_var); */ + + tree tmp2_var = create_tmp_var (unsigned_type_node, NULL); + mark_addressable (tmp2_var); + tree tmp3_addr = build_fold_addr_expr (tmp2_var); + tree update_stfsr = build_call_expr (stfsr, 1, tmp3_addr); + + tree update_ldfsr = build_call_expr (ldfsr, 1, fenv_addr); + + tree atomic_feraiseexcept + = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT); + tree update_call + = build_call_expr (atomic_feraiseexcept, 1, + fold_convert (integer_type_node, tmp2_var)); + + if (SPARC_LOW_FE_EXCEPT_VALUES) + { + tree shifted_tmp2_var + = build2 (RSHIFT_EXPR, unsigned_type_node, tmp2_var, + build_int_cst (unsigned_type_node, 5)); + tree update_shift + = build2 (MODIFY_EXPR, void_type_node, tmp2_var, shifted_tmp2_var); + update_call = compound_expr (update_shift, update_call); + } + + *update + = compound_expr (compound_expr (update_stfsr, update_ldfsr), update_call); +} + #include "gt-sparc.h" diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d96c1b6b422..7533e88491b 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1777,3 +1777,6 @@ extern int sparc_indent_opcode; #ifndef SUBTARGET_DEFAULT_MEMORY_MODEL #define SUBTARGET_DEFAULT_MEMORY_MODEL SMM_DEFAULT #endif + +/* Define this to 1 if the FE_EXCEPT values defined in fenv.h start at 1. */ +#define SPARC_LOW_FE_EXCEPT_VALUES 0 diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index be7bbe977a2..b3fb2eb18fb 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -96,13 +96,19 @@ (define_c_enum "unspecv" [ UNSPECV_BLOCKAGE + UNSPECV_PROBE_STACK_RANGE + UNSPECV_FLUSHW - UNSPECV_FLUSH UNSPECV_SAVEW - UNSPECV_CAS - UNSPECV_SWAP + + UNSPECV_FLUSH + UNSPECV_LDSTUB - UNSPECV_PROBE_STACK_RANGE + UNSPECV_SWAP + UNSPECV_CAS + + UNSPECV_LDFSR + UNSPECV_STFSR ]) (define_constants @@ -6783,22 +6789,26 @@ ;; Special pattern for the FLUSH instruction. -; We do SImode and DImode versions of this to quiet down genrecog's complaints -; of the define_insn otherwise missing a mode. We make "flush", aka -; gen_flush, the default one since sparc_initialize_trampoline uses -; it on SImode mem values. - -(define_insn "flush" - [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)] +(define_insn "flush<P:mode>" + [(unspec_volatile [(match_operand:P 0 "memory_operand" "m")] UNSPECV_FLUSH)] "" { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; } [(set_attr "type" "iflush")]) -(define_insn "flushdi" - [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)] - "" - { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; } - [(set_attr "type" "iflush")]) +;; Special insns to load and store the 32-bit FP Status Register. + +(define_insn "ldfsr" + [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_LDFSR)] + "TARGET_FPU" + "ld\t%0, %%fsr" + [(set_attr "type" "load")]) + +(define_insn "stfsr" + [(set (match_operand:SI 0 "memory_operand" "=m") + (unspec_volatile:SI [(const_int 0)] UNSPECV_STFSR))] + "TARGET_FPU" + "st\t%%fsr, %0" + [(set_attr "type" "store")]) ;; Find first set instructions. |