nds32-intrinsic.c revision 1.1
1/* Intrinsic functions of Andes NDS32 cpu for GNU compiler
2   Copyright (C) 2012-2015 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 "tm.h"
27#include "hash-set.h"
28#include "machmode.h"
29#include "vec.h"
30#include "double-int.h"
31#include "input.h"
32#include "alias.h"
33#include "symtab.h"
34#include "wide-int.h"
35#include "inchash.h"
36#include "tree.h"
37#include "stor-layout.h"
38#include "varasm.h"
39#include "calls.h"
40#include "rtl.h"
41#include "regs.h"
42#include "hard-reg-set.h"
43#include "insn-config.h"	/* Required by recog.h.  */
44#include "conditions.h"
45#include "output.h"
46#include "insn-attr.h"		/* For DFA state_t.  */
47#include "insn-codes.h"		/* For CODE_FOR_xxx.  */
48#include "reload.h"		/* For push_reload().  */
49#include "flags.h"
50#include "function.h"
51#include "hashtab.h"
52#include "statistics.h"
53#include "real.h"
54#include "fixed-value.h"
55#include "insn-config.h"
56#include "expmed.h"
57#include "dojump.h"
58#include "explow.h"
59#include "emit-rtl.h"
60#include "stmt.h"
61#include "expr.h"
62#include "recog.h"
63#include "diagnostic-core.h"
64#include "dominance.h"
65#include "cfg.h"
66#include "cfgrtl.h"
67#include "cfganal.h"
68#include "lcm.h"
69#include "cfgbuild.h"
70#include "cfgcleanup.h"
71#include "predict.h"
72#include "basic-block.h"
73#include "df.h"
74#include "tm_p.h"
75#include "tm-constrs.h"
76#include "optabs.h"		/* For GEN_FCN.  */
77#include "target.h"
78#include "target-def.h"
79#include "langhooks.h"		/* For add_builtin_function().  */
80#include "ggc.h"
81#include "builtins.h"
82
83/* ------------------------------------------------------------------------ */
84
85/* Function to expand builtin function for
86   '[(unspec_volatile [(reg)])]'.  */
87static rtx
88nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
89				     tree exp, rtx target)
90{
91  /* Mapping:
92       ops[0] <--> value0 <--> arg0 */
93  struct expand_operand ops[1];
94  tree arg0;
95  rtx value0;
96
97  /* Grab the incoming arguments and extract its rtx.  */
98  arg0 = CALL_EXPR_ARG (exp, 0);
99  value0 = expand_normal (arg0);
100
101  /* Create operands.  */
102  create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
103
104  /* Emit new instruction.  */
105  if (!maybe_expand_insn (icode, 1, ops))
106    error ("invalid argument to built-in function");
107
108  return target;
109}
110
111/* Function to expand builtin function for
112   '[(set (reg) (unspec_volatile [(imm)]))]'.  */
113static rtx
114nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
115				    tree exp, rtx target)
116{
117  /* Mapping:
118       ops[0] <--> target <--> exp
119       ops[1] <--> value0 <--> arg0 */
120  struct expand_operand ops[2];
121  tree arg0;
122  rtx value0;
123
124  /* Grab the incoming arguments and extract its rtx.  */
125  arg0 = CALL_EXPR_ARG (exp, 0);
126  value0 = expand_normal (arg0);
127
128  /* Create operands.  */
129  create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
130  create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
131
132  /* Emit new instruction.  */
133  if (!maybe_expand_insn (icode, 2, ops))
134    error ("invalid argument to built-in function");
135
136  return target;
137}
138
139/* Function to expand builtin function for
140   '[(unspec_volatile [(reg) (imm)])]' pattern.  */
141static rtx
142nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
143					 tree exp, rtx target)
144{
145  /* Mapping:
146       ops[0] <--> value0 <--> arg0
147       ops[1] <--> value1 <--> arg1 */
148  struct expand_operand ops[2];
149  tree arg0, arg1;
150  rtx value0, value1;
151
152  /* Grab the incoming arguments and extract its rtx.  */
153  arg0 = CALL_EXPR_ARG (exp, 0);
154  arg1 = CALL_EXPR_ARG (exp, 1);
155  value0 = expand_normal (arg0);
156  value1 = expand_normal (arg1);
157
158  /* Create operands.  */
159  create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
160  create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
161
162  /* Emit new instruction.  */
163  if (!maybe_expand_insn (icode, 2, ops))
164    error ("invalid argument to built-in function");
165
166  return target;
167}
168
169/* ------------------------------------------------------------------------ */
170
171void
172nds32_init_builtins_impl (void)
173{
174  tree pointer_type_node  = build_pointer_type (integer_type_node);
175
176  tree void_ftype_void    = build_function_type (void_type_node,
177						 void_list_node);
178
179  tree void_ftype_pint    = build_function_type_list (void_type_node,
180						      pointer_type_node,
181						      NULL_TREE);
182
183  tree int_ftype_int      = build_function_type_list (integer_type_node,
184						      integer_type_node,
185						      NULL_TREE);
186
187  tree void_ftype_int_int = build_function_type_list (void_type_node,
188						      integer_type_node,
189						      integer_type_node,
190						      NULL_TREE);
191
192  /* Cache.  */
193  add_builtin_function ("__builtin_nds32_isync",  void_ftype_pint,
194			NDS32_BUILTIN_ISYNC,
195			BUILT_IN_MD, NULL, NULL_TREE);
196  add_builtin_function ("__builtin_nds32_isb",  void_ftype_void,
197			NDS32_BUILTIN_ISB,
198			BUILT_IN_MD, NULL, NULL_TREE);
199
200  /* Register Transfer.  */
201  add_builtin_function ("__builtin_nds32_mfsr",  int_ftype_int,
202			NDS32_BUILTIN_MFSR,
203			BUILT_IN_MD, NULL, NULL_TREE);
204  add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
205			NDS32_BUILTIN_MFUSR,
206			BUILT_IN_MD, NULL, NULL_TREE);
207  add_builtin_function ("__builtin_nds32_mtsr",  void_ftype_int_int,
208			NDS32_BUILTIN_MTSR,
209			BUILT_IN_MD, NULL, NULL_TREE);
210  add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
211			NDS32_BUILTIN_MTUSR,
212			BUILT_IN_MD, NULL, NULL_TREE);
213
214  /* Interrupt.  */
215  add_builtin_function ("__builtin_nds32_setgie_en",  void_ftype_void,
216			NDS32_BUILTIN_SETGIE_EN,
217			BUILT_IN_MD, NULL, NULL_TREE);
218  add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
219			NDS32_BUILTIN_SETGIE_DIS,
220			BUILT_IN_MD, NULL, NULL_TREE);
221}
222
223
224rtx
225nds32_expand_builtin_impl (tree exp,
226			   rtx target,
227			   rtx subtarget ATTRIBUTE_UNUSED,
228			   machine_mode mode ATTRIBUTE_UNUSED,
229			   int ignore ATTRIBUTE_UNUSED)
230{
231  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
232
233  int fcode = DECL_FUNCTION_CODE (fndecl);
234
235  switch (fcode)
236    {
237    /* Cache.  */
238    case NDS32_BUILTIN_ISYNC:
239      return nds32_expand_builtin_null_ftype_reg
240	     (CODE_FOR_unspec_volatile_isync, exp, target);
241    case NDS32_BUILTIN_ISB:
242      /* Since there are no result and operands for isb instruciton,
243         we can simply emit this rtx.  */
244      emit_insn (gen_unspec_volatile_isb ());
245      return target;
246
247    /* Register Transfer.  */
248    case NDS32_BUILTIN_MFSR:
249      return nds32_expand_builtin_reg_ftype_imm
250	     (CODE_FOR_unspec_volatile_mfsr, exp, target);
251    case NDS32_BUILTIN_MFUSR:
252      return nds32_expand_builtin_reg_ftype_imm
253	     (CODE_FOR_unspec_volatile_mfusr, exp, target);
254    case NDS32_BUILTIN_MTSR:
255      return nds32_expand_builtin_null_ftype_reg_imm
256	     (CODE_FOR_unspec_volatile_mtsr, exp, target);
257    case NDS32_BUILTIN_MTUSR:
258      return nds32_expand_builtin_null_ftype_reg_imm
259	     (CODE_FOR_unspec_volatile_mtusr, exp, target);
260
261    /* Interrupt.  */
262    case NDS32_BUILTIN_SETGIE_EN:
263      /* Since there are no result and operands for setgie.e instruciton,
264         we can simply emit this rtx.  */
265      emit_insn (gen_unspec_volatile_setgie_en ());
266      return target;
267    case NDS32_BUILTIN_SETGIE_DIS:
268      /* Since there are no result and operands for setgie.d instruciton,
269         we can simply emit this rtx.  */
270      emit_insn (gen_unspec_volatile_setgie_dis ());
271      return target;
272
273    default:
274      gcc_unreachable ();
275    }
276
277  return NULL_RTX;
278}
279
280/* ------------------------------------------------------------------------ */
281