nds32-intrinsic.c revision 1.1.1.2
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)])]'.  */
40static rtx
41nds32_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)]))]'.  */
66static rtx
67nds32_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.  */
94static rtx
95nds32_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
124void
125nds32_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
177rtx
178nds32_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