PR target/84064
[official-gcc.git] / gcc / config / nds32 / nds32-intrinsic.c
blob5a1b92d604c13216b57a7f6e9524084a5d4497ce
1 /* Intrinsic functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* ------------------------------------------------------------------------ */
23 #define IN_TARGET_CODE 1
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "memmodel.h"
33 #include "optabs.h" /* For GEN_FCN. */
34 #include "diagnostic-core.h"
35 #include "stor-layout.h"
36 #include "expr.h"
37 #include "langhooks.h" /* For add_builtin_function(). */
39 /* ------------------------------------------------------------------------ */
41 /* Function to expand builtin function for
42 '[(unspec_volatile [(reg)])]'. */
43 static rtx
44 nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
45 tree exp, rtx target)
47 /* Mapping:
48 ops[0] <--> value0 <--> arg0 */
49 struct expand_operand ops[1];
50 tree arg0;
51 rtx value0;
53 /* Grab the incoming arguments and extract its rtx. */
54 arg0 = CALL_EXPR_ARG (exp, 0);
55 value0 = expand_normal (arg0);
57 /* Create operands. */
58 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
60 /* Emit new instruction. */
61 if (!maybe_expand_insn (icode, 1, ops))
62 error ("invalid argument to built-in function");
64 return target;
67 /* Function to expand builtin function for
68 '[(set (reg) (unspec_volatile [(imm)]))]'. */
69 static rtx
70 nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
71 tree exp, rtx target)
73 /* Mapping:
74 ops[0] <--> target <--> exp
75 ops[1] <--> value0 <--> arg0 */
76 struct expand_operand ops[2];
77 tree arg0;
78 rtx value0;
80 /* Grab the incoming arguments and extract its rtx. */
81 arg0 = CALL_EXPR_ARG (exp, 0);
82 value0 = expand_normal (arg0);
84 /* Create operands. */
85 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
86 create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
88 /* Emit new instruction. */
89 if (!maybe_expand_insn (icode, 2, ops))
90 error ("invalid argument to built-in function");
92 return target;
95 /* Function to expand builtin function for
96 '[(unspec_volatile [(reg) (imm)])]' pattern. */
97 static rtx
98 nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
99 tree exp, rtx target)
101 /* Mapping:
102 ops[0] <--> value0 <--> arg0
103 ops[1] <--> value1 <--> arg1 */
104 struct expand_operand ops[2];
105 tree arg0, arg1;
106 rtx value0, value1;
108 /* Grab the incoming arguments and extract its rtx. */
109 arg0 = CALL_EXPR_ARG (exp, 0);
110 arg1 = CALL_EXPR_ARG (exp, 1);
111 value0 = expand_normal (arg0);
112 value1 = expand_normal (arg1);
114 /* Create operands. */
115 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
116 create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
118 /* Emit new instruction. */
119 if (!maybe_expand_insn (icode, 2, ops))
120 error ("invalid argument to built-in function");
122 return target;
125 /* ------------------------------------------------------------------------ */
127 void
128 nds32_init_builtins_impl (void)
130 tree pointer_type_node = build_pointer_type (integer_type_node);
132 tree void_ftype_void = build_function_type (void_type_node,
133 void_list_node);
135 tree void_ftype_pint = build_function_type_list (void_type_node,
136 pointer_type_node,
137 NULL_TREE);
139 tree int_ftype_int = build_function_type_list (integer_type_node,
140 integer_type_node,
141 NULL_TREE);
143 tree void_ftype_int_int = build_function_type_list (void_type_node,
144 integer_type_node,
145 integer_type_node,
146 NULL_TREE);
148 /* Cache. */
149 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
150 NDS32_BUILTIN_ISYNC,
151 BUILT_IN_MD, NULL, NULL_TREE);
152 add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
153 NDS32_BUILTIN_ISB,
154 BUILT_IN_MD, NULL, NULL_TREE);
156 /* Register Transfer. */
157 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
158 NDS32_BUILTIN_MFSR,
159 BUILT_IN_MD, NULL, NULL_TREE);
160 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
161 NDS32_BUILTIN_MFUSR,
162 BUILT_IN_MD, NULL, NULL_TREE);
163 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
164 NDS32_BUILTIN_MTSR,
165 BUILT_IN_MD, NULL, NULL_TREE);
166 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
167 NDS32_BUILTIN_MTUSR,
168 BUILT_IN_MD, NULL, NULL_TREE);
170 /* Interrupt. */
171 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
172 NDS32_BUILTIN_SETGIE_EN,
173 BUILT_IN_MD, NULL, NULL_TREE);
174 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
175 NDS32_BUILTIN_SETGIE_DIS,
176 BUILT_IN_MD, NULL, NULL_TREE);
181 nds32_expand_builtin_impl (tree exp,
182 rtx target,
183 rtx subtarget ATTRIBUTE_UNUSED,
184 machine_mode mode ATTRIBUTE_UNUSED,
185 int ignore ATTRIBUTE_UNUSED)
187 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
189 int fcode = DECL_FUNCTION_CODE (fndecl);
191 switch (fcode)
193 /* Cache. */
194 case NDS32_BUILTIN_ISYNC:
195 return nds32_expand_builtin_null_ftype_reg
196 (CODE_FOR_unspec_volatile_isync, exp, target);
197 case NDS32_BUILTIN_ISB:
198 /* Since there are no result and operands for isb instruciton,
199 we can simply emit this rtx. */
200 emit_insn (gen_unspec_volatile_isb ());
201 return target;
203 /* Register Transfer. */
204 case NDS32_BUILTIN_MFSR:
205 return nds32_expand_builtin_reg_ftype_imm
206 (CODE_FOR_unspec_volatile_mfsr, exp, target);
207 case NDS32_BUILTIN_MFUSR:
208 return nds32_expand_builtin_reg_ftype_imm
209 (CODE_FOR_unspec_volatile_mfusr, exp, target);
210 case NDS32_BUILTIN_MTSR:
211 return nds32_expand_builtin_null_ftype_reg_imm
212 (CODE_FOR_unspec_volatile_mtsr, exp, target);
213 case NDS32_BUILTIN_MTUSR:
214 return nds32_expand_builtin_null_ftype_reg_imm
215 (CODE_FOR_unspec_volatile_mtusr, exp, target);
217 /* Interrupt. */
218 case NDS32_BUILTIN_SETGIE_EN:
219 /* Since there are no result and operands for setgie.e instruciton,
220 we can simply emit this rtx. */
221 emit_insn (gen_unspec_volatile_setgie_en ());
222 return target;
223 case NDS32_BUILTIN_SETGIE_DIS:
224 /* Since there are no result and operands for setgie.d instruciton,
225 we can simply emit this rtx. */
226 emit_insn (gen_unspec_volatile_setgie_dis ());
227 return target;
229 default:
230 gcc_unreachable ();
233 return NULL_RTX;
236 /* ------------------------------------------------------------------------ */