nds32-intrinsic.c revision 1.4
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.  */
47static rtx
48nds32_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.  */
56static rtx
57nds32_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.  */
73static rtx
74nds32_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.  */
120static int
121nds32_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.  */
139static rtx
140nds32_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.  */
156static rtx
157nds32_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.  */
183static rtx
184nds32_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.  */
213static rtx
214nds32_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.  */
243static rtx
244nds32_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.  */
276static rtx
277nds32_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.  */
309static rtx
310nds32_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.  */
345static rtx
346nds32_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.  */
372static rtx
373nds32_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.  */
400static rtx
401nds32_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.  */
441static rtx
442nds32_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. */
471static rtx
472nds32_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
501struct 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.  */
518static 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.  */
535static 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.  */
564static 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.  */
585static 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.  */
610static 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.  */
623static 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.  */
631static 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.  */
640static 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.  */
648static struct builtin_description bdesc_store[] =
649{
650  NDS32_BUILTIN(unspec_swup, "swup", SWUP)
651  NDS32_BUILTIN(unspec_sbup, "sbup", SBUP)
652};
653
654static 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
667rtx
668nds32_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
899static GTY(()) tree nds32_builtin_decls[NDS32_BUILTIN_COUNT];
900
901/* Return the NDS32 builtin for CODE.  */
902tree
903nds32_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
911void
912nds32_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