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