111
|
1 /* Intrinsic functions of Andes NDS32 cpu for GNU compiler
|
|
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
|
3 Contributed by Andes Technology Corporation.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
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.
|
|
11
|
|
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.
|
|
16
|
|
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/>. */
|
|
20
|
|
21 /* ------------------------------------------------------------------------ */
|
|
22
|
|
23 #include "config.h"
|
|
24 #include "system.h"
|
|
25 #include "coretypes.h"
|
|
26 #include "backend.h"
|
|
27 #include "target.h"
|
|
28 #include "rtl.h"
|
|
29 #include "tree.h"
|
|
30 #include "memmodel.h"
|
|
31 #include "optabs.h" /* For GEN_FCN. */
|
|
32 #include "diagnostic-core.h"
|
|
33 #include "stor-layout.h"
|
|
34 #include "expr.h"
|
|
35 #include "langhooks.h" /* For add_builtin_function(). */
|
|
36
|
|
37 /* ------------------------------------------------------------------------ */
|
|
38
|
|
39 /* Function to expand builtin function for
|
|
40 '[(unspec_volatile [(reg)])]'. */
|
|
41 static rtx
|
|
42 nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
|
|
43 tree exp, rtx target)
|
|
44 {
|
|
45 /* Mapping:
|
|
46 ops[0] <--> value0 <--> arg0 */
|
|
47 struct expand_operand ops[1];
|
|
48 tree arg0;
|
|
49 rtx value0;
|
|
50
|
|
51 /* Grab the incoming arguments and extract its rtx. */
|
|
52 arg0 = CALL_EXPR_ARG (exp, 0);
|
|
53 value0 = expand_normal (arg0);
|
|
54
|
|
55 /* Create operands. */
|
|
56 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
57
|
|
58 /* Emit new instruction. */
|
|
59 if (!maybe_expand_insn (icode, 1, ops))
|
|
60 error ("invalid argument to built-in function");
|
|
61
|
|
62 return target;
|
|
63 }
|
|
64
|
|
65 /* Function to expand builtin function for
|
|
66 '[(set (reg) (unspec_volatile [(imm)]))]'. */
|
|
67 static rtx
|
|
68 nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
|
|
69 tree exp, rtx target)
|
|
70 {
|
|
71 /* Mapping:
|
|
72 ops[0] <--> target <--> exp
|
|
73 ops[1] <--> value0 <--> arg0 */
|
|
74 struct expand_operand ops[2];
|
|
75 tree arg0;
|
|
76 rtx value0;
|
|
77
|
|
78 /* Grab the incoming arguments and extract its rtx. */
|
|
79 arg0 = CALL_EXPR_ARG (exp, 0);
|
|
80 value0 = expand_normal (arg0);
|
|
81
|
|
82 /* Create operands. */
|
|
83 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
|
|
84 create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
85
|
|
86 /* Emit new instruction. */
|
|
87 if (!maybe_expand_insn (icode, 2, ops))
|
|
88 error ("invalid argument to built-in function");
|
|
89
|
|
90 return target;
|
|
91 }
|
|
92
|
|
93 /* Function to expand builtin function for
|
|
94 '[(unspec_volatile [(reg) (imm)])]' pattern. */
|
|
95 static rtx
|
|
96 nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
|
|
97 tree exp, rtx target)
|
|
98 {
|
|
99 /* Mapping:
|
|
100 ops[0] <--> value0 <--> arg0
|
|
101 ops[1] <--> value1 <--> arg1 */
|
|
102 struct expand_operand ops[2];
|
|
103 tree arg0, arg1;
|
|
104 rtx value0, value1;
|
|
105
|
|
106 /* Grab the incoming arguments and extract its rtx. */
|
|
107 arg0 = CALL_EXPR_ARG (exp, 0);
|
|
108 arg1 = CALL_EXPR_ARG (exp, 1);
|
|
109 value0 = expand_normal (arg0);
|
|
110 value1 = expand_normal (arg1);
|
|
111
|
|
112 /* Create operands. */
|
|
113 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
|
|
114 create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
|
|
115
|
|
116 /* Emit new instruction. */
|
|
117 if (!maybe_expand_insn (icode, 2, ops))
|
|
118 error ("invalid argument to built-in function");
|
|
119
|
|
120 return target;
|
|
121 }
|
|
122
|
|
123 /* ------------------------------------------------------------------------ */
|
|
124
|
|
125 void
|
|
126 nds32_init_builtins_impl (void)
|
|
127 {
|
|
128 tree pointer_type_node = build_pointer_type (integer_type_node);
|
|
129
|
|
130 tree void_ftype_void = build_function_type (void_type_node,
|
|
131 void_list_node);
|
|
132
|
|
133 tree void_ftype_pint = build_function_type_list (void_type_node,
|
|
134 pointer_type_node,
|
|
135 NULL_TREE);
|
|
136
|
|
137 tree int_ftype_int = build_function_type_list (integer_type_node,
|
|
138 integer_type_node,
|
|
139 NULL_TREE);
|
|
140
|
|
141 tree void_ftype_int_int = build_function_type_list (void_type_node,
|
|
142 integer_type_node,
|
|
143 integer_type_node,
|
|
144 NULL_TREE);
|
|
145
|
|
146 /* Cache. */
|
|
147 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
|
|
148 NDS32_BUILTIN_ISYNC,
|
|
149 BUILT_IN_MD, NULL, NULL_TREE);
|
|
150 add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
|
|
151 NDS32_BUILTIN_ISB,
|
|
152 BUILT_IN_MD, NULL, NULL_TREE);
|
|
153
|
|
154 /* Register Transfer. */
|
|
155 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
|
|
156 NDS32_BUILTIN_MFSR,
|
|
157 BUILT_IN_MD, NULL, NULL_TREE);
|
|
158 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
|
|
159 NDS32_BUILTIN_MFUSR,
|
|
160 BUILT_IN_MD, NULL, NULL_TREE);
|
|
161 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
|
|
162 NDS32_BUILTIN_MTSR,
|
|
163 BUILT_IN_MD, NULL, NULL_TREE);
|
|
164 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
|
|
165 NDS32_BUILTIN_MTUSR,
|
|
166 BUILT_IN_MD, NULL, NULL_TREE);
|
|
167
|
|
168 /* Interrupt. */
|
|
169 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
|
|
170 NDS32_BUILTIN_SETGIE_EN,
|
|
171 BUILT_IN_MD, NULL, NULL_TREE);
|
|
172 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
|
|
173 NDS32_BUILTIN_SETGIE_DIS,
|
|
174 BUILT_IN_MD, NULL, NULL_TREE);
|
|
175 }
|
|
176
|
|
177
|
|
178 rtx
|
|
179 nds32_expand_builtin_impl (tree exp,
|
|
180 rtx target,
|
|
181 rtx subtarget ATTRIBUTE_UNUSED,
|
|
182 machine_mode mode ATTRIBUTE_UNUSED,
|
|
183 int ignore ATTRIBUTE_UNUSED)
|
|
184 {
|
|
185 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
|
186
|
|
187 int fcode = DECL_FUNCTION_CODE (fndecl);
|
|
188
|
|
189 switch (fcode)
|
|
190 {
|
|
191 /* Cache. */
|
|
192 case NDS32_BUILTIN_ISYNC:
|
|
193 return nds32_expand_builtin_null_ftype_reg
|
|
194 (CODE_FOR_unspec_volatile_isync, exp, target);
|
|
195 case NDS32_BUILTIN_ISB:
|
|
196 /* Since there are no result and operands for isb instruciton,
|
|
197 we can simply emit this rtx. */
|
|
198 emit_insn (gen_unspec_volatile_isb ());
|
|
199 return target;
|
|
200
|
|
201 /* Register Transfer. */
|
|
202 case NDS32_BUILTIN_MFSR:
|
|
203 return nds32_expand_builtin_reg_ftype_imm
|
|
204 (CODE_FOR_unspec_volatile_mfsr, exp, target);
|
|
205 case NDS32_BUILTIN_MFUSR:
|
|
206 return nds32_expand_builtin_reg_ftype_imm
|
|
207 (CODE_FOR_unspec_volatile_mfusr, exp, target);
|
|
208 case NDS32_BUILTIN_MTSR:
|
|
209 return nds32_expand_builtin_null_ftype_reg_imm
|
|
210 (CODE_FOR_unspec_volatile_mtsr, exp, target);
|
|
211 case NDS32_BUILTIN_MTUSR:
|
|
212 return nds32_expand_builtin_null_ftype_reg_imm
|
|
213 (CODE_FOR_unspec_volatile_mtusr, exp, target);
|
|
214
|
|
215 /* Interrupt. */
|
|
216 case NDS32_BUILTIN_SETGIE_EN:
|
|
217 /* Since there are no result and operands for setgie.e instruciton,
|
|
218 we can simply emit this rtx. */
|
|
219 emit_insn (gen_unspec_volatile_setgie_en ());
|
|
220 return target;
|
|
221 case NDS32_BUILTIN_SETGIE_DIS:
|
|
222 /* Since there are no result and operands for setgie.d instruciton,
|
|
223 we can simply emit this rtx. */
|
|
224 emit_insn (gen_unspec_volatile_setgie_dis ());
|
|
225 return target;
|
|
226
|
|
227 default:
|
|
228 gcc_unreachable ();
|
|
229 }
|
|
230
|
|
231 return NULL_RTX;
|
|
232 }
|
|
233
|
|
234 /* ------------------------------------------------------------------------ */
|