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.
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 #define IN_TARGET_CODE 1
24 
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 "memmodel.h"
32 #include "emit-rtl.h"
33 #include "tree.h"
34 #include "memmodel.h"
35 #include "optabs.h"		/* For GEN_FCN.  */
36 #include "diagnostic-core.h"
37 #include "stor-layout.h"
38 #include "expr.h"
39 #include "langhooks.h"		/* For add_builtin_function().  */
40 #include "recog.h"
41 #include "explow.h"
42 
43 /* ------------------------------------------------------------------------ */
44 
45 /* Read the requested argument from the EXP given by INDEX.
46    Return the value as an rtx.  */
47 static rtx
nds32_read_argument(tree exp,unsigned int index)48 nds32_read_argument (tree exp, unsigned int index)
49 {
50   return expand_normal (CALL_EXPR_ARG (exp, index));
51 }
52 
53 /* Return a legitimate rtx for instruction ICODE's return value.  Use TARGET
54    if it's not null, has the right mode, and satisfies operand 0's
55    predicate.  */
56 static rtx
nds32_legitimize_target(enum insn_code icode,rtx target)57 nds32_legitimize_target (enum insn_code icode, rtx target)
58 {
59   enum machine_mode mode = insn_data[icode].operand[0].mode;
60 
61   if (! target
62       || GET_MODE (target) != mode
63       || ! (*insn_data[icode].operand[0].predicate) (target, mode))
64     return gen_reg_rtx (mode);
65   else
66     return target;
67 }
68 
69 /* Given that ARG is being passed as operand OPNUM to instruction ICODE,
70    check whether ARG satisfies the operand's constraints.  If it doesn't,
71    copy ARG to a temporary register and return that.  Otherwise return ARG
72    itself.  */
73 static rtx
nds32_legitimize_argument(enum insn_code icode,int opnum,rtx arg)74 nds32_legitimize_argument (enum insn_code icode, int opnum, rtx arg)
75 {
76   enum machine_mode mode = insn_data[icode].operand[opnum].mode;
77 
78   if ((*insn_data[icode].operand[opnum].predicate) (arg, mode))
79     return arg;
80   else if (VECTOR_MODE_P (mode) && CONST_INT_P (arg))
81     {
82       /* Handle CONST_INT covert to CONST_VECTOR.  */
83       int nunits = GET_MODE_NUNITS (mode);
84       int i, shift = 0;
85       rtvec v = rtvec_alloc (nunits);
86       int val = INTVAL (arg);
87       enum machine_mode val_mode = (mode == V4QImode) ? QImode : HImode;
88       int shift_acc = (val_mode == QImode) ? 8 : 16;
89       int mask = (val_mode == QImode) ? 0xff : 0xffff;
90       int tmp_val = val;
91 
92       if (TARGET_BIG_ENDIAN)
93 	for (i = 0; i < nunits; i++)
94 	  {
95 	    tmp_val = (val >> shift) & mask;
96 	    RTVEC_ELT (v, nunits - i - 1) = gen_int_mode (tmp_val, val_mode);
97 	    shift += shift_acc;
98 	  }
99       else
100 	for (i = 0; i < nunits; i++)
101 	  {
102 	    tmp_val = (val >> shift) & mask;
103 	    RTVEC_ELT (v, i) = gen_int_mode (tmp_val, val_mode);
104 	    shift += shift_acc;
105 	  }
106 
107       return copy_to_mode_reg (mode, gen_rtx_CONST_VECTOR (mode, v));
108     }
109   else
110     {
111       rtx tmp_rtx = gen_reg_rtx (mode);
112       convert_move (tmp_rtx, arg, false);
113       return tmp_rtx;
114     }
115 }
116 
117 /* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
118    The instruction should require a constant operand of some sort.  The
119    function prints an error if OPVAL is not valid.  */
120 static int
nds32_check_constant_argument(enum insn_code icode,int opnum,rtx opval,const char * name)121 nds32_check_constant_argument (enum insn_code icode, int opnum, rtx opval,
122 			       const char *name)
123 {
124   if (GET_CODE (opval) != CONST_INT)
125     {
126       error ("invalid argument to built-in function %s", name);
127       return false;
128     }
129   if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
130     {
131       error ("constant argument out of range for %s", name);
132 
133       return false;
134     }
135   return true;
136 }
137 
138 /* Expand builtins that return target.  */
139 static rtx
nds32_expand_noarg_builtin(enum insn_code icode,rtx target)140 nds32_expand_noarg_builtin (enum insn_code icode, rtx target)
141 {
142   rtx pat;
143 
144   target = nds32_legitimize_target (icode, target);
145 
146   /* Emit and return the new instruction. */
147   pat = GEN_FCN (icode) (target);
148   if (! pat)
149     return NULL_RTX;
150 
151   emit_insn (pat);
152   return target;
153 }
154 
155 /* Expand builtins that take one operand.  */
156 static rtx
nds32_expand_unop_builtin(enum insn_code icode,tree exp,rtx target,bool return_p)157 nds32_expand_unop_builtin (enum insn_code icode, tree exp, rtx target,
158 			   bool return_p)
159 {
160   rtx pat;
161   rtx op0 = nds32_read_argument (exp, 0);
162   int op0_num = return_p ? 1 : 0;
163 
164   if (return_p)
165     target = nds32_legitimize_target (icode, target);
166 
167   op0 = nds32_legitimize_argument (icode, op0_num, op0);
168 
169   /* Emit and return the new instruction. */
170   if (return_p)
171     pat = GEN_FCN (icode) (target, op0);
172   else
173     pat = GEN_FCN (icode) (op0);
174 
175   if (! pat)
176     return NULL_RTX;
177 
178   emit_insn (pat);
179   return target;
180 }
181 
182 /* Expand builtins that take one operands and the first is immediate.  */
183 static rtx
nds32_expand_unopimm_builtin(enum insn_code icode,tree exp,rtx target,bool return_p,const char * name)184 nds32_expand_unopimm_builtin (enum insn_code icode, tree exp, rtx target,
185 			      bool return_p, const char *name)
186 {
187   rtx pat;
188   rtx op0 = nds32_read_argument (exp, 0);
189   int op0_num = return_p ? 1 : 0;
190 
191   if (return_p)
192     target = nds32_legitimize_target (icode, target);
193 
194   if (!nds32_check_constant_argument (icode, op0_num, op0, name))
195     return NULL_RTX;
196 
197   op0 = nds32_legitimize_argument (icode, op0_num, op0);
198 
199   /* Emit and return the new instruction. */
200   if (return_p)
201     pat = GEN_FCN (icode) (target, op0);
202   else
203     pat = GEN_FCN (icode) (op0);
204 
205   if (! pat)
206     return NULL_RTX;
207 
208   emit_insn (pat);
209   return target;
210 }
211 
212 /* Expand builtins that take two operands.  */
213 static rtx
nds32_expand_binop_builtin(enum insn_code icode,tree exp,rtx target,bool return_p)214 nds32_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
215 			    bool return_p)
216 {
217   rtx pat;
218   rtx op0 = nds32_read_argument (exp, 0);
219   rtx op1 = nds32_read_argument (exp, 1);
220   int op0_num = return_p ? 1 : 0;
221   int op1_num = return_p ? 2 : 1;
222 
223   if (return_p)
224     target = nds32_legitimize_target (icode, target);
225 
226   op0 = nds32_legitimize_argument (icode, op0_num, op0);
227   op1 = nds32_legitimize_argument (icode, op1_num, op1);
228 
229   /* Emit and return the new instruction. */
230   if (return_p)
231     pat = GEN_FCN (icode) (target, op0, op1);
232   else
233     pat = GEN_FCN (icode) (op0, op1);
234 
235   if (! pat)
236     return NULL_RTX;
237 
238   emit_insn (pat);
239   return target;
240 }
241 
242 /* Expand builtins that take two operands and the second is immediate.  */
243 static rtx
nds32_expand_binopimm_builtin(enum insn_code icode,tree exp,rtx target,bool return_p,const char * name)244 nds32_expand_binopimm_builtin (enum insn_code icode, tree exp, rtx target,
245 			       bool return_p, const char *name)
246 {
247   rtx pat;
248   rtx op0 = nds32_read_argument (exp, 0);
249   rtx op1 = nds32_read_argument (exp, 1);
250   int op0_num = return_p ? 1 : 0;
251   int op1_num = return_p ? 2 : 1;
252 
253   if (return_p)
254     target = nds32_legitimize_target (icode, target);
255 
256   if (!nds32_check_constant_argument (icode, op1_num, op1, name))
257     return NULL_RTX;
258 
259   op0 = nds32_legitimize_argument (icode, op0_num, op0);
260   op1 = nds32_legitimize_argument (icode, op1_num, op1);
261 
262   /* Emit and return the new instruction. */
263   if (return_p)
264     pat = GEN_FCN (icode) (target, op0, op1);
265   else
266     pat = GEN_FCN (icode) (op0, op1);
267 
268   if (! pat)
269     return NULL_RTX;
270 
271   emit_insn (pat);
272   return target;
273 }
274 
275 /* Expand builtins that take three operands.  */
276 static rtx
nds32_expand_triop_builtin(enum insn_code icode,tree exp,rtx target,bool return_p)277 nds32_expand_triop_builtin (enum insn_code icode, tree exp, rtx target,
278 			    bool return_p)
279 {
280   rtx pat;
281   rtx op0 = nds32_read_argument (exp, 0);
282   rtx op1 = nds32_read_argument (exp, 1);
283   rtx op2 = nds32_read_argument (exp, 2);
284   int op0_num = return_p ? 1 : 0;
285   int op1_num = return_p ? 2 : 1;
286   int op2_num = return_p ? 3 : 2;
287 
288   if (return_p)
289     target = nds32_legitimize_target (icode, target);
290 
291   op0 = nds32_legitimize_argument (icode, op0_num, op0);
292   op1 = nds32_legitimize_argument (icode, op1_num, op1);
293   op2 = nds32_legitimize_argument (icode, op2_num, op2);
294 
295   /* Emit and return the new instruction. */
296   if (return_p)
297     pat = GEN_FCN (icode) (target, op0, op1, op2);
298   else
299     pat = GEN_FCN (icode) (op0, op1, op2);
300 
301   if (! pat)
302     return NULL_RTX;
303 
304   emit_insn (pat);
305   return target;
306 }
307 
308 /* Expand builtins that take three operands and the third is immediate.  */
309 static rtx
nds32_expand_triopimm_builtin(enum insn_code icode,tree exp,rtx target,bool return_p,const char * name)310 nds32_expand_triopimm_builtin (enum insn_code icode, tree exp, rtx target,
311 			       bool return_p, const char *name)
312 {
313   rtx pat;
314   rtx op0 = nds32_read_argument (exp, 0);
315   rtx op1 = nds32_read_argument (exp, 1);
316   rtx op2 = nds32_read_argument (exp, 2);
317   int op0_num = return_p ? 1 : 0;
318   int op1_num = return_p ? 2 : 1;
319   int op2_num = return_p ? 3 : 2;
320 
321   if (return_p)
322     target = nds32_legitimize_target (icode, target);
323 
324   if (!nds32_check_constant_argument (icode, op2_num, op2, name))
325     return NULL_RTX;
326 
327   op0 = nds32_legitimize_argument (icode, op0_num, op0);
328   op1 = nds32_legitimize_argument (icode, op1_num, op1);
329   op2 = nds32_legitimize_argument (icode, op2_num, op2);
330 
331   /* Emit and return the new instruction. */
332   if (return_p)
333     pat = GEN_FCN (icode) (target, op0, op1, op2);
334   else
335     pat = GEN_FCN (icode) (op0, op1, op2);
336 
337   if (! pat)
338     return NULL_RTX;
339 
340   emit_insn (pat);
341   return target;
342 }
343 
344 /* Expand builtins for load.  */
345 static rtx
nds32_expand_builtin_load(enum insn_code icode,tree exp,rtx target)346 nds32_expand_builtin_load (enum insn_code icode, tree exp, rtx target)
347 {
348   /* Load address format is [$ra + $rb],
349      but input arguments not enough,
350      so we need another temp register as $rb.
351      Generating assembly code:
352        movi $temp, 0
353        llw  $rt, [$ra + $temp] */
354   rtx pat;
355   rtx op0 = nds32_read_argument (exp, 0);
356   rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
357 
358   target = nds32_legitimize_target (icode, target);
359   op0 = nds32_legitimize_argument (icode, 1, op0);
360 
361   /* Emit and return the new instruction. */
362   pat = GEN_FCN (icode) (target, op0, addr_helper);
363   if (!pat)
364     return NULL_RTX;
365 
366   emit_move_insn (addr_helper, GEN_INT (0));
367   emit_insn (pat);
368   return target;
369 }
370 
371 /* Expand builtins for store.  */
372 static rtx
nds32_expand_builtin_store(enum insn_code icode,tree exp,rtx target)373 nds32_expand_builtin_store (enum insn_code icode, tree exp, rtx target)
374 {
375   /* Store address format is [$ra + $rb],
376      but input arguments not enough,
377      so we need another temp register as $rb.
378      Generating assembly code:
379        movi $temp, 0
380        store  $rt, [$ra + $temp] */
381   rtx pat;
382   rtx op0 = nds32_read_argument (exp, 0);
383   rtx op1 = nds32_read_argument (exp, 1);
384   rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
385 
386   op0 = nds32_legitimize_argument (icode, 0, op0);
387   op1 = nds32_legitimize_argument (icode, 2, op1);
388 
389   /* Emit and return the new instruction. */
390   pat = GEN_FCN (icode) (op0, addr_helper, op1);
391   if (! pat)
392     return NULL_RTX;
393 
394   emit_move_insn (addr_helper, GEN_INT (0));
395   emit_insn (pat);
396   return target;
397 }
398 
399 /* Expand cctl builtins.  */
400 static rtx
nds32_expand_cctl_builtin(enum insn_code icode,tree exp,rtx target,bool return_p,const char * name)401 nds32_expand_cctl_builtin (enum insn_code icode, tree exp, rtx target,
402 			   bool return_p, const char *name)
403 {
404   rtx pat;
405   rtx op0 = nds32_read_argument (exp, 0);
406   rtx op1 = nds32_read_argument (exp, 1);
407   int op0_num = return_p ? 1 : 0;
408   int op1_num = return_p ? 2 : 1;
409 
410   if (return_p)
411     target = nds32_legitimize_target (icode, target);
412 
413   if (!nds32_check_constant_argument (icode, op0_num, op0, name))
414     return NULL_RTX;
415 
416   op0 = nds32_legitimize_argument (icode, op0_num, op0);
417   op1 = nds32_legitimize_argument (icode, op1_num, op1);
418 
419   /* Emit and return the new instruction. */
420   if (icode == CODE_FOR_cctl_idx_write)
421     {
422       /* cctl_idx_write is three argument,
423 	 so create operand2 for cctl_idx_write pattern.  */
424       rtx op2 = nds32_read_argument (exp, 2);
425       op2 = nds32_legitimize_argument (icode, 2, op2);
426       pat = GEN_FCN (icode) (op0, op1, op2);
427     }
428   else if (return_p)
429     pat = GEN_FCN (icode) (target, op0, op1);
430   else
431     pat = GEN_FCN (icode) (op0, op1);
432 
433   if (! pat)
434     return NULL_RTX;
435 
436   emit_insn (pat);
437   return target;
438 }
439 
440 /* Expand scw builtins.  */
441 static rtx
nds32_expand_scw_builtin(enum insn_code icode,tree exp,rtx target)442 nds32_expand_scw_builtin (enum insn_code icode, tree exp, rtx target)
443 {
444   /* SCW address format is [$ra + $rb], but input arguments not enough,
445      so we need another temp register as $rb.
446      Generating assembly code:
447 	movi $temp, 0
448 	scw  $rt, [$ra + $temp] */
449   rtx pat;
450   rtx op0 = nds32_read_argument (exp, 0);
451   rtx op1 = nds32_read_argument (exp, 1);
452   rtx addr_helper = gen_reg_rtx (insn_data[icode].operand[1].mode);
453 
454   target = nds32_legitimize_target (icode, target);
455   op0 = nds32_legitimize_argument (icode, 1, op0);
456   op1 = nds32_legitimize_argument (icode, 2, op1);
457 
458   /* Emit and return the new instruction. */
459   pat = GEN_FCN (icode) (target, op0, addr_helper, target);
460 
461   if (!pat)
462     return NULL_RTX;
463 
464   emit_move_insn (addr_helper, GEN_INT (0));
465   emit_move_insn (target, op1);
466   emit_insn (pat);
467   return target;
468 }
469 
470 /* Expand set int priority builtins. */
471 static rtx
nds32_expand_priority_builtin(enum insn_code icode,tree exp,rtx target,const char * name)472 nds32_expand_priority_builtin (enum insn_code icode, tree exp, rtx target,
473 			       const char *name)
474 {
475   rtx pat;
476   rtx op0 = nds32_read_argument (exp, 0);
477   rtx op1 = nds32_read_argument (exp, 1);
478 
479   /* set_int_priority intrinsic function that two arguments are immediate,
480      so check whether auguments are immedite.  */
481 
482   if (!nds32_check_constant_argument (icode, 0, op0, name))
483     return NULL_RTX;
484 
485   if (!nds32_check_constant_argument (icode, 1, op1, name))
486     return NULL_RTX;
487 
488   op0 = nds32_legitimize_argument (icode, 0, op0);
489   op1 = nds32_legitimize_argument (icode, 1, op1);
490 
491   /* Emit and return the new instruction. */
492   pat = GEN_FCN (icode) (op0, op1);
493 
494   if (! pat)
495     return NULL_RTX;
496 
497   emit_insn (pat);
498   return target;
499 }
500 
501 struct builtin_description
502 {
503   const enum insn_code icode;
504   const char *name;
505   enum nds32_builtins code;
506   bool return_p;
507 };
508 
509 #define NDS32_BUILTIN(code, string, builtin) \
510   { CODE_FOR_##code, "__nds32__" string, \
511     NDS32_BUILTIN_##builtin, true },
512 
513 #define NDS32_NO_TARGET_BUILTIN(code, string, builtin) \
514   { CODE_FOR_##code, "__nds32__" string, \
515     NDS32_BUILTIN_##builtin, false },
516 
517 /* Intrinsics that no argument, and that return value.  */
518 static struct builtin_description bdesc_noarg[] =
519 {
520   NDS32_BUILTIN(unspec_fmfcfg, "fmfcfg", FMFCFG)
521   NDS32_BUILTIN(unspec_fmfcsr, "fmfcsr", FMFCSR)
522   NDS32_BUILTIN(unspec_get_current_sp, "get_current_sp", GET_CURRENT_SP)
523   NDS32_BUILTIN(unspec_return_address, "return_address", RETURN_ADDRESS)
524   NDS32_BUILTIN(unspec_get_all_pending_int, "get_all_pending_int",
525 		GET_ALL_PENDING_INT)
526   NDS32_BUILTIN(unspec_unaligned_feature, "unaligned_feature",
527 		UNALIGNED_FEATURE)
528   NDS32_NO_TARGET_BUILTIN(unspec_enable_unaligned, "enable_unaligned",
529 			  ENABLE_UNALIGNED)
530   NDS32_NO_TARGET_BUILTIN(unspec_disable_unaligned, "disable_unaligned",
531 			  DISABLE_UNALIGNED)
532 };
533 
534 /* Intrinsics that take just one argument.  */
535 static struct builtin_description bdesc_1arg[] =
536 {
537   NDS32_BUILTIN(unspec_ssabssi2, "abs", ABS)
538   NDS32_BUILTIN(clzsi2, "clz", CLZ)
539   NDS32_BUILTIN(unspec_clo, "clo", CLO)
540   NDS32_BUILTIN(unspec_wsbh, "wsbh", WSBH)
541   NDS32_BUILTIN(unspec_tlbop_pb, "tlbop_pb",TLBOP_PB)
542   NDS32_BUILTIN(unaligned_load_hw, "unaligned_load_hw", UALOAD_HW)
543   NDS32_BUILTIN(unaligned_loadsi, "unaligned_load_w", UALOAD_W)
544   NDS32_BUILTIN(unaligned_loaddi, "unaligned_load_dw", UALOAD_DW)
545   NDS32_NO_TARGET_BUILTIN(unspec_volatile_isync, "isync", ISYNC)
546   NDS32_NO_TARGET_BUILTIN(unspec_fmtcsr, "fmtcsr", FMTCSR)
547   NDS32_NO_TARGET_BUILTIN(unspec_jr_itoff, "jr_itoff", JR_ITOFF)
548   NDS32_NO_TARGET_BUILTIN(unspec_jr_toff, "jr_toff", JR_TOFF)
549   NDS32_NO_TARGET_BUILTIN(unspec_jral_ton, "jral_ton", JRAL_TON)
550   NDS32_NO_TARGET_BUILTIN(unspec_ret_toff, "ret_toff", RET_TOFF)
551   NDS32_NO_TARGET_BUILTIN(unspec_jral_iton, "jral_iton",JRAL_ITON)
552   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_trd, "tlbop_trd", TLBOP_TRD)
553   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_twr, "tlbop_twr", TLBOP_TWR)
554   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwr, "tlbop_rwr", TLBOP_RWR)
555   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_rwlk, "tlbop_rwlk", TLBOP_RWLK)
556   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_unlk, "tlbop_unlk", TLBOP_UNLK)
557   NDS32_NO_TARGET_BUILTIN(unspec_tlbop_inv, "tlbop_inv", TLBOP_INV)
558   NDS32_NO_TARGET_BUILTIN(unspec_ret_itoff, "ret_itoff", RET_ITOFF)
559   NDS32_NO_TARGET_BUILTIN(unspec_set_current_sp,
560 			  "set_current_sp", SET_CURRENT_SP)
561 };
562 
563 /* Intrinsics that take just one argument. and the argument is immediate.  */
564 static struct builtin_description bdesc_1argimm[] =
565 {
566   NDS32_BUILTIN(unspec_volatile_mfsr, "mfsr", MFSR)
567   NDS32_BUILTIN(unspec_volatile_mfusr, "mfsr", MFUSR)
568   NDS32_BUILTIN(unspec_get_pending_int, "get_pending_int", GET_PENDING_INT)
569   NDS32_BUILTIN(unspec_get_int_priority, "get_int_priority", GET_INT_PRIORITY)
570   NDS32_NO_TARGET_BUILTIN(unspec_trap, "trap", TRAP)
571   NDS32_NO_TARGET_BUILTIN(unspec_break, "break", BREAK)
572   NDS32_NO_TARGET_BUILTIN(unspec_syscall, "syscall", SYSCALL)
573   NDS32_NO_TARGET_BUILTIN(unspec_enable_int, "enable_int", ENABLE_INT)
574   NDS32_NO_TARGET_BUILTIN(unspec_disable_int, "disable_int", DISABLE_INT)
575   NDS32_NO_TARGET_BUILTIN(unspec_clr_pending_hwint, "clr_pending_hwint",
576 			  CLR_PENDING_HWINT)
577   NDS32_NO_TARGET_BUILTIN(unspec_set_trig_level, "set_trig_level",
578 			  SET_TRIG_LEVEL)
579   NDS32_NO_TARGET_BUILTIN(unspec_set_trig_edge, "set_trig_edge",
580 			  SET_TRIG_EDGE)
581   NDS32_BUILTIN(unspec_get_trig_type, "get_trig_type", GET_TRIG_TYPE)
582 };
583 
584 /* Intrinsics that take two arguments.  */
585 static struct builtin_description bdesc_2arg[] =
586 {
587   NDS32_BUILTIN(unspec_fcpynss, "fcpynss", FCPYNSS)
588   NDS32_BUILTIN(unspec_fcpyss, "fcpyss", FCPYSS)
589   NDS32_BUILTIN(unspec_fcpynsd, "fcpynsd", FCPYNSD)
590   NDS32_BUILTIN(unspec_fcpysd, "fcpysd", FCPYSD)
591   NDS32_BUILTIN(unspec_ave, "ave", AVE)
592   NDS32_BUILTIN(unspec_pbsad, "pbsad", PBSAD)
593   NDS32_BUILTIN(unspec_ffb, "ffb", FFB)
594   NDS32_BUILTIN(unspec_ffmism, "ffmsim", FFMISM)
595   NDS32_BUILTIN(unspec_flmism, "flmism", FLMISM)
596   NDS32_BUILTIN(rotrsi3, "rotr", ROTR)
597   NDS32_BUILTIN(unspec_sva, "sva", SVA)
598   NDS32_BUILTIN(unspec_svs, "svs", SVS)
599   NDS32_NO_TARGET_BUILTIN(mtsr_isb, "mtsr_isb", MTSR_ISB)
600   NDS32_NO_TARGET_BUILTIN(mtsr_dsb, "mtsr_dsb", MTSR_DSB)
601   NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtsr, "mtsr", MTSR)
602   NDS32_NO_TARGET_BUILTIN(unspec_volatile_mtusr, "mtusr", MTUSR)
603   NDS32_NO_TARGET_BUILTIN(unaligned_store_hw, "unaligned_store_hw", UASTORE_HW)
604   NDS32_NO_TARGET_BUILTIN(unaligned_storesi, "unaligned_store_hw", UASTORE_W)
605   NDS32_NO_TARGET_BUILTIN(unaligned_storedi, "unaligned_store_hw", UASTORE_DW)
606 
607 };
608 
609 /* Two-argument intrinsics with an immediate second argument.  */
610 static struct builtin_description bdesc_2argimm[] =
611 {
612   NDS32_BUILTIN(unspec_bclr, "bclr", BCLR)
613   NDS32_BUILTIN(unspec_bset, "bset", BSET)
614   NDS32_BUILTIN(unspec_btgl, "btgl", BTGL)
615   NDS32_BUILTIN(unspec_btst, "btst", BTST)
616   NDS32_BUILTIN(unspec_clip, "clip", CLIP)
617   NDS32_BUILTIN(unspec_clips, "clips", CLIPS)
618   NDS32_NO_TARGET_BUILTIN(unspec_teqz, "teqz", TEQZ)
619   NDS32_NO_TARGET_BUILTIN(unspec_tnez, "tnez", TNEZ)
620 };
621 
622 /* Intrinsics that take three arguments.  */
623 static struct builtin_description bdesc_3arg[] =
624 {
625   NDS32_BUILTIN(unspec_pbsada, "pbsada", PBSADA)
626   NDS32_NO_TARGET_BUILTIN(bse, "bse", BSE)
627   NDS32_NO_TARGET_BUILTIN(bsp, "bsp", BSP)
628 };
629 
630 /* Three-argument intrinsics with an immediate third argument.  */
631 static struct builtin_description bdesc_3argimm[] =
632 {
633   NDS32_NO_TARGET_BUILTIN(prefetch_qw, "prefetch_qw", DPREF_QW)
634   NDS32_NO_TARGET_BUILTIN(prefetch_hw, "prefetch_hw", DPREF_HW)
635   NDS32_NO_TARGET_BUILTIN(prefetch_w, "prefetch_w", DPREF_W)
636   NDS32_NO_TARGET_BUILTIN(prefetch_dw, "prefetch_dw", DPREF_DW)
637 };
638 
639 /* Intrinsics that load a value.  */
640 static struct builtin_description bdesc_load[] =
641 {
642   NDS32_BUILTIN(unspec_volatile_llw, "llw", LLW)
643   NDS32_BUILTIN(unspec_lwup, "lwup", LWUP)
644   NDS32_BUILTIN(unspec_lbup, "lbup", LBUP)
645 };
646 
647 /* Intrinsics that store a value.  */
648 static struct builtin_description bdesc_store[] =
649 {
650   NDS32_BUILTIN(unspec_swup, "swup", SWUP)
651   NDS32_BUILTIN(unspec_sbup, "sbup", SBUP)
652 };
653 
654 static struct builtin_description bdesc_cctl[] =
655 {
656   NDS32_BUILTIN(cctl_idx_read, "cctl_idx_read", CCTL_IDX_READ)
657   NDS32_NO_TARGET_BUILTIN(cctl_idx_write, "cctl_idx_write", CCTL_IDX_WRITE)
658   NDS32_NO_TARGET_BUILTIN(cctl_va_lck, "cctl_va_lck", CCTL_VA_LCK)
659   NDS32_NO_TARGET_BUILTIN(cctl_idx_wbinval,
660 			  "cctl_idx_wbinval", CCTL_IDX_WBINVAL)
661   NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_l1,
662 			  "cctl_va_wbinval_l1", CCTL_VA_WBINVAL_L1)
663   NDS32_NO_TARGET_BUILTIN(cctl_va_wbinval_la,
664 			  "cctl_va_wbinval_la", CCTL_VA_WBINVAL_LA)
665 };
666 
667 rtx
nds32_expand_builtin_impl(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)668 nds32_expand_builtin_impl (tree exp,
669 			   rtx target,
670 			   rtx subtarget ATTRIBUTE_UNUSED,
671 			   enum machine_mode mode ATTRIBUTE_UNUSED,
672 			   int ignore ATTRIBUTE_UNUSED)
673 {
674   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
675   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
676   unsigned i;
677   struct builtin_description *d;
678 
679   switch (fcode)
680     {
681     /* FPU Register Transfer.  */
682     case NDS32_BUILTIN_FMFCFG:
683     case NDS32_BUILTIN_FMFCSR:
684     case NDS32_BUILTIN_FMTCSR:
685     case NDS32_BUILTIN_FCPYNSS:
686     case NDS32_BUILTIN_FCPYSS:
687       /* Both v3s and v3f toolchains define TARGET_FPU_SINGLE.  */
688       if (!TARGET_FPU_SINGLE)
689 	{
690 	  error ("this builtin function is only available "
691 		 "on the v3s or v3f toolchain");
692 	  return NULL_RTX;
693 	}
694       break;
695 
696     /* FPU Register Transfer.  */
697     case NDS32_BUILTIN_FCPYNSD:
698     case NDS32_BUILTIN_FCPYSD:
699       /* Only v3f toolchain defines TARGET_FPU_DOUBLE.  */
700       if (!TARGET_FPU_DOUBLE)
701 	{
702 	  error ("this builtin function is only available "
703 		 "on the v3f toolchain");
704 	  return NULL_RTX;
705 	}
706       break;
707 
708     /* Load and Store  */
709     case NDS32_BUILTIN_LLW:
710     case NDS32_BUILTIN_LWUP:
711     case NDS32_BUILTIN_LBUP:
712     case NDS32_BUILTIN_SCW:
713     case NDS32_BUILTIN_SWUP:
714     case NDS32_BUILTIN_SBUP:
715       if (TARGET_ISA_V3M)
716 	{
717 	  error ("this builtin function not support "
718 		 "on the v3m toolchain");
719 	  return NULL_RTX;
720 	}
721       break;
722 
723     /* Performance Extension  */
724     case NDS32_BUILTIN_ABS:
725     case NDS32_BUILTIN_AVE:
726     case NDS32_BUILTIN_BCLR:
727     case NDS32_BUILTIN_BSET:
728     case NDS32_BUILTIN_BTGL:
729     case NDS32_BUILTIN_BTST:
730     case NDS32_BUILTIN_CLIP:
731     case NDS32_BUILTIN_CLIPS:
732     case NDS32_BUILTIN_CLZ:
733     case NDS32_BUILTIN_CLO:
734       if (!TARGET_EXT_PERF)
735 	{
736 	  error ("don't support performance extension instructions");
737 	  return NULL_RTX;
738 	}
739       break;
740 
741     /* Performance Extension 2  */
742     case NDS32_BUILTIN_PBSAD:
743     case NDS32_BUILTIN_PBSADA:
744     case NDS32_BUILTIN_BSE:
745     case NDS32_BUILTIN_BSP:
746       if (!TARGET_EXT_PERF2)
747 	{
748 	  error ("don't support performance extension "
749 		 "version 2 instructions");
750 	  return NULL_RTX;
751 	}
752       break;
753 
754     /* String Extension  */
755     case NDS32_BUILTIN_FFB:
756     case NDS32_BUILTIN_FFMISM:
757     case NDS32_BUILTIN_FLMISM:
758       if (!TARGET_EXT_STRING)
759 	{
760 	  error ("don't support string extension instructions");
761 	  return NULL_RTX;
762 	}
763       break;
764 
765     default:
766       break;
767     }
768 
769   /* Since there are no result and operands, we can simply emit this rtx.  */
770   switch (fcode)
771     {
772     case NDS32_BUILTIN_ISB:
773       emit_insn (gen_unspec_volatile_isb ());
774       return target;
775     case NDS32_BUILTIN_DSB:
776       emit_insn (gen_unspec_dsb ());
777       return target;
778     case NDS32_BUILTIN_MSYNC_ALL:
779       emit_insn (gen_unspec_msync_all ());
780       return target;
781     case NDS32_BUILTIN_MSYNC_STORE:
782       emit_insn (gen_unspec_msync_store ());
783       return target;
784     case NDS32_BUILTIN_SETGIE_EN:
785       emit_insn (gen_unspec_volatile_setgie_en ());
786       emit_insn (gen_unspec_dsb ());
787       return target;
788     case NDS32_BUILTIN_SETGIE_DIS:
789       emit_insn (gen_unspec_volatile_setgie_dis ());
790       emit_insn (gen_unspec_dsb ());
791       return target;
792     case NDS32_BUILTIN_GIE_DIS:
793       emit_insn (gen_unspec_volatile_setgie_dis ());
794       emit_insn (gen_unspec_dsb ());
795       return target;
796     case NDS32_BUILTIN_GIE_EN:
797       emit_insn (gen_unspec_volatile_setgie_en ());
798       emit_insn (gen_unspec_dsb ());
799       return target;
800     case NDS32_BUILTIN_SET_PENDING_SWINT:
801       emit_insn (gen_unspec_set_pending_swint ());
802       return target;
803     case NDS32_BUILTIN_CLR_PENDING_SWINT:
804       emit_insn (gen_unspec_clr_pending_swint ());
805       return target;
806     case NDS32_BUILTIN_CCTL_L1D_INVALALL:
807       emit_insn (gen_cctl_l1d_invalall());
808       return target;
809     case NDS32_BUILTIN_CCTL_L1D_WBALL_ALVL:
810       emit_insn (gen_cctl_l1d_wball_alvl());
811       return target;
812     case NDS32_BUILTIN_CCTL_L1D_WBALL_ONE_LVL:
813       emit_insn (gen_cctl_l1d_wball_one_lvl());
814       return target;
815     case NDS32_BUILTIN_STANDBY_NO_WAKE_GRANT:
816       emit_insn (gen_unspec_standby_no_wake_grant ());
817       return target;
818     case NDS32_BUILTIN_STANDBY_WAKE_GRANT:
819       emit_insn (gen_unspec_standby_wake_grant ());
820       return target;
821     case NDS32_BUILTIN_STANDBY_WAKE_DONE:
822       emit_insn (gen_unspec_standby_wait_done ());
823       return target;
824     case NDS32_BUILTIN_SETEND_BIG:
825       emit_insn (gen_unspec_setend_big ());
826       return target;
827     case NDS32_BUILTIN_SETEND_LITTLE:
828       emit_insn (gen_unspec_setend_little ());
829       return target;
830     case NDS32_BUILTIN_NOP:
831       emit_insn (gen_unspec_nop ());
832       return target;
833     case NDS32_BUILTIN_SCHE_BARRIER:
834       emit_insn (gen_blockage ());
835       return target;
836     case NDS32_BUILTIN_TLBOP_FLUA:
837       emit_insn (gen_unspec_tlbop_flua ());
838       return target;
839     case NDS32_BUILTIN_SCW:
840       return nds32_expand_scw_builtin (CODE_FOR_unspec_volatile_scw,
841 				       exp, target);
842     case NDS32_BUILTIN_SET_INT_PRIORITY:
843       return nds32_expand_priority_builtin (CODE_FOR_unspec_set_int_priority,
844 					    exp, target,
845 					    "__nds32__set_int_priority");
846       return target;
847     default:
848       break;
849     }
850 
851   /* Expand groups of builtins.  */
852   for (i = 0, d = bdesc_noarg; i < ARRAY_SIZE (bdesc_noarg); i++, d++)
853     if (d->code == fcode)
854       return nds32_expand_noarg_builtin (d->icode, target);
855 
856   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
857     if (d->code == fcode)
858       return nds32_expand_unop_builtin (d->icode, exp, target, d->return_p);
859 
860   for (i = 0, d = bdesc_1argimm; i < ARRAY_SIZE (bdesc_1argimm); i++, d++)
861     if (d->code == fcode)
862       return nds32_expand_unopimm_builtin (d->icode, exp, target,
863 					   d->return_p, d->name);
864 
865   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
866     if (d->code == fcode)
867       return nds32_expand_binop_builtin (d->icode, exp, target, d->return_p);
868 
869   for (i = 0, d = bdesc_2argimm; i < ARRAY_SIZE (bdesc_2argimm); i++, d++)
870     if (d->code == fcode)
871       return nds32_expand_binopimm_builtin (d->icode, exp, target,
872 					    d->return_p, d->name);
873 
874   for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
875     if (d->code == fcode)
876       return nds32_expand_triop_builtin (d->icode, exp, target, d->return_p);
877 
878   for (i = 0, d = bdesc_3argimm; i < ARRAY_SIZE (bdesc_3argimm); i++, d++)
879     if (d->code == fcode)
880       return nds32_expand_triopimm_builtin (d->icode, exp, target,
881 					    d->return_p, d->name);
882 
883   for (i = 0, d = bdesc_load; i < ARRAY_SIZE (bdesc_load); i++, d++)
884     if (d->code == fcode)
885       return nds32_expand_builtin_load (d->icode, exp, target);
886 
887   for (i = 0, d = bdesc_store; i < ARRAY_SIZE (bdesc_store); i++, d++)
888     if (d->code == fcode)
889       return nds32_expand_builtin_store (d->icode, exp, target);
890 
891   for (i = 0, d = bdesc_cctl; i < ARRAY_SIZE (bdesc_cctl); i++, d++)
892     if (d->code == fcode)
893       return nds32_expand_cctl_builtin (d->icode, exp, target,
894 					d->return_p, d->name);
895 
896   return NULL_RTX;
897 }
898 
899 static GTY(()) tree nds32_builtin_decls[NDS32_BUILTIN_COUNT];
900 
901 /* Return the NDS32 builtin for CODE.  */
902 tree
nds32_builtin_decl_impl(unsigned code,bool initialize_p ATTRIBUTE_UNUSED)903 nds32_builtin_decl_impl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
904 {
905   if (code >= NDS32_BUILTIN_COUNT)
906     return error_mark_node;
907 
908   return nds32_builtin_decls[code];
909 }
910 
911 void
nds32_init_builtins_impl(void)912 nds32_init_builtins_impl (void)
913 {
914 #define ADD_NDS32_BUILTIN0(NAME, RET_TYPE, CODE)		\
915   nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] =			\
916   add_builtin_function ("__builtin_nds32_" NAME,		\
917 			build_function_type_list (RET_TYPE##_type_node, \
918 						  NULL_TREE),		\
919 			NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
920 
921 #define ADD_NDS32_BUILTIN1(NAME, RET_TYPE, ARG_TYPE, CODE)	\
922   nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] =			\
923   add_builtin_function ("__builtin_nds32_" NAME,		\
924 			build_function_type_list (RET_TYPE##_type_node, \
925 						  ARG_TYPE##_type_node, \
926 						  NULL_TREE),		\
927 			NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
928 
929 #define ADD_NDS32_BUILTIN2(NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2, CODE)	\
930   nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] =				\
931   add_builtin_function ("__builtin_nds32_" NAME,			\
932 			build_function_type_list (RET_TYPE##_type_node, \
933 						  ARG_TYPE1##_type_node,\
934 						  ARG_TYPE2##_type_node,\
935 						  NULL_TREE),		\
936 			NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
937 
938 #define ADD_NDS32_BUILTIN3(NAME, RET_TYPE,				\
939 			   ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, CODE)	\
940   nds32_builtin_decls[NDS32_BUILTIN_ ## CODE] =				\
941   add_builtin_function ("__builtin_nds32_" NAME,			\
942 			build_function_type_list (RET_TYPE##_type_node,	\
943 						  ARG_TYPE1##_type_node,\
944 						  ARG_TYPE2##_type_node,\
945 						  ARG_TYPE3##_type_node,\
946 						  NULL_TREE),		\
947 			NDS32_BUILTIN_ ## CODE, BUILT_IN_MD, NULL, NULL_TREE)
948 
949   /* Looking for return type and argument can be found in tree.h file.  */
950   tree ptr_uchar_type_node = build_pointer_type (unsigned_char_type_node);
951   tree ptr_ushort_type_node = build_pointer_type (short_unsigned_type_node);
952   tree ptr_uint_type_node = build_pointer_type (unsigned_type_node);
953   tree ptr_ulong_type_node = build_pointer_type (long_long_unsigned_type_node);
954 
955   /* Cache.  */
956   ADD_NDS32_BUILTIN1 ("isync", void, ptr_uint, ISYNC);
957   ADD_NDS32_BUILTIN0 ("isb", void, ISB);
958   ADD_NDS32_BUILTIN0 ("dsb", void, DSB);
959   ADD_NDS32_BUILTIN0 ("msync_all", void, MSYNC_ALL);
960   ADD_NDS32_BUILTIN0 ("msync_store", void, MSYNC_STORE);
961 
962   /* Register Transfer.  */
963   ADD_NDS32_BUILTIN1 ("mfsr", unsigned, integer, MFSR);
964   ADD_NDS32_BUILTIN1 ("mfusr", unsigned, integer, MFUSR);
965   ADD_NDS32_BUILTIN2 ("mtsr", void, unsigned, integer, MTSR);
966   ADD_NDS32_BUILTIN2 ("mtsr_isb", void, unsigned, integer, MTSR_ISB);
967   ADD_NDS32_BUILTIN2 ("mtsr_dsb", void, unsigned, integer, MTSR_DSB);
968   ADD_NDS32_BUILTIN2 ("mtusr", void, unsigned, integer, MTUSR);
969 
970   /* FPU Register Transfer.  */
971   ADD_NDS32_BUILTIN0 ("fmfcsr", unsigned, FMFCSR);
972   ADD_NDS32_BUILTIN1 ("fmtcsr", void, unsigned, FMTCSR);
973   ADD_NDS32_BUILTIN0 ("fmfcfg", unsigned, FMFCFG);
974   ADD_NDS32_BUILTIN2 ("fcpyss", float, float, float, FCPYSS);
975   ADD_NDS32_BUILTIN2 ("fcpynss", float, float, float, FCPYNSS);
976   ADD_NDS32_BUILTIN2 ("fcpysd", double, double, double, FCPYSD);
977   ADD_NDS32_BUILTIN2 ("fcpynsd", double, double, double, FCPYNSD);
978 
979   /* Interrupt.  */
980   ADD_NDS32_BUILTIN0 ("setgie_en", void, SETGIE_EN);
981   ADD_NDS32_BUILTIN0 ("setgie_dis", void, SETGIE_DIS);
982   ADD_NDS32_BUILTIN0 ("gie_en", void, GIE_EN);
983   ADD_NDS32_BUILTIN0 ("gie_dis", void, GIE_DIS);
984   ADD_NDS32_BUILTIN1 ("enable_int", void, integer, ENABLE_INT);
985   ADD_NDS32_BUILTIN1 ("disable_int", void, integer, DISABLE_INT);
986   ADD_NDS32_BUILTIN0 ("set_pending_swint", void, SET_PENDING_SWINT);
987   ADD_NDS32_BUILTIN0 ("clr_pending_swint", void, CLR_PENDING_SWINT);
988   ADD_NDS32_BUILTIN0 ("get_all_pending_int", unsigned, GET_ALL_PENDING_INT);
989   ADD_NDS32_BUILTIN1 ("get_pending_int", unsigned, integer, GET_PENDING_INT);
990   ADD_NDS32_BUILTIN1 ("get_int_priority", unsigned, integer, GET_INT_PRIORITY);
991   ADD_NDS32_BUILTIN2 ("set_int_priority", void, integer, integer,
992 		      SET_INT_PRIORITY);
993   ADD_NDS32_BUILTIN1 ("clr_pending_hwint", void, integer, CLR_PENDING_HWINT);
994   ADD_NDS32_BUILTIN1 ("set_trig_level", void, integer, SET_TRIG_LEVEL);
995   ADD_NDS32_BUILTIN1 ("set_trig_edge", void, integer, SET_TRIG_EDGE);
996   ADD_NDS32_BUILTIN1 ("get_trig_type", unsigned, integer, GET_TRIG_TYPE);
997 
998   /* Load and Store  */
999   ADD_NDS32_BUILTIN1 ("llw", unsigned, ptr_uint, LLW);
1000   ADD_NDS32_BUILTIN1 ("lwup", unsigned, ptr_uint, LWUP);
1001   ADD_NDS32_BUILTIN1 ("lbup", char, ptr_uchar, LBUP);
1002   ADD_NDS32_BUILTIN2 ("scw", unsigned, ptr_uint, unsigned, SCW);
1003   ADD_NDS32_BUILTIN2 ("swup", void, ptr_uint, unsigned, SWUP);
1004   ADD_NDS32_BUILTIN2 ("sbup", void, ptr_uchar, char, SBUP);
1005 
1006   /* CCTL  */
1007   ADD_NDS32_BUILTIN0 ("cctl_l1d_invalall", void, CCTL_L1D_INVALALL);
1008   ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_alvl", void, CCTL_L1D_WBALL_ALVL);
1009   ADD_NDS32_BUILTIN0 ("cctl_l1d_wball_one_lvl", void, CCTL_L1D_WBALL_ONE_LVL);
1010   ADD_NDS32_BUILTIN2 ("cctl_va_lck", void, integer, ptr_uint, CCTL_VA_LCK);
1011   ADD_NDS32_BUILTIN2 ("cctl_idx_wbinval", void, integer, unsigned,
1012 		      CCTL_IDX_WBINVAL);
1013   ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_l1", void, integer, ptr_uint,
1014 		      CCTL_VA_WBINVAL_L1);
1015   ADD_NDS32_BUILTIN2 ("cctl_va_wbinval_la", void, integer, ptr_uint,
1016 		      CCTL_VA_WBINVAL_LA);
1017   ADD_NDS32_BUILTIN2 ("cctl_idx_read", unsigned, integer, unsigned,
1018 		      CCTL_IDX_READ);
1019   ADD_NDS32_BUILTIN3 ("cctl_idx_write", void, integer, unsigned, unsigned,
1020 		      CCTL_IDX_WRITE);
1021 
1022   /* PREFETCH  */
1023   ADD_NDS32_BUILTIN3 ("dpref_qw", void, ptr_uchar, unsigned, integer, DPREF_QW);
1024   ADD_NDS32_BUILTIN3 ("dpref_hw", void, ptr_ushort, unsigned, integer,
1025 		      DPREF_HW);
1026   ADD_NDS32_BUILTIN3 ("dpref_w", void, ptr_uint, unsigned, integer, DPREF_W);
1027   ADD_NDS32_BUILTIN3 ("dpref_dw", void, ptr_ulong, unsigned, integer, DPREF_DW);
1028 
1029   /* Performance Extension  */
1030   ADD_NDS32_BUILTIN1 ("pe_abs", integer, integer, ABS);
1031   ADD_NDS32_BUILTIN2 ("pe_ave", integer, integer, integer, AVE);
1032   ADD_NDS32_BUILTIN2 ("pe_bclr", unsigned, unsigned, unsigned, BCLR);
1033   ADD_NDS32_BUILTIN2 ("pe_bset", unsigned, unsigned, unsigned, BSET);
1034   ADD_NDS32_BUILTIN2 ("pe_btgl", unsigned, unsigned, unsigned, BTGL);
1035   ADD_NDS32_BUILTIN2 ("pe_btst", unsigned, unsigned, unsigned, BTST);
1036   ADD_NDS32_BUILTIN2 ("pe_clip", unsigned, integer, unsigned, CLIP);
1037   ADD_NDS32_BUILTIN2 ("pe_clips", integer, integer, unsigned, CLIPS);
1038   ADD_NDS32_BUILTIN1 ("pe_clz", unsigned, unsigned, CLZ);
1039   ADD_NDS32_BUILTIN1 ("pe_clo", unsigned, unsigned, CLO);
1040 
1041   /* Performance Extension 2  */
1042   ADD_NDS32_BUILTIN3 ("pe2_bse", void, ptr_uint, unsigned, ptr_uint, BSE);
1043   ADD_NDS32_BUILTIN3 ("pe2_bsp", void, ptr_uint, unsigned, ptr_uint, BSP);
1044   ADD_NDS32_BUILTIN2 ("pe2_pbsad", unsigned, unsigned, unsigned, PBSAD);
1045   ADD_NDS32_BUILTIN3 ("pe2_pbsada", unsigned, unsigned, unsigned, unsigned,
1046 		      PBSADA);
1047 
1048   /* String Extension  */
1049   ADD_NDS32_BUILTIN2 ("se_ffb", integer, unsigned, unsigned, FFB);
1050   ADD_NDS32_BUILTIN2 ("se_ffmism", integer, unsigned, unsigned, FFMISM);
1051   ADD_NDS32_BUILTIN2 ("se_flmism", integer, unsigned, unsigned, FLMISM);
1052 
1053 
1054   /* ROTR  */
1055   ADD_NDS32_BUILTIN2 ("rotr", unsigned, unsigned, unsigned, ROTR);
1056 
1057   /* Swap  */
1058   ADD_NDS32_BUILTIN1 ("wsbh", unsigned, unsigned, WSBH);
1059 
1060   /* System  */
1061   ADD_NDS32_BUILTIN2 ("svs", unsigned, integer, integer, SVS);
1062   ADD_NDS32_BUILTIN2 ("sva", unsigned, integer, integer, SVA);
1063   ADD_NDS32_BUILTIN1 ("jr_itoff", void, unsigned, JR_ITOFF);
1064   ADD_NDS32_BUILTIN1 ("jr_toff", void, unsigned, JR_TOFF);
1065   ADD_NDS32_BUILTIN1 ("jral_iton", void, unsigned, JRAL_ITON);
1066   ADD_NDS32_BUILTIN1 ("jral_ton", void, unsigned, JRAL_TON);
1067   ADD_NDS32_BUILTIN1 ("ret_itoff", void, unsigned, RET_ITOFF);
1068   ADD_NDS32_BUILTIN1 ("ret_toff", void, unsigned, RET_TOFF);
1069   ADD_NDS32_BUILTIN0 ("standby_no_wake_grant", void, STANDBY_NO_WAKE_GRANT);
1070   ADD_NDS32_BUILTIN0 ("standby_wake_grant", void, STANDBY_WAKE_GRANT);
1071   ADD_NDS32_BUILTIN0 ("standby_wait_done", void, STANDBY_WAKE_DONE);
1072   ADD_NDS32_BUILTIN1 ("break", void, unsigned, BREAK);
1073   ADD_NDS32_BUILTIN1 ("syscall", void, unsigned, SYSCALL);
1074   ADD_NDS32_BUILTIN0 ("nop", void, NOP);
1075   ADD_NDS32_BUILTIN0 ("get_current_sp", unsigned, GET_CURRENT_SP);
1076   ADD_NDS32_BUILTIN1 ("set_current_sp", void, unsigned, SET_CURRENT_SP);
1077   ADD_NDS32_BUILTIN2 ("teqz", void, unsigned, unsigned, TEQZ);
1078   ADD_NDS32_BUILTIN2 ("tnez", void, unsigned, unsigned, TNEZ);
1079   ADD_NDS32_BUILTIN1 ("trap", void, unsigned, TRAP);
1080   ADD_NDS32_BUILTIN0 ("return_address", unsigned, RETURN_ADDRESS);
1081   ADD_NDS32_BUILTIN0 ("setend_big", void, SETEND_BIG);
1082   ADD_NDS32_BUILTIN0 ("setend_little", void, SETEND_LITTLE);
1083 
1084   /* Schedule Barrier */
1085   ADD_NDS32_BUILTIN0 ("schedule_barrier", void, SCHE_BARRIER);
1086 
1087   /* TLBOP  */
1088   ADD_NDS32_BUILTIN1 ("tlbop_trd", void, unsigned, TLBOP_TRD);
1089   ADD_NDS32_BUILTIN1 ("tlbop_twr", void, unsigned, TLBOP_TWR);
1090   ADD_NDS32_BUILTIN1 ("tlbop_rwr", void, unsigned, TLBOP_RWR);
1091   ADD_NDS32_BUILTIN1 ("tlbop_rwlk", void, unsigned, TLBOP_RWLK);
1092   ADD_NDS32_BUILTIN1 ("tlbop_unlk", void, unsigned, TLBOP_UNLK);
1093   ADD_NDS32_BUILTIN1 ("tlbop_pb", unsigned, unsigned, TLBOP_PB);
1094   ADD_NDS32_BUILTIN1 ("tlbop_inv", void, unsigned, TLBOP_INV);
1095   ADD_NDS32_BUILTIN0 ("tlbop_flua", void, TLBOP_FLUA);
1096 
1097   /* Unaligned Load/Store  */
1098   ADD_NDS32_BUILTIN1 ("unaligned_load_hw", short_unsigned, ptr_ushort,
1099 		      UALOAD_HW);
1100   ADD_NDS32_BUILTIN1 ("unaligned_load_w", unsigned, ptr_uint, UALOAD_W);
1101   ADD_NDS32_BUILTIN1 ("unaligned_load_dw", long_long_unsigned, ptr_ulong,
1102 		      UALOAD_DW);
1103   ADD_NDS32_BUILTIN2 ("unaligned_store_hw", void, ptr_ushort, short_unsigned,
1104 		      UASTORE_HW);
1105   ADD_NDS32_BUILTIN2 ("unaligned_store_w", void, ptr_uint, unsigned, UASTORE_W);
1106   ADD_NDS32_BUILTIN2 ("unaligned_store_dw", void, ptr_ulong, long_long_unsigned,
1107 		      UASTORE_DW);
1108   ADD_NDS32_BUILTIN0 ("unaligned_feature", unsigned, UNALIGNED_FEATURE);
1109   ADD_NDS32_BUILTIN0 ("enable_unaligned", void, ENABLE_UNALIGNED);
1110   ADD_NDS32_BUILTIN0 ("disable_unaligned", void, DISABLE_UNALIGNED);
1111 
1112 }
1113