OSDN Git Service

Add ports for TILE-Gx and TILEPro.
[pf3gnuchains/gcc-fork.git] / gcc / config / tilegx / tilegx.c
1 /* Subroutines used for code generation on the Tilera TILE-Gx.
2    Copyright (C) 2011, 2012
3    Free Software Foundation, Inc.
4    Contributed by Walter Lee (walt@tilera.com)
5
6    This file is part of GCC.
7
8    GCC is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published
10    by the Free Software Foundation; either version 3, or (at your
11    option) any later version.
12
13    GCC is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING3.  If not see
20    <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "insn-config.h"
29 #include "output.h"
30 #include "insn-attr.h"
31 #include "recog.h"
32 #include "expr.h"
33 #include "langhooks.h"
34 #include "optabs.h"
35 #include "sched-int.h"
36 #include "tm_p.h"
37 #include "tm-constrs.h"
38 #include "target.h"
39 #include "target-def.h"
40 #include "integrate.h"
41 #include "dwarf2.h"
42 #include "timevar.h"
43 #include "gimple.h"
44 #include "cfgloop.h"
45 #include "tilegx-builtins.h"
46 #include "tilegx-multiply.h"
47 #include "diagnostic.h"
48
49 /* SYMBOL_REF for GOT */
50 static GTY(()) rtx g_got_symbol = NULL;
51
52 /* In case of a POST_INC or POST_DEC memory reference, we must report
53    the mode of the memory reference from TARGET_PRINT_OPERAND to
54    TARGET_PRINT_OPERAND_ADDRESS.  */
55 static enum machine_mode output_memory_reference_mode;
56
57 /* Report whether we're printing out the first address fragment of a
58    POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
59    TARGET_PRINT_OPERAND_ADDRESS.  */
60 static bool output_memory_autoinc_first;
61
62 \f
63
64 /* Option handling  */
65
66 /* Implement TARGET_OPTION_OVERRIDE.  */
67 static void
68 tilegx_option_override (void)
69 {
70   /* When modulo scheduling is enabled, we still rely on regular
71      scheduler for bundling.  */
72   if (flag_modulo_sched)
73     flag_resched_modulo_sched = 1;
74 }
75 \f
76
77
78 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
79 static bool
80 tilegx_scalar_mode_supported_p (enum machine_mode mode)
81 {
82   switch (mode)
83     {
84     case QImode:
85     case HImode:
86     case SImode:
87     case DImode:
88     case TImode:
89       return true;
90
91     case SFmode:
92     case DFmode:
93       return true;
94
95     default:
96       return false;
97     }
98 }
99
100
101 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P.  */
102 static bool
103 tilegx_vector_mode_supported_p (enum machine_mode mode)
104 {
105   return mode == V8QImode || mode == V4HImode || mode == V2SImode;
106 }
107
108
109 /* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
110 static bool
111 tilegx_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
112                                rtx x ATTRIBUTE_UNUSED)
113 {
114   return true;
115 }
116
117
118 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
119 static bool
120 tilegx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
121 {
122   return decl != NULL;
123 }
124
125
126 /* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
127    passed by reference.  */
128 static bool
129 tilegx_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
130                           enum machine_mode mode ATTRIBUTE_UNUSED,
131                           const_tree type, bool named ATTRIBUTE_UNUSED)
132 {
133   return (type && TYPE_SIZE (type)
134           && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST);
135 }
136
137
138 /* Implement TARGET_RETURN_IN_MEMORY.  */
139 static bool
140 tilegx_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
141 {
142   return !IN_RANGE (int_size_in_bytes (type),
143                     0, TILEGX_NUM_RETURN_REGS * UNITS_PER_WORD);
144 }
145
146
147 /* TARGET_MODE_REP_EXTENDED.  */
148 static int
149 tilegx_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep)
150 {
151   /* SImode register values are sign-extended to DImode.  */
152   if (mode == SImode && mode_rep == DImode)
153     return SIGN_EXTEND;
154
155   return UNKNOWN;
156 }
157
158
159 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
160 static unsigned int
161 tilegx_function_arg_boundary (enum machine_mode mode, const_tree type)
162 {
163   unsigned int alignment;
164
165   alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
166   if (alignment < PARM_BOUNDARY)
167     alignment = PARM_BOUNDARY;
168   if (alignment > STACK_BOUNDARY)
169     alignment = STACK_BOUNDARY;
170   return alignment;
171 }
172
173
174 /* Implement TARGET_FUNCTION_ARG.  */
175 static rtx
176 tilegx_function_arg (cumulative_args_t cum_v,
177                      enum machine_mode mode,
178                      const_tree type, bool named ATTRIBUTE_UNUSED)
179 {
180   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
181   int byte_size = ((mode == BLKmode)
182                    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
183
184   if (cum >= TILEGX_NUM_ARG_REGS)
185     return NULL_RTX;
186
187   /* The ABI does not allow parameters to be passed partially in reg
188      and partially in stack.  */
189   if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
190       > TILEGX_NUM_ARG_REGS)
191     return NULL_RTX;
192
193   return gen_rtx_REG (mode, cum);
194 }
195
196
197 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
198 static void
199 tilegx_function_arg_advance (cumulative_args_t cum_v,
200                              enum machine_mode mode,
201                              const_tree type, bool named ATTRIBUTE_UNUSED)
202 {
203   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
204
205   int byte_size = ((mode == BLKmode)
206                    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
207   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
208
209   /* If the current argument does not fit in the pretend_args space,
210      skip over it.  */
211   if (*cum < TILEGX_NUM_ARG_REGS
212       && *cum + word_size > TILEGX_NUM_ARG_REGS)
213     *cum = TILEGX_NUM_ARG_REGS;
214
215   *cum += word_size;
216 }
217
218
219 /* Implement TARGET_FUNCTION_VALUE.  */
220 static rtx
221 tilegx_function_value (const_tree valtype, const_tree fn_decl_or_type,
222                        bool outgoing ATTRIBUTE_UNUSED)
223 {
224   enum machine_mode mode;
225   int unsigned_p;
226
227   mode = TYPE_MODE (valtype);
228   unsigned_p = TYPE_UNSIGNED (valtype);
229
230   mode = promote_function_mode (valtype, mode, &unsigned_p,
231                                 fn_decl_or_type, 1);
232
233   return gen_rtx_REG (mode, 0);
234 }
235
236
237 /* Implement TARGET_LIBCALL_VALUE.  */
238 static rtx
239 tilegx_libcall_value (enum machine_mode mode,
240                        const_rtx fun ATTRIBUTE_UNUSED)
241 {
242   return gen_rtx_REG (mode, 0);
243 }
244
245
246 /* Implement FUNCTION_VALUE_REGNO_P.  */
247 static bool
248 tilegx_function_value_regno_p (const unsigned int regno)
249 {
250   return regno < TILEGX_NUM_RETURN_REGS;
251 }
252
253
254 /* Implement TARGET_BUILD_BUILTIN_VA_LIST.  */
255 static tree
256 tilegx_build_builtin_va_list (void)
257 {
258   tree f_args, f_skip, record, type_decl;
259   bool owp;
260
261   record = lang_hooks.types.make_type (RECORD_TYPE);
262
263   type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
264                           get_identifier ("__va_list_tag"), record);
265
266   f_args = build_decl (BUILTINS_LOCATION, FIELD_DECL,
267                        get_identifier ("__args"), ptr_type_node);
268   f_skip = build_decl (BUILTINS_LOCATION, FIELD_DECL,
269                        get_identifier ("__skip"), ptr_type_node);
270
271   DECL_FIELD_CONTEXT (f_args) = record;
272
273   DECL_FIELD_CONTEXT (f_skip) = record;
274
275   TREE_CHAIN (record) = type_decl;
276   TYPE_NAME (record) = type_decl;
277   TYPE_FIELDS (record) = f_args;
278   TREE_CHAIN (f_args) = f_skip;
279
280   /* We know this is being padded and we want it too.  It is an
281      internal type so hide the warnings from the user.  */
282   owp = warn_padded;
283   warn_padded = false;
284
285   layout_type (record);
286
287   warn_padded = owp;
288
289   /* The correct type is an array type of one element.  */
290   return record;
291 }
292
293
294 /* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
295 static void
296 tilegx_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
297 {
298   tree f_args, f_skip;
299   tree args, skip, t;
300
301   f_args = TYPE_FIELDS (TREE_TYPE (valist));
302   f_skip = TREE_CHAIN (f_args);
303
304   args =
305     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
306   skip =
307     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
308
309   /* Find the __args area.  */
310   t = make_tree (TREE_TYPE (args), virtual_incoming_args_rtx);
311   t = fold_build_pointer_plus_hwi (t,
312                                    UNITS_PER_WORD *
313                                    (crtl->args.info - TILEGX_NUM_ARG_REGS));
314
315   if (crtl->args.pretend_args_size > 0)
316     t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
317
318   t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
319   TREE_SIDE_EFFECTS (t) = 1;
320   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
321
322   /* Find the __skip area.  */
323   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
324   t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
325   t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
326   TREE_SIDE_EFFECTS (t) = 1;
327   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
328 }
329
330
331 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
332 static void
333 tilegx_setup_incoming_varargs (cumulative_args_t cum,
334                                enum machine_mode mode,
335                                tree type, int *pretend_args, int no_rtl)
336 {
337   CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
338   int first_reg;
339
340   /* The caller has advanced CUM up to, but not beyond, the last named
341      argument.  Advance a local copy of CUM past the last "real" named
342      argument, to find out how many registers are left over.  */
343   targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
344                                       mode, type, true);
345   first_reg = local_cum;
346
347   if (local_cum < TILEGX_NUM_ARG_REGS)
348     {
349       *pretend_args = UNITS_PER_WORD * (TILEGX_NUM_ARG_REGS - first_reg);
350
351       if (!no_rtl)
352         {
353           alias_set_type set = get_varargs_alias_set ();
354           rtx tmp =
355             gen_rtx_MEM (BLKmode, plus_constant (virtual_incoming_args_rtx,
356                                                  -STACK_POINTER_OFFSET -
357                                                  UNITS_PER_WORD *
358                                                  (TILEGX_NUM_ARG_REGS -
359                                                   first_reg)));
360           MEM_NOTRAP_P (tmp) = 1;
361           set_mem_alias_set (tmp, set);
362           move_block_from_reg (first_reg, tmp,
363                                TILEGX_NUM_ARG_REGS - first_reg);
364         }
365     }
366   else
367     *pretend_args = 0;
368 }
369
370
371 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  Gimplify va_arg by updating
372    the va_list structure VALIST as required to retrieve an argument of
373    type TYPE, and returning that argument.
374    
375    ret = va_arg(VALIST, TYPE);
376
377    generates code equivalent to:
378   
379     paddedsize = (sizeof(TYPE) + 3) & -4;
380     if (  (VALIST.__args + paddedsize > VALIST.__skip)
381         & (VALIST.__args <= VALIST.__skip))
382       addr = VALIST.__skip + STACK_POINTER_OFFSET;
383     else
384       addr = VALIST.__args;
385     VALIST.__args = addr + paddedsize;
386     ret = *(TYPE *)addr;
387  */
388 static tree
389 tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
390                              gimple_seq *post_p ATTRIBUTE_UNUSED)
391 {
392   tree f_args, f_skip;
393   tree args, skip;
394   HOST_WIDE_INT size, rsize;
395   tree addr, tmp;
396   bool pass_by_reference_p;
397
398   f_args = TYPE_FIELDS (va_list_type_node);
399   f_skip = TREE_CHAIN (f_args);
400
401   args =
402     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
403   skip =
404     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
405
406   addr = create_tmp_var (ptr_type_node, "va_arg");
407
408   /* if an object is dynamically sized, a pointer to it is passed
409      instead of the object itself.  */
410   pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
411                                            false);
412
413   if (pass_by_reference_p)
414     type = build_pointer_type (type);
415
416   size = int_size_in_bytes (type);
417   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
418
419   /* Assert alignment assumption.  */
420   gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY);
421
422   /* Build conditional expression to calculate addr. The expression
423      will be gimplified later.  */
424   tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
425   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
426                 build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
427                 build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
428                         unshare_expr (skip)));
429
430   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
431                 build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
432                         size_int (STACK_POINTER_OFFSET)),
433                 unshare_expr (args));
434
435   gimplify_assign (addr, tmp, pre_p);
436
437   /* Update VALIST.__args.  */
438   tmp = fold_build_pointer_plus_hwi (addr, rsize);
439   gimplify_assign (unshare_expr (args), tmp, pre_p);
440
441   addr = fold_convert (build_pointer_type (type), addr);
442
443   if (pass_by_reference_p)
444     addr = build_va_arg_indirect_ref (addr);
445
446   return build_va_arg_indirect_ref (addr);
447 }
448 \f
449
450
451 /* Implement TARGET_RTX_COSTS.  */
452 static bool
453 tilegx_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
454                   bool speed)
455 {
456   switch (code)
457     {
458     case CONST_INT:
459       /* If this is an 8-bit constant, return zero since it can be
460          used nearly anywhere with no cost.  If it is a valid operand
461          for an ADD or AND, likewise return 0 if we know it will be
462          used in that context.  Otherwise, return 2 since it might be
463          used there later.  All other constants take at least two
464          insns.  */
465       if (satisfies_constraint_I (x))
466         {
467           *total = 0;
468           return true;
469         }
470       else if (outer_code == PLUS && add_operand (x, VOIDmode))
471         {
472           /* Slightly penalize large constants even though we can add
473              them in one instruction, because it forces the use of
474              2-wide bundling mode.  */
475           *total = 1;
476           return true;
477         }
478       else if (move_operand (x, SImode))
479         {
480           /* We can materialize in one move.  */
481           *total = COSTS_N_INSNS (1);
482           return true;
483         }
484       else
485         {
486           /* We can materialize in two moves.  */
487           *total = COSTS_N_INSNS (2);
488           return true;
489         }
490
491       return false;
492
493     case CONST:
494     case LABEL_REF:
495     case SYMBOL_REF:
496       *total = COSTS_N_INSNS (2);
497       return true;
498
499     case CONST_DOUBLE:
500       *total = COSTS_N_INSNS (4);
501       return true;
502
503     case HIGH:
504       *total = 0;
505       return true;
506
507     case MEM:
508       /* If outer-code was a sign or zero extension, a cost of
509          COSTS_N_INSNS (1) was already added in, so account for
510          that.  */
511       if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
512         *total = COSTS_N_INSNS (1);
513       else
514         *total = COSTS_N_INSNS (2);
515       return true;
516
517     case PLUS:
518       /* Convey that shl[123]add are efficient.  */
519       if (GET_CODE (XEXP (x, 0)) == MULT
520           && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
521         {
522           *total = (rtx_cost (XEXP (XEXP (x, 0), 0),
523                               (enum rtx_code) outer_code, opno, speed)
524                     + rtx_cost (XEXP (x, 1),
525                                 (enum rtx_code) outer_code, opno, speed)
526                     + COSTS_N_INSNS (1));
527           return true;
528         }
529       return false;
530
531     case MULT:
532       *total = COSTS_N_INSNS (2);
533       return false;
534
535     case DIV:
536     case UDIV:
537     case MOD:
538     case UMOD:
539       /* These are handled by software and are very expensive.  */
540       *total = COSTS_N_INSNS (100);
541       return false;
542
543     case UNSPEC:
544     case UNSPEC_VOLATILE:
545       {
546         int num = XINT (x, 1);
547
548         if (num <= TILEGX_LAST_LATENCY_1_INSN)
549           *total = COSTS_N_INSNS (1);
550         else if (num <= TILEGX_LAST_LATENCY_2_INSN)
551           *total = COSTS_N_INSNS (2);
552         else if (num > TILEGX_LAST_LATENCY_INSN)
553           {
554             if (num == UNSPEC_NON_TEMPORAL)
555               {
556                 /* These are basically loads.  */
557                 if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
558                   *total = COSTS_N_INSNS (1);
559                 else
560                   *total = COSTS_N_INSNS (2);
561               }
562             else
563               {
564                 if (outer_code == PLUS)
565                   *total = 0;
566                 else
567                   *total = COSTS_N_INSNS (1);
568               }
569           }
570         else
571           {
572             switch (num)
573               {
574               case UNSPEC_BLOCKAGE:
575               case UNSPEC_NETWORK_BARRIER:
576               case UNSPEC_ATOMIC:
577                 *total = 0;
578                 break;
579
580               case UNSPEC_LNK_AND_LABEL:
581               case UNSPEC_MF:
582               case UNSPEC_MOV_PCREL_STEP3:
583               case UNSPEC_NETWORK_RECEIVE:
584               case UNSPEC_NETWORK_SEND:
585               case UNSPEC_SPR_MOVE:
586               case UNSPEC_TLS_GD_ADD:
587                 *total = COSTS_N_INSNS (1);
588                 break;
589
590               case UNSPEC_TLS_IE_LOAD:
591               case UNSPEC_XCHG:
592                 *total = COSTS_N_INSNS (2);
593                 break;
594
595               case UNSPEC_SP_SET:
596                 *total = COSTS_N_INSNS (3);
597                 break;
598
599               case UNSPEC_SP_TEST:
600                 *total = COSTS_N_INSNS (4);
601                 break;
602
603               case UNSPEC_CMPXCHG:
604               case UNSPEC_INSN_CMPEXCH:
605               case UNSPEC_LATENCY_L2:
606                 *total = COSTS_N_INSNS (11);
607                 break;
608
609               case UNSPEC_TLS_GD_CALL:
610                 *total = COSTS_N_INSNS (30);
611                 break;
612
613               case UNSPEC_LATENCY_MISS:
614                 *total = COSTS_N_INSNS (80);
615                 break;
616
617               default:
618                 *total = COSTS_N_INSNS (1);
619               }
620           }
621         return true;
622       }
623
624     default:
625       return false;
626     }
627 }
628 \f
629
630
631 /* Rtl lowering.  */
632
633 /* Create a temporary variable to hold a partial result, to enable
634    CSE.  */
635 static rtx
636 create_temp_reg_if_possible (enum machine_mode mode, rtx default_reg)
637 {
638   return can_create_pseudo_p ()? gen_reg_rtx (mode) : default_reg;
639 }
640
641
642 /* Functions to save and restore machine-specific function data.  */
643 static struct machine_function *
644 tilegx_init_machine_status (void)
645 {
646   return ggc_alloc_cleared_machine_function ();
647 }
648
649
650 /* Do anything needed before RTL is emitted for each function.  */
651 void
652 tilegx_init_expanders (void)
653 {
654   /* Arrange to initialize and mark the machine per-function
655      status.  */
656   init_machine_status = tilegx_init_machine_status;
657
658   if (cfun && cfun->machine && flag_pic)
659     {
660       static int label_num = 0;
661
662       char text_label_name[32];
663
664       struct machine_function *machine = cfun->machine;
665
666       ASM_GENERATE_INTERNAL_LABEL (text_label_name, "L_PICLNK", label_num++);
667
668       machine->text_label_symbol =
669         gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (text_label_name));
670
671       machine->text_label_rtx =
672         gen_rtx_REG (Pmode, TILEGX_PIC_TEXT_LABEL_REGNUM);
673
674       machine->got_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
675
676       machine->calls_tls_get_addr = false;
677     }
678 }
679
680
681 /* Implement TARGET_SHIFT_TRUNCATION_MASK.  DImode shifts use the mode
682    matching insns and therefore guarantee that the shift count is
683    modulo 64.  SImode shifts sometimes use the 64 bit version so do
684    not hold such guarantee.  */
685 static unsigned HOST_WIDE_INT
686 tilegx_shift_truncation_mask (enum machine_mode mode)
687 {
688   return mode == DImode ? 63 : 0;
689 }
690
691
692 /* Implement TARGET_INIT_LIBFUNCS.  */
693 static void
694 tilegx_init_libfuncs (void)
695 {
696   /* We need to explicitly generate these libfunc's to support
697      conversion of divide by constant to multiply (the divide stubs in
698      tilegx.md exist also for this reason).  Normally we'd expect gcc
699      to lazily generate them when they are needed, but for some reason
700      it's set up to only generate them if the mode is the word
701      mode.  */
702   set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
703   set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
704   set_optab_libfunc (smod_optab, SImode, "__modsi3");
705   set_optab_libfunc (umod_optab, SImode, "__umodsi3");
706 }
707
708
709 /* Return true if X contains a thread-local symbol.  */
710 static bool
711 tilegx_tls_referenced_p (rtx x)
712 {
713   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
714     x = XEXP (XEXP (x, 0), 0);
715
716   if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
717     return true;
718
719   /* That's all we handle in tilegx_legitimize_tls_address for
720      now.  */
721   return false;
722 }
723
724
725 /* Return true if X requires a scratch register.  It is given that
726    flag_pic is on and that X satisfies CONSTANT_P.  */
727 static int
728 tilegx_pic_address_needs_scratch (rtx x)
729 {
730   if (GET_CODE (x) == CONST
731       && GET_CODE (XEXP (x, 0)) == PLUS
732       && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
733           || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
734       && (CONST_INT_P (XEXP (XEXP (x, 0), 1))))
735     return true;
736
737   return false;
738 }
739
740
741 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  This is all constants for
742    which we are willing to load the value into a register via a move
743    pattern.  TLS cannot be treated as a constant because it can
744    include a function call.  */
745 static bool
746 tilegx_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
747 {
748   switch (GET_CODE (x))
749     {
750     case CONST:
751     case SYMBOL_REF:
752       return !tilegx_tls_referenced_p (x);
753
754     default:
755       return true;
756     }
757 }
758
759
760 /* Return true if the constant value X is a legitimate general operand
761    when generating PIC code.  It is given that flag_pic is on and that
762    X satisfies CONSTANT_P.  */
763 bool
764 tilegx_legitimate_pic_operand_p (rtx x)
765 {
766   if (tilegx_pic_address_needs_scratch (x))
767     return false;
768
769   if (tilegx_tls_referenced_p (x))
770     return false;
771
772   return true;
773 }
774
775
776 /* Return true if the rtx X can be used as an address operand.  */
777 static bool
778 tilegx_legitimate_address_p (enum machine_mode ARG_UNUSED (mode), rtx x,
779                              bool strict)
780 {
781   if (GET_CODE (x) == SUBREG)
782     x = SUBREG_REG (x);
783
784   switch (GET_CODE (x))
785     {
786     case POST_INC:
787     case POST_DEC:
788       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
789         return false;
790
791       x = XEXP (x, 0);
792       break;
793
794     case POST_MODIFY:
795       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
796         return false;
797
798       if (GET_CODE (XEXP (x, 1)) != PLUS)
799         return false;
800
801       if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
802         return false;
803
804       if (!satisfies_constraint_I (XEXP (XEXP (x, 1), 1)))
805         return false;
806
807       x = XEXP (x, 0);
808       break;
809
810     case REG:
811       break;
812
813     default:
814       return false;
815     }
816
817   /* Check if x is a valid reg.  */
818   if (!REG_P (x))
819     return false;
820
821   if (strict)
822     return REGNO_OK_FOR_BASE_P (REGNO (x));
823   else
824     return true;
825 }
826
827
828 /* Return the rtx containing SYMBOL_REF to the text label.  */
829 static rtx
830 tilegx_text_label_symbol (void)
831 {
832   return cfun->machine->text_label_symbol;
833 }
834
835
836 /* Return the register storing the value of the text label.  */
837 static rtx
838 tilegx_text_label_rtx (void)
839 {
840   return cfun->machine->text_label_rtx;
841 }
842
843
844 /* Return the register storing the value of the global offset
845    table.  */
846 static rtx
847 tilegx_got_rtx (void)
848 {
849   return cfun->machine->got_rtx;
850 }
851
852
853 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_.  */
854 static rtx
855 tilegx_got_symbol (void)
856 {
857   if (g_got_symbol == NULL)
858     g_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
859
860   return g_got_symbol;
861 }
862
863
864 /* Return a reference to the got to be used by tls references.  */
865 static rtx
866 tilegx_tls_got (void)
867 {
868   rtx temp;
869   if (flag_pic)
870     {
871       crtl->uses_pic_offset_table = 1;
872       return tilegx_got_rtx ();
873     }
874
875   temp = gen_reg_rtx (Pmode);
876   emit_move_insn (temp, tilegx_got_symbol ());
877
878   return temp;
879 }
880
881
882 /* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
883    this (thread-local) address.  */
884 static rtx
885 tilegx_legitimize_tls_address (rtx addr)
886 {
887   rtx ret;
888
889   gcc_assert (can_create_pseudo_p ());
890
891   if (GET_CODE (addr) == SYMBOL_REF)
892     switch (SYMBOL_REF_TLS_MODEL (addr))
893       {
894       case TLS_MODEL_GLOBAL_DYNAMIC:
895       case TLS_MODEL_LOCAL_DYNAMIC:
896         {
897           rtx r0, temp, temp2, temp3, got, last;
898
899           ret = gen_reg_rtx (Pmode);
900           r0 = gen_rtx_REG (Pmode, 0);
901           temp = gen_reg_rtx (Pmode);
902           temp2 = gen_reg_rtx (Pmode);
903           temp3 = gen_reg_rtx (Pmode);
904
905           got = tilegx_tls_got ();
906           if (TARGET_32BIT)
907             {
908               emit_insn (gen_mov_tls_gd_step1_32bit (temp, addr));
909               emit_insn (gen_mov_tls_gd_step2_32bit (temp2, temp, addr));
910               emit_insn (gen_tls_add_32bit (temp2, got, temp2, addr));
911             }
912           else
913             {
914               emit_insn (gen_mov_tls_gd_step1 (temp, addr));
915               emit_insn (gen_mov_tls_gd_step2 (temp2, temp, addr));
916               emit_insn (gen_tls_add (temp2, got, temp2, addr));
917             }
918
919           emit_move_insn (r0, temp2);
920
921           if (TARGET_32BIT)
922             {
923               emit_insn (gen_tls_gd_call_32bit (addr));
924             }
925           else
926             {
927               emit_insn (gen_tls_gd_call (addr));
928             }
929
930           emit_move_insn (temp3, r0);
931
932           if (TARGET_32BIT)
933             last = emit_insn (gen_tls_gd_add_32bit (ret, temp3, addr));
934           else
935             last = emit_insn (gen_tls_gd_add (ret, temp3, addr));
936
937           set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
938           break;
939         }
940       case TLS_MODEL_INITIAL_EXEC:
941         {
942           rtx temp, temp2, temp3, got, last;
943
944           ret = gen_reg_rtx (Pmode);
945           temp = gen_reg_rtx (Pmode);
946           temp2 = gen_reg_rtx (Pmode);
947           temp3 = gen_reg_rtx (Pmode);
948
949           got = tilegx_tls_got ();
950           if (TARGET_32BIT)
951             {
952               emit_insn (gen_mov_tls_ie_step1_32bit (temp, addr));
953               emit_insn (gen_mov_tls_ie_step2_32bit (temp2, temp, addr));
954               emit_insn (gen_tls_add_32bit (temp2, got, temp2, addr));
955               emit_insn (gen_tls_ie_load_32bit (temp3, temp2, addr));
956             }
957           else
958             {
959               emit_insn (gen_mov_tls_ie_step1 (temp, addr));
960               emit_insn (gen_mov_tls_ie_step2 (temp2, temp, addr));
961               emit_insn (gen_tls_add (temp2, got, temp2, addr));
962               emit_insn (gen_tls_ie_load (temp3, temp2, addr));
963             }
964
965           last =
966             emit_move_insn(ret,
967                            gen_rtx_PLUS (Pmode,
968                                          gen_rtx_REG (Pmode,
969                                                       THREAD_POINTER_REGNUM),
970                                          temp3));
971           set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
972           break;
973         }
974       case TLS_MODEL_LOCAL_EXEC:
975         {
976           rtx temp, temp2, last;
977
978           ret = gen_reg_rtx (Pmode);
979           temp = gen_reg_rtx (Pmode);
980           temp2 = gen_reg_rtx (Pmode);
981
982           if (TARGET_32BIT)
983             {
984               emit_insn (gen_mov_tls_le_step1_32bit (temp, addr));
985               emit_insn (gen_mov_tls_le_step2_32bit (temp2, temp, addr));
986             }
987           else
988             {
989               emit_insn (gen_mov_tls_le_step1 (temp, addr));
990               emit_insn (gen_mov_tls_le_step2 (temp2, temp, addr));
991             }
992
993           last =
994             emit_move_insn (ret,
995                             gen_rtx_PLUS (Pmode,
996                                           gen_rtx_REG (Pmode,
997                                                        THREAD_POINTER_REGNUM),
998                                           temp2));
999           set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
1000           break;
1001         }
1002       default:
1003         gcc_unreachable ();
1004       }
1005   else if (GET_CODE (addr) == CONST)
1006     {
1007       rtx base, offset;
1008
1009       gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
1010
1011       base = tilegx_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
1012       offset = XEXP (XEXP (addr, 0), 1);
1013
1014       base = force_operand (base, NULL_RTX);
1015       ret = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
1016     }
1017   else
1018     gcc_unreachable ();
1019
1020   return ret;
1021 }
1022
1023
1024 /* Returns a register that points to ADDR, a symbolic address, by
1025    computing its address relative to tilegx_text_label_symbol.  */
1026 static void
1027 compute_pcrel_address (rtx result, rtx addr)
1028 {
1029   rtx text_label_symbol = tilegx_text_label_symbol ();
1030   rtx text_label_rtx = tilegx_text_label_rtx ();
1031   rtx temp, temp2;
1032
1033   temp = create_temp_reg_if_possible (Pmode, result);
1034   temp2 = create_temp_reg_if_possible (Pmode, result);
1035
1036   if (TARGET_32BIT)
1037     {
1038       emit_insn (gen_mov_pcrel_step1_32bit (temp, addr, text_label_symbol));
1039       emit_insn (gen_mov_pcrel_step2_32bit (temp2, temp, addr,
1040                                             text_label_symbol));
1041       emit_insn (gen_mov_pcrel_step3_32bit (result, temp2,
1042                                             text_label_rtx,
1043                                             addr, text_label_symbol));
1044     }
1045   else
1046     {
1047       emit_insn (gen_mov_pcrel_step1 (temp, addr, text_label_symbol));
1048       emit_insn (gen_mov_pcrel_step2 (temp2, temp, addr, text_label_symbol));
1049       emit_insn (gen_mov_pcrel_step3 (result, temp2,
1050                                       text_label_rtx,
1051                                       addr, text_label_symbol));
1052     }
1053 }
1054
1055
1056 /* Legitimize PIC addresses.  If the address is already
1057    position-independent, we return ORIG.  Newly generated
1058    position-independent addresses go into a reg.  This is REG if
1059    nonzero, otherwise we allocate register(s) as necessary.  */
1060 static rtx
1061 tilegx_legitimize_pic_address (rtx orig,
1062                                enum machine_mode mode ATTRIBUTE_UNUSED,
1063                                rtx reg)
1064 {
1065   if (GET_CODE (orig) == SYMBOL_REF)
1066     {
1067       rtx address, pic_ref;
1068
1069       if (reg == 0)
1070         {
1071           gcc_assert (can_create_pseudo_p ());
1072           reg = gen_reg_rtx (Pmode);
1073         }
1074
1075       if (SYMBOL_REF_LOCAL_P (orig))
1076         {
1077           /* If not during reload, allocate another temp reg here for
1078              loading in the address, so that these instructions can be
1079              optimized properly.  */
1080           rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
1081           compute_pcrel_address (temp_reg, orig);
1082
1083           /* Note: this is conservative.  We use the text_label but we
1084              don't use the pic_offset_table.  However, in some cases
1085              we may need the pic_offset_table (see
1086              tilegx_fixup_pcrel_references).  */
1087           crtl->uses_pic_offset_table = 1;
1088
1089           address = temp_reg;
1090
1091           emit_move_insn (reg, address);
1092           return reg;
1093         }
1094       else
1095         {
1096           /* If not during reload, allocate another temp reg here for
1097              loading in the address, so that these instructions can be
1098              optimized properly.  */
1099           rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
1100
1101           gcc_assert (flag_pic);
1102           if (flag_pic == 1)
1103             {
1104               if (TARGET_32BIT)
1105                 {
1106                   emit_insn (gen_add_got16_32bit (temp_reg,
1107                                                   tilegx_got_rtx (),
1108                                                   orig));
1109                 }
1110               else
1111                 {
1112                   emit_insn (gen_add_got16 (temp_reg,
1113                                             tilegx_got_rtx (), orig));
1114                 }
1115             }
1116           else
1117             {
1118               rtx temp_reg2 = create_temp_reg_if_possible (Pmode, reg);
1119               rtx temp_reg3 = create_temp_reg_if_possible (Pmode, reg);
1120               if (TARGET_32BIT)
1121                 {
1122                   emit_insn (gen_mov_got32_step1_32bit (temp_reg3, orig));
1123                   emit_insn (gen_mov_got32_step2_32bit
1124                              (temp_reg2, temp_reg3, orig));
1125                 }
1126               else
1127                 {
1128                   emit_insn (gen_mov_got32_step1 (temp_reg3, orig));
1129                   emit_insn (gen_mov_got32_step2 (temp_reg2, temp_reg3,
1130                                                   orig));
1131                 }
1132               emit_move_insn (temp_reg,
1133                               gen_rtx_PLUS (Pmode,
1134                                             tilegx_got_rtx (), temp_reg2));
1135             }
1136
1137           address = temp_reg;
1138
1139           pic_ref = gen_const_mem (Pmode, address);
1140           crtl->uses_pic_offset_table = 1;
1141           emit_move_insn (reg, pic_ref);
1142           /* The following put a REG_EQUAL note on this insn, so that
1143              it can be optimized by loop.  But it causes the label to
1144              be optimized away.  */
1145           /* set_unique_reg_note (insn, REG_EQUAL, orig); */
1146           return reg;
1147         }
1148     }
1149   else if (GET_CODE (orig) == CONST)
1150     {
1151       rtx base, offset;
1152
1153       if (GET_CODE (XEXP (orig, 0)) == PLUS
1154           && XEXP (XEXP (orig, 0), 0) == tilegx_got_rtx ())
1155         return orig;
1156
1157       if (reg == 0)
1158         {
1159           gcc_assert (can_create_pseudo_p ());
1160           reg = gen_reg_rtx (Pmode);
1161         }
1162
1163       gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1164       base = tilegx_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
1165                                             Pmode, reg);
1166       offset = tilegx_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1167                                               base == reg ? 0 : reg);
1168
1169       if (CONST_INT_P (offset))
1170         {
1171           if (can_create_pseudo_p ())
1172             offset = force_reg (Pmode, offset);
1173           else
1174             /* If we reach here, then something is seriously wrong.  */
1175             gcc_unreachable ();
1176         }
1177
1178       if (can_create_pseudo_p ())
1179         return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
1180       else
1181         gcc_unreachable ();
1182     }
1183   else if (GET_CODE (orig) == LABEL_REF)
1184     {
1185       rtx address;
1186       rtx temp_reg;
1187
1188       if (reg == 0)
1189         {
1190           gcc_assert (can_create_pseudo_p ());
1191           reg = gen_reg_rtx (Pmode);
1192         }
1193
1194       /* If not during reload, allocate another temp reg here for
1195          loading in the address, so that these instructions can be
1196          optimized properly.  */
1197       temp_reg = create_temp_reg_if_possible (Pmode, reg);
1198       compute_pcrel_address (temp_reg, orig);
1199
1200       /* Note: this is conservative.  We use the text_label but we
1201          don't use the pic_offset_table.  */
1202       crtl->uses_pic_offset_table = 1;
1203
1204       address = temp_reg;
1205
1206       emit_move_insn (reg, address);
1207
1208       return reg;
1209     }
1210
1211   return orig;
1212 }
1213
1214
1215 /* Implement TARGET_LEGITIMIZE_ADDRESS.  */
1216 static rtx
1217 tilegx_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1218                            enum machine_mode mode)
1219 {
1220   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
1221       && symbolic_operand (x, Pmode) && tilegx_tls_referenced_p (x))
1222     {
1223       return tilegx_legitimize_tls_address (x);
1224     }
1225   else if (flag_pic)
1226     {
1227       return tilegx_legitimize_pic_address (x, mode, 0);
1228     }
1229   else
1230     return x;
1231 }
1232
1233
1234 /* Implement TARGET_DELEGITIMIZE_ADDRESS.  */
1235 static rtx
1236 tilegx_delegitimize_address (rtx x)
1237 {
1238   x = delegitimize_mem_from_attrs (x);
1239
1240   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
1241     {
1242       switch (XINT (XEXP (x, 0), 1))
1243         {
1244           case UNSPEC_HW0:
1245           case UNSPEC_HW1:
1246           case UNSPEC_HW2:
1247           case UNSPEC_HW3:
1248           case UNSPEC_HW0_LAST:
1249           case UNSPEC_HW1_LAST:
1250           case UNSPEC_HW2_LAST:
1251           case UNSPEC_HW0_PCREL:
1252           case UNSPEC_HW1_LAST_PCREL:
1253           case UNSPEC_HW0_GOT:
1254           case UNSPEC_HW0_LAST_GOT:
1255           case UNSPEC_HW1_LAST_GOT:
1256           case UNSPEC_HW0_TLS_GD:
1257           case UNSPEC_HW1_LAST_TLS_GD:
1258           case UNSPEC_HW0_TLS_IE:
1259           case UNSPEC_HW1_LAST_TLS_IE:
1260           case UNSPEC_HW0_TLS_LE:
1261           case UNSPEC_HW1_LAST_TLS_LE:
1262             x = XVECEXP (XEXP (x, 0), 0, 0);
1263           break;
1264         }
1265     }
1266
1267   return x;
1268 }
1269
1270
1271 /* Emit code to load the PIC register.  */
1272 static void
1273 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED)
1274 {
1275   int orig_flag_pic = flag_pic;
1276
1277   rtx got_symbol = tilegx_got_symbol ();
1278   rtx text_label_symbol = tilegx_text_label_symbol ();
1279   rtx text_label_rtx = tilegx_text_label_rtx ();
1280   flag_pic = 0;
1281
1282   if (TARGET_32BIT)
1283     {
1284       emit_insn (gen_insn_lnk_and_label_32bit (text_label_rtx,
1285                                                text_label_symbol));
1286     }
1287   else
1288     {
1289       emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol));
1290     }
1291
1292   compute_pcrel_address (tilegx_got_rtx (), got_symbol);
1293
1294   flag_pic = orig_flag_pic;
1295
1296   /* Need to emit this whether or not we obey regdecls, since
1297      setjmp/longjmp can cause life info to screw up.  ??? In the case
1298      where we don't obey regdecls, this is not sufficient since we may
1299      not fall out the bottom.  */
1300   emit_use (tilegx_got_rtx ());
1301 }
1302
1303
1304 /* Return the simd variant of the constant NUM of mode MODE, by
1305    replicating it to fill an interger of mode DImode.  NUM is first
1306    truncated to fit in MODE.  */
1307 rtx
1308 tilegx_simd_int (rtx num, enum machine_mode mode)
1309 {
1310   HOST_WIDE_INT n = 0;
1311
1312   gcc_assert (CONST_INT_P (num));
1313
1314   n = INTVAL (num);
1315
1316   switch (mode)
1317     {
1318     case QImode:
1319       n = 0x0101010101010101LL * (n & 0x000000FF);
1320       break;
1321     case HImode:
1322       n = 0x0001000100010001LL * (n & 0x0000FFFF);
1323       break;
1324     case SImode:
1325       n = 0x0000000100000001LL * (n & 0xFFFFFFFF);
1326       break;
1327     case DImode:
1328       break;
1329     default:
1330       gcc_unreachable ();
1331     }
1332
1333   return GEN_INT (n);
1334 }
1335
1336
1337 /* Returns true iff VAL can be moved into a register in one
1338    instruction.  And if it can, it emits the code to move the
1339    constant into DEST_REG.
1340
1341    If THREE_WIDE_ONLY is true, this insists on an instruction that
1342    works in a bundle containing three instructions.  */
1343 static bool
1344 expand_set_cint64_one_inst (rtx dest_reg,
1345                             HOST_WIDE_INT val, bool three_wide_only)
1346 {
1347   if (val == trunc_int_for_mode (val, QImode))
1348     {
1349       /* Success! */
1350       emit_move_insn (dest_reg, GEN_INT (val));
1351       return true;
1352     }
1353   else if (!three_wide_only)
1354     {
1355       rtx imm_op = GEN_INT (val);
1356
1357       if (satisfies_constraint_J (imm_op)
1358           || satisfies_constraint_K (imm_op)
1359           || satisfies_constraint_N (imm_op)
1360           || satisfies_constraint_P (imm_op))
1361         {
1362           emit_move_insn (dest_reg, imm_op);
1363           return true;
1364         }
1365     }
1366
1367   return false;
1368 }
1369
1370
1371 /* Implement DImode rotatert.  */
1372 static HOST_WIDE_INT
1373 rotate_right (HOST_WIDE_INT n, int count)
1374 {
1375   unsigned HOST_WIDE_INT x = n & 0xFFFFFFFFFFFFFFFFULL;
1376   if (count == 0)
1377     return x;
1378   return ((x >> count) | (x << (64 - count))) & 0xFFFFFFFFFFFFFFFFULL;
1379 }
1380
1381
1382 /* Return true iff n contains exactly one contiguous sequence of 1
1383    bits, possibly wrapping around from high bits to low bits.  */
1384 bool
1385 tilegx_bitfield_operand_p (HOST_WIDE_INT n, int *first_bit, int *last_bit)
1386 {
1387   int i;
1388
1389   if (n == 0)
1390     return false;
1391
1392   for (i = 0; i < 64; i++)
1393     {
1394       unsigned HOST_WIDE_INT x = rotate_right (n, i);
1395       if (!(x & 1))
1396         continue;
1397
1398       /* See if x is a power of two minus one, i.e. only consecutive 1
1399          bits starting from bit 0.  */
1400       if ((x & (x + 1)) == 0)
1401         {
1402           if (first_bit != NULL)
1403             *first_bit = i;
1404           if (last_bit != NULL)
1405             *last_bit = (i + exact_log2 (x ^ (x >> 1))) & 63;
1406
1407           return true;
1408         }
1409     }
1410
1411   return false;
1412 }
1413
1414
1415 /* Create code to move the CONST_INT value in src_val to dest_reg.  */
1416 static void
1417 expand_set_cint64 (rtx dest_reg, rtx src_val)
1418 {
1419   HOST_WIDE_INT val;
1420   int leading_zeroes, trailing_zeroes;
1421   int three_wide_only;
1422   int shift, ins_shift, zero_cluster_shift;
1423   rtx temp, subreg;
1424
1425   gcc_assert (CONST_INT_P (src_val));
1426   val = trunc_int_for_mode (INTVAL (src_val), GET_MODE (dest_reg));
1427
1428   /* See if we can generate the constant in one instruction.  */
1429   if (expand_set_cint64_one_inst (dest_reg, val, false))
1430     return;
1431
1432   /* Force the destination to DImode so we can use DImode instructions
1433      to create it.  This both allows instructions like rotl, and
1434      certain efficient 3-wide instructions.  */
1435   subreg = simplify_gen_subreg (DImode, dest_reg, GET_MODE (dest_reg), 0);
1436   gcc_assert (subreg != NULL);
1437   dest_reg = subreg;
1438
1439   temp = create_temp_reg_if_possible (DImode, dest_reg);
1440
1441   leading_zeroes = 63 - floor_log2 (val & 0xFFFFFFFFFFFFFFFFULL);
1442   trailing_zeroes = exact_log2 (val & -val);
1443
1444   /* First try all three-wide instructions that generate a constant
1445      (i.e. movei) followed by various shifts and rotates. If none of
1446      those work, try various two-wide ways of generating a constant
1447      followed by various shifts and rotates.  */
1448   for (three_wide_only = 1; three_wide_only >= 0; three_wide_only--)
1449     {
1450       int count;
1451
1452       if (expand_set_cint64_one_inst (temp, val >> trailing_zeroes,
1453                                       three_wide_only))
1454         {
1455           /* 0xFFFFFFFFFFFFA500 becomes:
1456              movei temp, 0xFFFFFFFFFFFFFFA5
1457              shli dest, temp, 8  */
1458           emit_move_insn (dest_reg,
1459                           gen_rtx_ASHIFT (DImode, temp,
1460                                           GEN_INT (trailing_zeroes)));
1461           return;
1462         }
1463
1464       if (expand_set_cint64_one_inst (temp, val << leading_zeroes,
1465                                       three_wide_only))
1466         {
1467           /* 0x7FFFFFFFFFFFFFFF becomes:
1468              movei temp, -2
1469              shrui dest, temp, 1  */
1470           emit_move_insn (dest_reg,
1471                           gen_rtx_LSHIFTRT (DImode, temp,
1472                                             GEN_INT (leading_zeroes)));
1473           return;
1474         }
1475
1476       /* Try rotating a one-instruction immediate.  */
1477       for (count = 1; count < 64; count++)
1478         {
1479           HOST_WIDE_INT r = rotate_right (val, count);
1480           if (expand_set_cint64_one_inst (temp, r, three_wide_only))
1481             {
1482               /* 0xFFFFFFFFFFA5FFFF becomes:
1483                  movei temp, 0xFFFFFFFFFFFFFFA5
1484                  rotli dest, temp, 16  */
1485               emit_move_insn (dest_reg,
1486                               gen_rtx_ROTATE (DImode, temp, GEN_INT (count)));
1487               return;
1488             }
1489         }
1490     }
1491
1492   /* There are two cases here to produce a large constant.
1493      In the most general case, we do this:
1494
1495      moveli x, hw3(NUM)
1496      shl16insli x, x, hw2(NUM)
1497      shl16insli x, x, hw1(NUM)
1498      shl16insli x, x, hw0(NUM)
1499
1500      However, we can sometimes do better.  shl16insli is a poor way to
1501      insert 16 zero bits, because simply shifting left by 16 has more
1502      bundling freedom.  So if we see any contiguous aligned sequence
1503      of 16 or more zero bits (below the highest set bit), it is always
1504      more efficient to materialize the bits above the zero bits, then
1505      left shift to put in the zeroes, then insert whatever bits
1506      remain.  For example, we might end up with:
1507
1508      movei x, NUM >> (37 + 16)
1509      shli x, x, 37
1510      shl16insli x, x, hw0(NUM)      */
1511
1512   zero_cluster_shift = -1;
1513
1514   for (shift = 0; shift < 48 - leading_zeroes; shift += 16)
1515     {
1516       HOST_WIDE_INT x = val >> shift;
1517
1518       /* Find the least significant group of 16 aligned zero bits.  */
1519       if ((x & 0xFFFF) == 0x0000)
1520         {
1521           /* Grab any following zero bits as well.  */
1522           zero_cluster_shift = exact_log2 (x & -x);
1523           shift += zero_cluster_shift;
1524           break;
1525         }
1526     }
1527
1528   if (zero_cluster_shift >= 0)
1529     {
1530       unsigned HOST_WIDE_INT leftover;
1531
1532       /* Recursively create the constant above the lowest 16 zero
1533          bits.  */
1534       expand_set_cint64 (temp, GEN_INT (val >> shift));
1535
1536       /* See if we can easily insert the remaining bits, or if we need
1537          to fall through to the more general case.  */
1538       leftover = val - ((val >> shift) << shift);
1539       if (leftover == 0)
1540         {
1541           /* A simple left shift is enough.  */
1542           emit_move_insn (dest_reg,
1543                           gen_rtx_ASHIFT (DImode, temp, GEN_INT (shift)));
1544           return;
1545         }
1546       else if (leftover <= 32767)
1547         {
1548           /* Left shift into position then add in the leftover.  */
1549           rtx temp2 = create_temp_reg_if_possible (DImode, temp);
1550           emit_move_insn (temp2,
1551                           gen_rtx_ASHIFT (DImode, temp, GEN_INT (shift)));
1552           emit_move_insn (dest_reg,
1553                           gen_rtx_PLUS (DImode, temp2, GEN_INT (leftover)));
1554           return;
1555         }
1556       else
1557         {
1558           /* Shift in the batch of >= 16 zeroes we detected earlier.
1559              After this, shift will be aligned mod 16 so the final
1560              loop can use shl16insli.  */
1561           rtx temp2 = create_temp_reg_if_possible (DImode, temp);
1562           rtx shift_count_rtx = GEN_INT (zero_cluster_shift);
1563
1564           emit_move_insn (temp2,
1565                           gen_rtx_ASHIFT (DImode, temp, shift_count_rtx));
1566
1567           shift -= zero_cluster_shift;
1568           temp = temp2;
1569         }
1570     }
1571   else
1572     {
1573       /* Set as many high 16-bit blocks as we can with a single
1574          instruction.  We'll insert the remaining 16-bit blocks
1575          below.  */
1576       for (shift = 16;; shift += 16)
1577         {
1578           gcc_assert (shift < 64);
1579           if (expand_set_cint64_one_inst (temp, val >> shift, false))
1580             break;
1581         }
1582     }
1583
1584   /* At this point, temp == val >> shift, shift % 16 == 0, and we
1585      still need to insert any bits of 'val' below 'shift'. Those bits
1586      are guaranteed to not have 16 contiguous zeroes.  */
1587
1588   gcc_assert ((shift & 15) == 0);
1589
1590   for (ins_shift = shift - 16; ins_shift >= 0; ins_shift -= 16)
1591     {
1592       rtx result;
1593       HOST_WIDE_INT bits = (val >> ins_shift) & 0xFFFF;
1594       gcc_assert (bits != 0);
1595
1596       /* On the last iteration we need to store into dest_reg.  */
1597       if (ins_shift == 0)
1598         result = dest_reg;
1599       else
1600         result = create_temp_reg_if_possible (DImode, dest_reg);
1601
1602       emit_insn (gen_insn_shl16insli (result, temp, GEN_INT (bits)));
1603
1604       temp = result;
1605     }
1606 }
1607
1608
1609 /* Load OP1, a 64-bit constant, into OP0, a register.  We know it
1610    can't be done in one insn when we get here, the move expander
1611    guarantees this.  */
1612 void
1613 tilegx_expand_set_const64 (rtx op0, rtx op1)
1614 {
1615   if (CONST_INT_P (op1))
1616     {
1617       /* TODO: I don't know if we want to split large constants
1618          now, or wait until later (with a define_split).
1619
1620          Does splitting early help CSE?  Does it harm other
1621          optimizations that might fold loads? */
1622       expand_set_cint64 (op0, op1);
1623     }
1624   else
1625     {
1626       rtx temp = create_temp_reg_if_possible (Pmode, op0);
1627
1628       if (TARGET_32BIT)
1629         {
1630           /* Generate the 2-insn sequence to materialize a symbolic
1631              address.  */
1632           emit_insn (gen_mov_address_32bit_step1 (temp, op1));
1633           emit_insn (gen_mov_address_32bit_step2 (op0, temp, op1));
1634         }
1635       else
1636         {
1637           /* Generate the 3-insn sequence to materialize a symbolic
1638              address.  Note that this assumes that virtual addresses
1639              fit in 48 signed bits, which is currently true.  */
1640           rtx temp2 = create_temp_reg_if_possible (Pmode, op0);
1641           emit_insn (gen_mov_address_step1 (temp, op1));
1642           emit_insn (gen_mov_address_step2 (temp2, temp, op1));
1643           emit_insn (gen_mov_address_step3 (op0, temp2, op1));
1644         }
1645     }
1646 }
1647
1648
1649 /* Expand a move instruction.  Return true if all work is done.  */
1650 bool
1651 tilegx_expand_mov (enum machine_mode mode, rtx *operands)
1652 {
1653   /* Handle sets of MEM first.  */
1654   if (MEM_P (operands[0]))
1655     {
1656       if (can_create_pseudo_p ())
1657         operands[0] = validize_mem (operands[0]);
1658
1659       if (reg_or_0_operand (operands[1], mode))
1660         return false;
1661
1662       if (!reload_in_progress)
1663         operands[1] = force_reg (mode, operands[1]);
1664     }
1665
1666   /* Fixup TLS cases.  */
1667   if (CONSTANT_P (operands[1]) && tilegx_tls_referenced_p (operands[1]))
1668     {
1669       operands[1] = tilegx_legitimize_tls_address (operands[1]);
1670       return false;
1671     }
1672
1673   /* Fixup PIC cases.  */
1674   if (flag_pic && CONSTANT_P (operands[1]))
1675     {
1676       if (tilegx_pic_address_needs_scratch (operands[1]))
1677         operands[1] = tilegx_legitimize_pic_address (operands[1], mode, 0);
1678
1679       if (symbolic_operand (operands[1], mode))
1680         {
1681           operands[1] = tilegx_legitimize_pic_address (operands[1],
1682                                                        mode,
1683                                                        (reload_in_progress ?
1684                                                         operands[0] :
1685                                                         NULL_RTX));
1686           return false;
1687         }
1688     }
1689
1690   /* Accept non-constants and valid constants unmodified.  */
1691   if (!CONSTANT_P (operands[1]) || move_operand (operands[1], mode))
1692     return false;
1693
1694   /* Split large integers.  */
1695   tilegx_expand_set_const64 (operands[0], operands[1]);
1696   return true;
1697 }
1698
1699
1700 /* Expand unaligned loads.  */
1701 void
1702 tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
1703                               HOST_WIDE_INT bit_offset, bool sign)
1704 {
1705   enum machine_mode mode;
1706   rtx addr_lo, addr_hi;
1707   rtx mem_lo, mem_hi, hi;
1708   rtx mema, wide_result;
1709   int last_byte_offset;
1710   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
1711
1712   mode = GET_MODE (dest_reg);
1713
1714   hi = gen_reg_rtx (mode);
1715
1716   if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0)
1717     {
1718       /* When just loading a two byte value, we can load the two bytes
1719          individually and combine them efficiently.  */
1720
1721       mem_lo = adjust_address (mem, QImode, byte_offset);
1722       mem_hi = adjust_address (mem, QImode, byte_offset + 1);
1723
1724       if (sign)
1725         {
1726           /* Do a signed load of the second byte and use bfins to set
1727              the high bits of the result.  */
1728           emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, dest_reg),
1729                                            mem_lo));
1730           emit_insn (gen_extendqidi2 (gen_lowpart (DImode, hi), mem_hi));
1731           emit_insn (gen_insv (gen_lowpart (DImode, dest_reg),
1732                                GEN_INT (64 - 8), GEN_INT (8),
1733                                gen_lowpart (DImode, hi)));
1734         }
1735       else
1736         {
1737           /* Do two unsigned loads and use v1int_l to interleave
1738              them.  */
1739           rtx lo = gen_reg_rtx (mode);
1740           emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, lo),
1741                                            mem_lo));
1742           emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, hi),
1743                                            mem_hi));
1744           emit_insn (gen_insn_v1int_l (gen_lowpart (DImode, dest_reg),
1745                                        gen_lowpart (DImode, hi),
1746                                        gen_lowpart (DImode, lo)));
1747         }
1748
1749       return;
1750     }
1751
1752   mema = XEXP (mem, 0);
1753
1754   /* AND addresses cannot be in any alias set, since they may
1755      implicitly alias surrounding code.  Ideally we'd have some alias
1756      set that covered all types except those with alignment 8 or
1757      higher.  */
1758   addr_lo = force_reg (Pmode, plus_constant (mema, byte_offset));
1759   mem_lo = change_address (mem, mode,
1760                            gen_rtx_AND (GET_MODE (mema), addr_lo,
1761                                         GEN_INT (-8)));
1762   set_mem_alias_set (mem_lo, 0);
1763
1764   /* Load the high word at an address that will not fault if the low
1765      address is aligned and at the very end of a page.  */
1766   last_byte_offset = (bit_offset + bitsize - 1) / BITS_PER_UNIT;
1767   addr_hi = force_reg (Pmode, plus_constant (mema, last_byte_offset));
1768   mem_hi = change_address (mem, mode,
1769                            gen_rtx_AND (GET_MODE (mema), addr_hi,
1770                                         GEN_INT (-8)));
1771   set_mem_alias_set (mem_hi, 0);
1772
1773   if (bitsize == 64)
1774     {
1775       addr_lo = make_safe_from (addr_lo, dest_reg);
1776       wide_result = dest_reg;
1777     }
1778   else
1779     {
1780       wide_result = gen_reg_rtx (mode);
1781     }
1782
1783   /* Load hi first in case dest_reg is used in mema.  */
1784   emit_move_insn (hi, mem_hi);
1785   emit_move_insn (wide_result, mem_lo);
1786
1787   emit_insn (gen_insn_dblalign (gen_lowpart (DImode, wide_result),
1788                                 gen_lowpart (DImode, wide_result),
1789                                 gen_lowpart (DImode, hi), addr_lo));
1790
1791   if (bitsize != 64)
1792     {
1793       rtx extracted =
1794         extract_bit_field (gen_lowpart (DImode, wide_result),
1795                            bitsize, bit_offset % BITS_PER_UNIT,
1796                            !sign, false, gen_lowpart (DImode, dest_reg),
1797                            DImode, DImode);
1798
1799       if (extracted != dest_reg)
1800         emit_move_insn (dest_reg, gen_lowpart (DImode, extracted));
1801     }
1802 }
1803
1804
1805 /* Expand unaligned stores.  */
1806 static void
1807 tilegx_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize,
1808                                HOST_WIDE_INT bit_offset)
1809 {
1810   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
1811   HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT;
1812   HOST_WIDE_INT shift_amt;
1813   HOST_WIDE_INT i;
1814   rtx mem_addr;
1815   rtx store_val;
1816
1817   for (i = 0, shift_amt = 0; i < bytesize; i++, shift_amt += BITS_PER_UNIT)
1818     {
1819       mem_addr = adjust_address (mem, QImode, byte_offset + i);
1820
1821       if (shift_amt)
1822         {
1823           store_val = expand_simple_binop (DImode, LSHIFTRT,
1824                                            gen_lowpart (DImode, src),
1825                                            GEN_INT (shift_amt), NULL, 1,
1826                                            OPTAB_LIB_WIDEN);
1827           store_val = gen_lowpart (QImode, store_val);
1828         }
1829       else
1830         {
1831           store_val = gen_lowpart (QImode, src);
1832         }
1833
1834       emit_move_insn (mem_addr, store_val);
1835     }
1836 }
1837
1838
1839 /* Implement the movmisalign patterns.  One of the operands is a
1840    memory that is not naturally aligned.  Emit instructions to load
1841    it.  */
1842 void
1843 tilegx_expand_movmisalign (enum machine_mode mode, rtx *operands)
1844 {
1845   if (MEM_P (operands[1]))
1846     {
1847       rtx tmp;
1848
1849       if (register_operand (operands[0], mode))
1850         tmp = operands[0];
1851       else
1852         tmp = gen_reg_rtx (mode);
1853
1854       tilegx_expand_unaligned_load (tmp, operands[1], GET_MODE_BITSIZE (mode),
1855                                     0, true);
1856
1857       if (tmp != operands[0])
1858         emit_move_insn (operands[0], tmp);
1859     }
1860   else if (MEM_P (operands[0]))
1861     {
1862       if (!reg_or_0_operand (operands[1], mode))
1863         operands[1] = force_reg (mode, operands[1]);
1864
1865       tilegx_expand_unaligned_store (operands[0], operands[1],
1866                                      GET_MODE_BITSIZE (mode), 0);
1867     }
1868   else
1869     gcc_unreachable ();
1870
1871 }
1872
1873
1874 /* Implement the allocate_stack pattern (alloca).  */
1875 void
1876 tilegx_allocate_stack (rtx op0, rtx op1)
1877 {
1878   /* Technically the correct way to initialize chain_loc is with
1879    * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
1880    * sets the alias_set to that of a frame reference.  Some of our
1881    * tests rely on some unsafe assumption about when the chaining
1882    * update is done, we need to be conservative about reordering the
1883    * chaining instructions.
1884    */
1885   rtx fp_addr = gen_reg_rtx (Pmode);
1886   rtx fp_value = gen_reg_rtx (Pmode);
1887   rtx fp_loc;
1888
1889   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1890                                          GEN_INT (UNITS_PER_WORD)));
1891
1892   fp_loc = gen_frame_mem (Pmode, fp_addr);
1893
1894   emit_move_insn (fp_value, fp_loc);
1895
1896   op1 = force_reg (Pmode, op1);
1897
1898   emit_move_insn (stack_pointer_rtx,
1899                   gen_rtx_MINUS (Pmode, stack_pointer_rtx, op1));
1900
1901   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1902                                          GEN_INT (UNITS_PER_WORD)));
1903
1904   fp_loc = gen_frame_mem (Pmode, fp_addr);
1905
1906   emit_move_insn (fp_loc, fp_value);
1907
1908   emit_move_insn (op0, virtual_stack_dynamic_rtx);
1909 }
1910 \f
1911
1912
1913 /* Multiplies */
1914
1915
1916 /* Returns the insn_code in ENTRY.  */
1917 static enum insn_code
1918 tilegx_multiply_get_opcode (const struct tilegx_multiply_insn_seq_entry
1919                             *entry)
1920 {
1921   return tilegx_multiply_insn_seq_decode_opcode[entry->compressed_opcode];
1922 }
1923
1924
1925 /* Returns the length of the 'op' array.  */
1926 static int
1927 tilegx_multiply_get_num_ops (const struct tilegx_multiply_insn_seq *seq)
1928 {
1929   /* The array either uses all of its allocated slots or is terminated
1930      by a bogus opcode. Either way, the array size is the index of the
1931      last valid opcode plus one.  */
1932   int i;
1933   for (i = tilegx_multiply_insn_seq_MAX_OPERATIONS - 1; i >= 0; i--)
1934     if (tilegx_multiply_get_opcode (&seq->op[i]) != CODE_FOR_nothing)
1935       return i + 1;
1936
1937   /* An empty array is not allowed.  */
1938   gcc_unreachable ();
1939 }
1940
1941
1942 /* We precompute a number of expression trees for multiplying by
1943    constants.  This generates code for such an expression tree by
1944    walking through the nodes in the tree (which are conveniently
1945    pre-linearized) and emitting an instruction for each one.  */
1946 static void
1947 tilegx_expand_constant_multiply_given_sequence (rtx result, rtx src,
1948                                                 const struct
1949                                                 tilegx_multiply_insn_seq *seq)
1950 {
1951   int i;
1952   int num_ops;
1953
1954   /* Keep track of the subexpressions computed so far, so later
1955      instructions can refer to them.  We seed the array with zero and
1956      the value being multiplied.  */
1957   int num_subexprs = 2;
1958   rtx subexprs[tilegx_multiply_insn_seq_MAX_OPERATIONS + 2];
1959   subexprs[0] = const0_rtx;
1960   subexprs[1] = src;
1961
1962   /* Determine how many instructions we are going to generate.  */
1963   num_ops = tilegx_multiply_get_num_ops (seq);
1964   gcc_assert (num_ops > 0
1965               && num_ops <= tilegx_multiply_insn_seq_MAX_OPERATIONS);
1966
1967   for (i = 0; i < num_ops; i++)
1968     {
1969       const struct tilegx_multiply_insn_seq_entry *entry = &seq->op[i];
1970
1971       /* Figure out where to store the output of this instruction.  */
1972       const bool is_last_op = (i + 1 == num_ops);
1973       rtx out = is_last_op ? result : gen_reg_rtx (DImode);
1974
1975       enum insn_code opcode = tilegx_multiply_get_opcode (entry);
1976       if (opcode == CODE_FOR_ashldi3)
1977         {
1978           /* Handle shift by immediate. This is a special case because
1979              the meaning of the second operand is a constant shift
1980              count rather than an operand index.  */
1981
1982           /* Make sure the shift count is in range. Zero should not
1983              happen.  */
1984           const int shift_count = entry->rhs;
1985           gcc_assert (shift_count > 0 && shift_count < 64);
1986
1987           /* Emit the actual instruction.  */
1988           emit_insn (GEN_FCN (opcode)
1989                      (out, subexprs[entry->lhs],
1990                       gen_rtx_CONST_INT (DImode, shift_count)));
1991         }
1992       else
1993         {
1994           /* Handle a normal two-operand instruction, such as add or
1995              shl1add.  */
1996
1997           /* Make sure we are referring to a previously computed
1998              subexpression.  */
1999           gcc_assert (entry->rhs < num_subexprs);
2000
2001           /* Emit the actual instruction.  */
2002           emit_insn (GEN_FCN (opcode)
2003                      (out, subexprs[entry->lhs], subexprs[entry->rhs]));
2004         }
2005
2006       /* Record this subexpression for use by later expressions.  */
2007       subexprs[num_subexprs++] = out;
2008     }
2009 }
2010
2011
2012 /* bsearch helper function.  */
2013 static int
2014 tilegx_compare_multipliers (const void *key, const void *t)
2015 {
2016   long long delta =
2017     (*(const long long *) key
2018      - ((const struct tilegx_multiply_insn_seq *) t)->multiplier);
2019   return (delta < 0) ? -1 : (delta > 0);
2020 }
2021
2022
2023 /* Returns the tilegx_multiply_insn_seq for multiplier, or NULL if none
2024    exists.  */
2025 static const struct tilegx_multiply_insn_seq *
2026 tilegx_find_multiply_insn_seq_for_constant (long long multiplier)
2027 {
2028   return ((const struct tilegx_multiply_insn_seq *)
2029           bsearch (&multiplier, tilegx_multiply_insn_seq_table,
2030                    tilegx_multiply_insn_seq_table_size,
2031                    sizeof tilegx_multiply_insn_seq_table[0],
2032                    tilegx_compare_multipliers));
2033 }
2034
2035
2036 /* Try to a expand constant multiply in DImode by looking it up in a
2037    precompiled table.  OP0 is the result operand, OP1 is the source
2038    operand, and MULTIPLIER is the value of the constant.  Return true
2039    if it succeeds.  */
2040 static bool
2041 tilegx_expand_const_muldi (rtx op0, rtx op1, long long multiplier)
2042 {
2043   /* See if we have precomputed an efficient way to multiply by this
2044      constant.  */
2045   const struct tilegx_multiply_insn_seq *seq =
2046     tilegx_find_multiply_insn_seq_for_constant (multiplier);
2047   if (seq != NULL)
2048     {
2049       tilegx_expand_constant_multiply_given_sequence (op0, op1, seq);
2050       return true;
2051     }
2052   else
2053     return false;
2054 }
2055
2056 /* Expand the muldi pattern.  */
2057 bool
2058 tilegx_expand_muldi (rtx op0, rtx op1, rtx op2)
2059 {
2060   if (CONST_INT_P (op2))
2061     {
2062       HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op2), DImode);
2063       return tilegx_expand_const_muldi (op0, op1, n);
2064     }
2065   return false;
2066 }
2067
2068
2069 /* Expand a high multiply pattern in DImode.  RESULT, OP1, OP2 are the
2070    operands, and SIGN is true if it's a signed multiply, and false if
2071    it's an unsigned multiply.  */
2072 static void
2073 tilegx_expand_high_multiply (rtx result, rtx op1, rtx op2, bool sign)
2074 {
2075   rtx tmp0 = gen_reg_rtx (DImode);
2076   rtx tmp1 = gen_reg_rtx (DImode);
2077   rtx tmp2 = gen_reg_rtx (DImode);
2078   rtx tmp3 = gen_reg_rtx (DImode);
2079   rtx tmp4 = gen_reg_rtx (DImode);
2080   rtx tmp5 = gen_reg_rtx (DImode);
2081   rtx tmp6 = gen_reg_rtx (DImode);
2082   rtx tmp7 = gen_reg_rtx (DImode);
2083   rtx tmp8 = gen_reg_rtx (DImode);
2084   rtx tmp9 = gen_reg_rtx (DImode);
2085   rtx tmp10 = gen_reg_rtx (DImode);
2086   rtx tmp11 = gen_reg_rtx (DImode);
2087   rtx tmp12 = gen_reg_rtx (DImode);
2088   rtx tmp13 = gen_reg_rtx (DImode);
2089   rtx result_lo = gen_reg_rtx (DImode);
2090
2091   if (sign)
2092     {
2093       emit_insn (gen_insn_mul_hs_lu (tmp0, op1, op2));
2094       emit_insn (gen_insn_mul_hs_lu (tmp1, op2, op1));
2095       emit_insn (gen_insn_mul_lu_lu (tmp2, op1, op2));
2096       emit_insn (gen_insn_mul_hs_hs (tmp3, op1, op2));
2097     }
2098   else
2099     {
2100       emit_insn (gen_insn_mul_hu_lu (tmp0, op1, op2));
2101       emit_insn (gen_insn_mul_hu_lu (tmp1, op2, op1));
2102       emit_insn (gen_insn_mul_lu_lu (tmp2, op1, op2));
2103       emit_insn (gen_insn_mul_hu_hu (tmp3, op1, op2));
2104     }
2105
2106   emit_move_insn (tmp4, (gen_rtx_ASHIFT (DImode, tmp0, GEN_INT (32))));
2107
2108   emit_move_insn (tmp5, (gen_rtx_ASHIFT (DImode, tmp1, GEN_INT (32))));
2109
2110   emit_move_insn (tmp6, (gen_rtx_PLUS (DImode, tmp4, tmp5)));
2111   emit_move_insn (result_lo, (gen_rtx_PLUS (DImode, tmp2, tmp6)));
2112
2113   emit_move_insn (tmp7, gen_rtx_LTU (DImode, tmp6, tmp4));
2114   emit_move_insn (tmp8, gen_rtx_LTU (DImode, result_lo, tmp2));
2115
2116   if (sign)
2117     {
2118       emit_move_insn (tmp9, (gen_rtx_ASHIFTRT (DImode, tmp0, GEN_INT (32))));
2119       emit_move_insn (tmp10, (gen_rtx_ASHIFTRT (DImode, tmp1, GEN_INT (32))));
2120     }
2121   else
2122     {
2123       emit_move_insn (tmp9, (gen_rtx_LSHIFTRT (DImode, tmp0, GEN_INT (32))));
2124       emit_move_insn (tmp10, (gen_rtx_LSHIFTRT (DImode, tmp1, GEN_INT (32))));
2125     }
2126
2127   emit_move_insn (tmp11, (gen_rtx_PLUS (DImode, tmp3, tmp7)));
2128   emit_move_insn (tmp12, (gen_rtx_PLUS (DImode, tmp8, tmp9)));
2129   emit_move_insn (tmp13, (gen_rtx_PLUS (DImode, tmp11, tmp12)));
2130   emit_move_insn (result, (gen_rtx_PLUS (DImode, tmp13, tmp10)));
2131 }
2132
2133
2134 /* Implement smuldi3_highpart.  */
2135 void
2136 tilegx_expand_smuldi3_highpart (rtx op0, rtx op1, rtx op2)
2137 {
2138   tilegx_expand_high_multiply (op0, op1, op2, true);
2139 }
2140
2141
2142 /* Implement umuldi3_highpart.  */
2143 void
2144 tilegx_expand_umuldi3_highpart (rtx op0, rtx op1, rtx op2)
2145 {
2146   tilegx_expand_high_multiply (op0, op1, op2, false);
2147 }
2148 \f
2149
2150
2151 /* Compare and branches  */
2152
2153 /* Produce the rtx yielding a bool for a floating point
2154    comparison.  */
2155 static bool
2156 tilegx_emit_fp_setcc (rtx res, enum rtx_code code, enum machine_mode mode,
2157                       rtx op0, rtx op1)
2158 {
2159   /* TODO: Certain compares again constants can be done using entirely
2160      integer operations. But you have to get the special cases right
2161      e.g. NaN, +0 == -0, etc.  */
2162
2163   rtx flags;
2164   int flag_index;
2165   rtx a = force_reg (DImode, gen_lowpart (DImode, op0));
2166   rtx b = force_reg (DImode, gen_lowpart (DImode, op1));
2167
2168   flags = gen_reg_rtx (DImode);
2169
2170   if (mode == SFmode)
2171     {
2172       emit_insn (gen_insn_fsingle_add1 (flags, a, b));
2173     }
2174   else
2175     {
2176       gcc_assert (mode == DFmode);
2177       emit_insn (gen_insn_fdouble_add_flags (flags, a, b));
2178     }
2179
2180   switch (code)
2181     {
2182     case EQ: flag_index = 30; break;
2183     case NE: flag_index = 31; break;
2184     case LE: flag_index = 27; break;
2185     case LT: flag_index = 26; break;
2186     case GE: flag_index = 29; break;
2187     case GT: flag_index = 28; break;
2188     default: gcc_unreachable ();
2189     }
2190
2191   gcc_assert (GET_MODE (res) == DImode);
2192   emit_move_insn (res, gen_rtx_ZERO_EXTRACT (DImode, flags, GEN_INT (1),
2193                                              GEN_INT (flag_index)));
2194   return true;
2195 }
2196
2197
2198 /* Certain simplifications can be done to make invalid setcc
2199    operations valid.  Return the final comparison, or NULL if we can't
2200    work.  */
2201 static bool
2202 tilegx_emit_setcc_internal (rtx res, enum rtx_code code, rtx op0, rtx op1,
2203                             enum machine_mode cmp_mode)
2204 {
2205   rtx tmp;
2206   bool swap = false;
2207
2208   if (cmp_mode == SFmode || cmp_mode == DFmode)
2209     return tilegx_emit_fp_setcc (res, code, cmp_mode, op0, op1);
2210
2211   /* The general case: fold the comparison code to the types of
2212      compares that we have, choosing the branch as necessary.  */
2213
2214   switch (code)
2215     {
2216     case EQ:
2217     case NE:
2218     case LE:
2219     case LT:
2220     case LEU:
2221     case LTU:
2222       /* We have these compares.  */
2223       break;
2224
2225     case GE:
2226     case GT:
2227     case GEU:
2228     case GTU:
2229       /* We do not have these compares, so we reverse the
2230          operands.  */
2231       swap = true;
2232       break;
2233
2234     default:
2235       /* We should not have called this with any other code.  */
2236       gcc_unreachable ();
2237     }
2238
2239   if (swap)
2240     {
2241       code = swap_condition (code);
2242       tmp = op0, op0 = op1, op1 = tmp;
2243     }
2244
2245   if (!reg_or_0_operand (op0, cmp_mode))
2246     op0 = force_reg (cmp_mode, op0);
2247
2248   if (!CONST_INT_P (op1) && !register_operand (op1, cmp_mode))
2249     op1 = force_reg (cmp_mode, op1);
2250
2251   /* Return the setcc comparison.  */
2252   emit_insn (gen_rtx_SET (VOIDmode, res,
2253                           gen_rtx_fmt_ee (code, DImode, op0, op1)));
2254
2255   return true;
2256 }
2257
2258
2259 /* Implement cstore patterns.  */
2260 bool
2261 tilegx_emit_setcc (rtx operands[], enum machine_mode cmp_mode)
2262 {
2263   return
2264     tilegx_emit_setcc_internal (operands[0], GET_CODE (operands[1]),
2265                                 operands[2], operands[3], cmp_mode);
2266 }
2267
2268
2269 /* Return whether CODE is a signed comparison.  */
2270 static bool
2271 signed_compare_p (enum rtx_code code)
2272 {
2273   return (code == EQ || code == NE || code == LT || code == LE
2274           || code == GT || code == GE);
2275 }
2276
2277
2278 /* Generate the comparison for a DImode conditional branch.  */
2279 static rtx
2280 tilegx_emit_cc_test (enum rtx_code code, rtx op0, rtx op1,
2281                      enum machine_mode cmp_mode, bool eq_ne_only)
2282 {
2283   enum rtx_code branch_code;
2284   rtx temp;
2285
2286   if (cmp_mode == SFmode || cmp_mode == DFmode)
2287     {
2288       /* Compute a boolean saying whether the comparison is true.  */
2289       temp = gen_reg_rtx (DImode);
2290       tilegx_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
2291
2292       /* Test that flag.  */
2293       return gen_rtx_fmt_ee (NE, VOIDmode, temp, const0_rtx);
2294     }
2295
2296   /* Check for a compare against zero using a comparison we can do
2297      directly.  */
2298   if (op1 == const0_rtx
2299       && (code == EQ || code == NE
2300           || (!eq_ne_only && signed_compare_p (code))))
2301     {
2302       op0 = force_reg (cmp_mode, op0);
2303       return gen_rtx_fmt_ee (code, VOIDmode, op0, const0_rtx);
2304     }
2305
2306   /* The general case: fold the comparison code to the types of
2307      compares that we have, choosing the branch as necessary.  */
2308   switch (code)
2309     {
2310     case EQ:
2311     case LE:
2312     case LT:
2313     case LEU:
2314     case LTU:
2315       /* We have these compares.  */
2316       branch_code = NE;
2317       break;
2318
2319     case NE:
2320     case GE:
2321     case GT:
2322     case GEU:
2323     case GTU:
2324       /* These must be reversed (except NE, but let's
2325          canonicalize).  */
2326       code = reverse_condition (code);
2327       branch_code = EQ;
2328       break;
2329
2330     default:
2331       gcc_unreachable ();
2332     }
2333
2334   if (CONST_INT_P (op1) && (!satisfies_constraint_I (op1) || code == LEU))
2335     {
2336       HOST_WIDE_INT n = INTVAL (op1);
2337
2338       switch (code)
2339         {
2340         case EQ:
2341           /* Subtract off the value we want to compare against and see
2342              if we get zero.  This is cheaper than creating a constant
2343              in a register. Except that subtracting -128 is more
2344              expensive than seqi to -128, so we leave that alone.  */
2345           /* ??? Don't do this when comparing against symbols,
2346              otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
2347              0), which will be declared false out of hand (at least
2348              for non-weak).  */
2349           if (n != -128
2350               && add_operand (GEN_INT (-n), DImode)
2351               && !(symbolic_operand (op0, VOIDmode)
2352                    || (REG_P (op0) && REG_POINTER (op0))))
2353             {
2354               /* TODO: Use a SIMD add immediate to hit zero for tiled
2355                  constants in a single instruction.  */
2356               if (GET_MODE (op0) != DImode)
2357                 {
2358                   /* Convert to DImode so we can use addli.  Note that
2359                      this will not actually generate any code because
2360                      sign extension from SI -> DI is a no-op.  I don't
2361                      know if it's safe just to make a paradoxical
2362                      subreg here though.  */
2363                   rtx temp2 = gen_reg_rtx (DImode);
2364                   emit_insn (gen_extendsidi2 (temp2, op0));
2365                   op0 = temp2;
2366                 }
2367               else
2368                 {
2369                   op0 = force_reg (DImode, op0);
2370                 }
2371               temp = gen_reg_rtx (DImode);
2372               emit_move_insn (temp, gen_rtx_PLUS (DImode, op0, GEN_INT (-n)));
2373               return gen_rtx_fmt_ee (reverse_condition (branch_code),
2374                                      VOIDmode, temp, const0_rtx);
2375             }
2376           break;
2377
2378         case LEU:
2379           if (n == -1)
2380             break;
2381           /* FALLTHRU */
2382
2383         case LTU:
2384           /* Change ((unsigned)x < 0x1000) into !((int)x >> 12), etc.
2385              We use arithmetic shift right because it's a 3-wide op,
2386              while logical shift right is not.  */
2387           {
2388             int first = exact_log2 (code == LTU ? n : n + 1);
2389             if (first != -1)
2390               {
2391                 op0 = force_reg (cmp_mode, op0);
2392                 temp = gen_reg_rtx (cmp_mode);
2393                 emit_move_insn (temp,
2394                                 gen_rtx_ASHIFTRT (cmp_mode, op0,
2395                                                   GEN_INT (first)));
2396                 return gen_rtx_fmt_ee (reverse_condition (branch_code),
2397                                        VOIDmode, temp, const0_rtx);
2398               }
2399           }
2400           break;
2401
2402         default:
2403           break;
2404         }
2405     }
2406
2407   /* Compute a flag saying whether we should branch.  */
2408   temp = gen_reg_rtx (DImode);
2409   tilegx_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
2410
2411   /* Return the branch comparison.  */
2412   return gen_rtx_fmt_ee (branch_code, VOIDmode, temp, const0_rtx);
2413 }
2414
2415
2416 /* Generate the comparison for a conditional branch.  */
2417 void
2418 tilegx_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode)
2419 {
2420   rtx cmp_rtx =
2421     tilegx_emit_cc_test (GET_CODE (operands[0]), operands[1], operands[2],
2422                          cmp_mode, false);
2423   rtx branch_rtx = gen_rtx_SET (VOIDmode, pc_rtx,
2424                                 gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
2425                                                       gen_rtx_LABEL_REF
2426                                                       (VOIDmode,
2427                                                        operands[3]),
2428                                                       pc_rtx));
2429   emit_jump_insn (branch_rtx);
2430 }
2431
2432
2433 /* Implement the mov<mode>cc pattern.  */
2434 rtx
2435 tilegx_emit_conditional_move (rtx cmp)
2436 {
2437   return
2438     tilegx_emit_cc_test (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1),
2439                          GET_MODE (XEXP (cmp, 0)), true);
2440 }
2441
2442
2443 /* Return true if INSN is annotated with a REG_BR_PROB note that
2444    indicates it's a branch that's predicted taken.  */
2445 static bool
2446 cbranch_predicted_p (rtx insn)
2447 {
2448   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2449
2450   if (x)
2451     {
2452       int pred_val = INTVAL (XEXP (x, 0));
2453
2454       return pred_val >= REG_BR_PROB_BASE / 2;
2455     }
2456
2457   return false;
2458 }
2459
2460
2461 /* Output assembly code for a specific branch instruction, appending
2462    the branch prediction flag to the opcode if appropriate.  */
2463 static const char *
2464 tilegx_output_simple_cbranch_with_opcode (rtx insn, const char *opcode,
2465                                           int regop, bool reverse_predicted)
2466 {
2467   static char buf[64];
2468   sprintf (buf, "%s%s\t%%r%d, %%l0", opcode,
2469            (cbranch_predicted_p (insn) ^ reverse_predicted) ? "t" : "",
2470            regop);
2471   return buf;
2472 }
2473
2474
2475 /* Output assembly code for a specific branch instruction, appending
2476    the branch prediction flag to the opcode if appropriate.  */
2477 const char *
2478 tilegx_output_cbranch_with_opcode (rtx insn, rtx *operands,
2479                                    const char *opcode,
2480                                    const char *rev_opcode, int regop)
2481 {
2482   const char *branch_if_false;
2483   rtx taken, not_taken;
2484   bool is_simple_branch;
2485
2486   gcc_assert (LABEL_P (operands[0]));
2487
2488   is_simple_branch = true;
2489   if (INSN_ADDRESSES_SET_P ())
2490     {
2491       int from_addr = INSN_ADDRESSES (INSN_UID (insn));
2492       int to_addr = INSN_ADDRESSES (INSN_UID (operands[0]));
2493       int delta = to_addr - from_addr;
2494       is_simple_branch = IN_RANGE (delta, -524288, 524280);
2495     }
2496
2497   if (is_simple_branch)
2498     {
2499       /* Just a simple conditional branch.  */
2500       return
2501         tilegx_output_simple_cbranch_with_opcode (insn, opcode, regop, false);
2502     }
2503
2504   /* Generate a reversed branch around a direct jump.  This fallback
2505      does not use branch-likely instructions.  */
2506   not_taken = gen_label_rtx ();
2507   taken = operands[0];
2508
2509   /* Generate the reversed branch to NOT_TAKEN.  */
2510   operands[0] = not_taken;
2511   branch_if_false =
2512     tilegx_output_simple_cbranch_with_opcode (insn, rev_opcode, regop, true);
2513   output_asm_insn (branch_if_false, operands);
2514
2515   output_asm_insn ("j\t%l0", &taken);
2516
2517   /* Output NOT_TAKEN.  */
2518   targetm.asm_out.internal_label (asm_out_file, "L",
2519                                   CODE_LABEL_NUMBER (not_taken));
2520   return "";
2521 }
2522
2523
2524 /* Output assembly code for a conditional branch instruction.  */
2525 const char *
2526 tilegx_output_cbranch (rtx insn, rtx *operands, bool reversed)
2527 {
2528   enum rtx_code code = GET_CODE (operands[1]);
2529   const char *opcode;
2530   const char *rev_opcode;
2531
2532   if (reversed)
2533     code = reverse_condition (code);
2534
2535   switch (code)
2536     {
2537     case NE:
2538       opcode = "bnez";
2539       rev_opcode = "beqz";
2540       break;
2541     case EQ:
2542       opcode = "beqz";
2543       rev_opcode = "bnez";
2544       break;
2545     case GE:
2546       opcode = "bgez";
2547       rev_opcode = "bltz";
2548       break;
2549     case GT:
2550       opcode = "bgtz";
2551       rev_opcode = "blez";
2552       break;
2553     case LE:
2554       opcode = "blez";
2555       rev_opcode = "bgtz";
2556       break;
2557     case LT:
2558       opcode = "bltz";
2559       rev_opcode = "bgez";
2560       break;
2561     default:
2562       gcc_unreachable ();
2563     }
2564
2565   return tilegx_output_cbranch_with_opcode (insn, operands, opcode,
2566                                             rev_opcode, 2);
2567 }
2568
2569
2570 /* Implement the tablejump pattern.  */
2571 void
2572 tilegx_expand_tablejump (rtx op0, rtx op1)
2573 {
2574   if (flag_pic)
2575     {
2576       rtx temp = gen_reg_rtx (Pmode);
2577       rtx temp2 = gen_reg_rtx (Pmode);
2578
2579       compute_pcrel_address (temp, gen_rtx_LABEL_REF (Pmode, op1));
2580       emit_move_insn (temp2,
2581                       gen_rtx_PLUS (Pmode,
2582                                     convert_to_mode (Pmode, op0, false),
2583                                     temp));
2584       op0 = temp2;
2585     }
2586
2587   emit_jump_insn (gen_tablejump_aux (op0, op1));
2588 }
2589
2590
2591 /* Emit barrier before an atomic, as needed for the memory MODEL.  */
2592 void
2593 tilegx_pre_atomic_barrier (enum memmodel model)
2594 {
2595   switch (model)
2596     {
2597     case MEMMODEL_RELAXED:
2598     case MEMMODEL_CONSUME:
2599     case MEMMODEL_ACQUIRE:
2600       break;
2601     case MEMMODEL_RELEASE:
2602     case MEMMODEL_ACQ_REL:
2603     case MEMMODEL_SEQ_CST:
2604       emit_insn (gen_memory_barrier ());
2605       break;
2606     default:
2607       gcc_unreachable ();
2608     }
2609 }
2610
2611
2612 /* Emit barrier after an atomic, as needed for the memory MODEL.  */
2613 void
2614 tilegx_post_atomic_barrier (enum memmodel model)
2615 {
2616   switch (model)
2617     {
2618     case MEMMODEL_RELAXED:
2619     case MEMMODEL_CONSUME:
2620     case MEMMODEL_RELEASE:
2621       break;
2622     case MEMMODEL_ACQUIRE:
2623     case MEMMODEL_ACQ_REL:
2624     case MEMMODEL_SEQ_CST:
2625       emit_insn (gen_memory_barrier ());
2626       break;
2627     default:
2628       gcc_unreachable ();
2629     }
2630 }
2631
2632
2633
2634 /* Expand a builtin vector binary op, by calling gen function GEN with
2635    operands in the proper modes.  DEST is converted to DEST_MODE, and
2636    src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE.  */
2637 void
2638 tilegx_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
2639                                     enum machine_mode dest_mode,
2640                                     rtx dest,
2641                                     enum machine_mode src_mode,
2642                                     rtx src0, rtx src1, bool do_src1)
2643 {
2644   dest = gen_lowpart (dest_mode, dest);
2645
2646   if (src0 == const0_rtx)
2647     src0 = CONST0_RTX (src_mode);
2648   else
2649     src0 = gen_lowpart (src_mode, src0);
2650
2651   if (do_src1)
2652     {
2653       if (src1 == const0_rtx)
2654         src1 = CONST0_RTX (src_mode);
2655       else
2656         src1 = gen_lowpart (src_mode, src1);
2657     }
2658
2659   emit_insn ((*gen) (dest, src0, src1));
2660 }
2661 \f
2662
2663
2664 /* Intrinsics  */
2665
2666
2667 struct tile_builtin_info
2668 {
2669   enum insn_code icode;
2670   tree fndecl;
2671 };
2672
2673 static struct tile_builtin_info tilegx_builtin_info[TILEGX_BUILTIN_max] = {
2674   { CODE_FOR_adddi3,                    NULL }, /* add */
2675   { CODE_FOR_addsi3,                    NULL }, /* addx */
2676   { CODE_FOR_ssaddsi3,                  NULL }, /* addxsc */
2677   { CODE_FOR_anddi3,                    NULL }, /* and */
2678   { CODE_FOR_insn_bfexts,               NULL }, /* bfexts */
2679   { CODE_FOR_insn_bfextu,               NULL }, /* bfextu */
2680   { CODE_FOR_insn_bfins,                NULL }, /* bfins */
2681   { CODE_FOR_clzdi2,                    NULL }, /* clz */
2682   { CODE_FOR_insn_cmoveqz,              NULL }, /* cmoveqz */
2683   { CODE_FOR_insn_cmovnez,              NULL }, /* cmovnez */
2684   { CODE_FOR_insn_cmpeq_didi,           NULL }, /* cmpeq */
2685   { CODE_FOR_insn_cmpexch,              NULL }, /* cmpexch */
2686   { CODE_FOR_insn_cmpexch4,             NULL }, /* cmpexch4 */
2687   { CODE_FOR_insn_cmples_didi,          NULL }, /* cmples */
2688   { CODE_FOR_insn_cmpleu_didi,          NULL }, /* cmpleu */
2689   { CODE_FOR_insn_cmplts_didi,          NULL }, /* cmplts */
2690   { CODE_FOR_insn_cmpltu_didi,          NULL }, /* cmpltu */
2691   { CODE_FOR_insn_cmpne_didi,           NULL }, /* cmpne */
2692   { CODE_FOR_insn_cmul,                 NULL }, /* cmul */
2693   { CODE_FOR_insn_cmula,                NULL }, /* cmula */
2694   { CODE_FOR_insn_cmulaf,               NULL }, /* cmulaf */
2695   { CODE_FOR_insn_cmulf,                NULL }, /* cmulf */
2696   { CODE_FOR_insn_cmulfr,               NULL }, /* cmulfr */
2697   { CODE_FOR_insn_cmulh,                NULL }, /* cmulh */
2698   { CODE_FOR_insn_cmulhr,               NULL }, /* cmulhr */
2699   { CODE_FOR_insn_crc32_32,             NULL }, /* crc32_32 */
2700   { CODE_FOR_insn_crc32_8,              NULL }, /* crc32_8 */
2701   { CODE_FOR_ctzdi2,                    NULL }, /* ctz */
2702   { CODE_FOR_insn_dblalign,             NULL }, /* dblalign */
2703   { CODE_FOR_insn_dblalign2,            NULL }, /* dblalign2 */
2704   { CODE_FOR_insn_dblalign4,            NULL }, /* dblalign4 */
2705   { CODE_FOR_insn_dblalign6,            NULL }, /* dblalign6 */
2706   { CODE_FOR_insn_drain,                NULL }, /* drain */
2707   { CODE_FOR_insn_dtlbpr,               NULL }, /* dtlbpr */
2708   { CODE_FOR_insn_exch,                 NULL }, /* exch */
2709   { CODE_FOR_insn_exch4,                NULL }, /* exch4 */
2710   { CODE_FOR_insn_fdouble_add_flags,    NULL }, /* fdouble_add_flags */
2711   { CODE_FOR_insn_fdouble_addsub,       NULL }, /* fdouble_addsub */
2712   { CODE_FOR_insn_fdouble_mul_flags,    NULL }, /* fdouble_mul_flags */
2713   { CODE_FOR_insn_fdouble_pack1,        NULL }, /* fdouble_pack1 */
2714   { CODE_FOR_insn_fdouble_pack2,        NULL }, /* fdouble_pack2 */
2715   { CODE_FOR_insn_fdouble_sub_flags,    NULL }, /* fdouble_sub_flags */
2716   { CODE_FOR_insn_fdouble_unpack_max,   NULL }, /* fdouble_unpack_max */
2717   { CODE_FOR_insn_fdouble_unpack_min,   NULL }, /* fdouble_unpack_min */
2718   { CODE_FOR_insn_fetchadd,             NULL }, /* fetchadd */
2719   { CODE_FOR_insn_fetchadd4,            NULL }, /* fetchadd4 */
2720   { CODE_FOR_insn_fetchaddgez,          NULL }, /* fetchaddgez */
2721   { CODE_FOR_insn_fetchaddgez4,         NULL }, /* fetchaddgez4 */
2722   { CODE_FOR_insn_fetchand,             NULL }, /* fetchand */
2723   { CODE_FOR_insn_fetchand4,            NULL }, /* fetchand4 */
2724   { CODE_FOR_insn_fetchor,              NULL }, /* fetchor */
2725   { CODE_FOR_insn_fetchor4,             NULL }, /* fetchor4 */
2726   { CODE_FOR_insn_finv,                 NULL }, /* finv */
2727   { CODE_FOR_insn_flush,                NULL }, /* flush */
2728   { CODE_FOR_insn_flushwb,              NULL }, /* flushwb */
2729   { CODE_FOR_insn_fnop,                 NULL }, /* fnop */
2730   { CODE_FOR_insn_fsingle_add1,         NULL }, /* fsingle_add1 */
2731   { CODE_FOR_insn_fsingle_addsub2,      NULL }, /* fsingle_addsub2 */
2732   { CODE_FOR_insn_fsingle_mul1,         NULL }, /* fsingle_mul1 */
2733   { CODE_FOR_insn_fsingle_mul2,         NULL }, /* fsingle_mul2 */
2734   { CODE_FOR_insn_fsingle_pack1,        NULL }, /* fsingle_pack1 */
2735   { CODE_FOR_insn_fsingle_pack2,        NULL }, /* fsingle_pack2 */
2736   { CODE_FOR_insn_fsingle_sub1,         NULL }, /* fsingle_sub1 */
2737   { CODE_FOR_insn_icoh,                 NULL }, /* icoh */
2738   { CODE_FOR_insn_ill,                  NULL }, /* ill */
2739   { CODE_FOR_insn_info,                 NULL }, /* info */
2740   { CODE_FOR_insn_infol,                NULL }, /* infol */
2741   { CODE_FOR_insn_inv,                  NULL }, /* inv */
2742   { CODE_FOR_insn_ld,                   NULL }, /* ld */
2743   { CODE_FOR_insn_ld1s,                 NULL }, /* ld1s */
2744   { CODE_FOR_insn_ld1u,                 NULL }, /* ld1u */
2745   { CODE_FOR_insn_ld2s,                 NULL }, /* ld2s */
2746   { CODE_FOR_insn_ld2u,                 NULL }, /* ld2u */
2747   { CODE_FOR_insn_ld4s,                 NULL }, /* ld4s */
2748   { CODE_FOR_insn_ld4u,                 NULL }, /* ld4u */
2749   { CODE_FOR_insn_ldna,                 NULL }, /* ldna */
2750   { CODE_FOR_insn_ldnt,                 NULL }, /* ldnt */
2751   { CODE_FOR_insn_ldnt1s,               NULL }, /* ldnt1s */
2752   { CODE_FOR_insn_ldnt1u,               NULL }, /* ldnt1u */
2753   { CODE_FOR_insn_ldnt2s,               NULL }, /* ldnt2s */
2754   { CODE_FOR_insn_ldnt2u,               NULL }, /* ldnt2u */
2755   { CODE_FOR_insn_ldnt4s,               NULL }, /* ldnt4s */
2756   { CODE_FOR_insn_ldnt4u,               NULL }, /* ldnt4u */
2757   { CODE_FOR_insn_ld_L2,                NULL }, /* ld_L2 */
2758   { CODE_FOR_insn_ld1s_L2,              NULL }, /* ld1s_L2 */
2759   { CODE_FOR_insn_ld1u_L2,              NULL }, /* ld1u_L2 */
2760   { CODE_FOR_insn_ld2s_L2,              NULL }, /* ld2s_L2 */
2761   { CODE_FOR_insn_ld2u_L2,              NULL }, /* ld2u_L2 */
2762   { CODE_FOR_insn_ld4s_L2,              NULL }, /* ld4s_L2 */
2763   { CODE_FOR_insn_ld4u_L2,              NULL }, /* ld4u_L2 */
2764   { CODE_FOR_insn_ldna_L2,              NULL }, /* ldna_L2 */
2765   { CODE_FOR_insn_ldnt_L2,              NULL }, /* ldnt_L2 */
2766   { CODE_FOR_insn_ldnt1s_L2,            NULL }, /* ldnt1s_L2 */
2767   { CODE_FOR_insn_ldnt1u_L2,            NULL }, /* ldnt1u_L2 */
2768   { CODE_FOR_insn_ldnt2s_L2,            NULL }, /* ldnt2s_L2 */
2769   { CODE_FOR_insn_ldnt2u_L2,            NULL }, /* ldnt2u_L2 */
2770   { CODE_FOR_insn_ldnt4s_L2,            NULL }, /* ldnt4s_L2 */
2771   { CODE_FOR_insn_ldnt4u_L2,            NULL }, /* ldnt4u_L2 */
2772   { CODE_FOR_insn_ld_miss,              NULL }, /* ld_miss */
2773   { CODE_FOR_insn_ld1s_miss,            NULL }, /* ld1s_miss */
2774   { CODE_FOR_insn_ld1u_miss,            NULL }, /* ld1u_miss */
2775   { CODE_FOR_insn_ld2s_miss,            NULL }, /* ld2s_miss */
2776   { CODE_FOR_insn_ld2u_miss,            NULL }, /* ld2u_miss */
2777   { CODE_FOR_insn_ld4s_miss,            NULL }, /* ld4s_miss */
2778   { CODE_FOR_insn_ld4u_miss,            NULL }, /* ld4u_miss */
2779   { CODE_FOR_insn_ldna_miss,            NULL }, /* ldna_miss */
2780   { CODE_FOR_insn_ldnt_miss,            NULL }, /* ldnt_miss */
2781   { CODE_FOR_insn_ldnt1s_miss,          NULL }, /* ldnt1s_miss */
2782   { CODE_FOR_insn_ldnt1u_miss,          NULL }, /* ldnt1u_miss */
2783   { CODE_FOR_insn_ldnt2s_miss,          NULL }, /* ldnt2s_miss */
2784   { CODE_FOR_insn_ldnt2u_miss,          NULL }, /* ldnt2u_miss */
2785   { CODE_FOR_insn_ldnt4s_miss,          NULL }, /* ldnt4s_miss */
2786   { CODE_FOR_insn_ldnt4u_miss,          NULL }, /* ldnt4u_miss */
2787   { CODE_FOR_insn_lnk,                  NULL }, /* lnk */
2788   { CODE_FOR_memory_barrier,            NULL }, /* mf */
2789   { CODE_FOR_insn_mfspr,                NULL }, /* mfspr */
2790   { CODE_FOR_insn_mm,                   NULL }, /* mm */
2791   { CODE_FOR_insn_mnz,                  NULL }, /* mnz */
2792   { CODE_FOR_movdi,                     NULL }, /* move */
2793   { CODE_FOR_insn_mtspr,                NULL }, /* mtspr */
2794   { CODE_FOR_insn_mul_hs_hs,            NULL }, /* mul_hs_hs */
2795   { CODE_FOR_insn_mul_hs_hu,            NULL }, /* mul_hs_hu */
2796   { CODE_FOR_insn_mul_hs_ls,            NULL }, /* mul_hs_ls */
2797   { CODE_FOR_insn_mul_hs_lu,            NULL }, /* mul_hs_lu */
2798   { CODE_FOR_insn_mul_hu_hu,            NULL }, /* mul_hu_hu */
2799   { CODE_FOR_insn_mul_hu_ls,            NULL }, /* mul_hu_ls */
2800   { CODE_FOR_insn_mul_hu_lu,            NULL }, /* mul_hu_lu */
2801   { CODE_FOR_insn_mul_ls_ls,            NULL }, /* mul_ls_ls */
2802   { CODE_FOR_insn_mul_ls_lu,            NULL }, /* mul_ls_lu */
2803   { CODE_FOR_insn_mul_lu_lu,            NULL }, /* mul_lu_lu */
2804   { CODE_FOR_insn_mula_hs_hs,           NULL }, /* mula_hs_hs */
2805   { CODE_FOR_insn_mula_hs_hu,           NULL }, /* mula_hs_hu */
2806   { CODE_FOR_insn_mula_hs_ls,           NULL }, /* mula_hs_ls */
2807   { CODE_FOR_insn_mula_hs_lu,           NULL }, /* mula_hs_lu */
2808   { CODE_FOR_insn_mula_hu_hu,           NULL }, /* mula_hu_hu */
2809   { CODE_FOR_insn_mula_hu_ls,           NULL }, /* mula_hu_ls */
2810   { CODE_FOR_insn_mula_hu_lu,           NULL }, /* mula_hu_lu */
2811   { CODE_FOR_insn_mula_ls_ls,           NULL }, /* mula_ls_ls */
2812   { CODE_FOR_insn_mula_ls_lu,           NULL }, /* mula_ls_lu */
2813   { CODE_FOR_insn_mula_lu_lu,           NULL }, /* mula_lu_lu */
2814   { CODE_FOR_insn_mulax,                NULL }, /* mulax */
2815   { CODE_FOR_mulsi3,                    NULL }, /* mulx */
2816   { CODE_FOR_insn_mz,                   NULL }, /* mz */
2817   { CODE_FOR_insn_nap,                  NULL }, /* nap */
2818   { CODE_FOR_nop,                       NULL }, /* nop */
2819   { CODE_FOR_insn_nor_di,               NULL }, /* nor */
2820   { CODE_FOR_iordi3,                    NULL }, /* or */
2821   { CODE_FOR_popcountdi2,               NULL }, /* pcnt */
2822   { CODE_FOR_insn_prefetch_l1,          NULL }, /* prefetch_l1 */
2823   { CODE_FOR_insn_prefetch_l1_fault,    NULL }, /* prefetch_l1_fault */
2824   { CODE_FOR_insn_prefetch_l2,          NULL }, /* prefetch_l2 */
2825   { CODE_FOR_insn_prefetch_l2_fault,    NULL }, /* prefetch_l2_fault */
2826   { CODE_FOR_insn_prefetch_l3,          NULL }, /* prefetch_l3 */
2827   { CODE_FOR_insn_prefetch_l3_fault,    NULL }, /* prefetch_l3_fault */
2828   { CODE_FOR_insn_revbits,              NULL }, /* revbits */
2829   { CODE_FOR_bswapdi2,                  NULL }, /* revbytes */
2830   { CODE_FOR_rotldi3,                   NULL }, /* rotl */
2831   { CODE_FOR_ashldi3,                   NULL }, /* shl */
2832   { CODE_FOR_insn_shl16insli,           NULL }, /* shl16insli */
2833   { CODE_FOR_insn_shl1add,              NULL }, /* shl1add */
2834   { CODE_FOR_insn_shl1addx,             NULL }, /* shl1addx */
2835   { CODE_FOR_insn_shl2add,              NULL }, /* shl2add */
2836   { CODE_FOR_insn_shl2addx,             NULL }, /* shl2addx */
2837   { CODE_FOR_insn_shl3add,              NULL }, /* shl3add */
2838   { CODE_FOR_insn_shl3addx,             NULL }, /* shl3addx */
2839   { CODE_FOR_ashlsi3,                   NULL }, /* shlx */
2840   { CODE_FOR_ashrdi3,                   NULL }, /* shrs */
2841   { CODE_FOR_lshrdi3,                   NULL }, /* shru */
2842   { CODE_FOR_lshrsi3,                   NULL }, /* shrux */
2843   { CODE_FOR_insn_shufflebytes,         NULL }, /* shufflebytes */
2844   { CODE_FOR_insn_st,                   NULL }, /* st */
2845   { CODE_FOR_insn_st1,                  NULL }, /* st1 */
2846   { CODE_FOR_insn_st2,                  NULL }, /* st2 */
2847   { CODE_FOR_insn_st4,                  NULL }, /* st4 */
2848   { CODE_FOR_insn_stnt,                 NULL }, /* stnt */
2849   { CODE_FOR_insn_stnt1,                NULL }, /* stnt1 */
2850   { CODE_FOR_insn_stnt2,                NULL }, /* stnt2 */
2851   { CODE_FOR_insn_stnt4,                NULL }, /* stnt4 */
2852   { CODE_FOR_subdi3,                    NULL }, /* sub */
2853   { CODE_FOR_subsi3,                    NULL }, /* subx */
2854   { CODE_FOR_sssubsi3,                  NULL }, /* subxsc */
2855   { CODE_FOR_insn_tblidxb0,             NULL }, /* tblidxb0 */
2856   { CODE_FOR_insn_tblidxb1,             NULL }, /* tblidxb1 */
2857   { CODE_FOR_insn_tblidxb2,             NULL }, /* tblidxb2 */
2858   { CODE_FOR_insn_tblidxb3,             NULL }, /* tblidxb3 */
2859   { CODE_FOR_insn_v1add,                NULL }, /* v1add */
2860   { CODE_FOR_insn_v1addi,               NULL }, /* v1addi */
2861   { CODE_FOR_insn_v1adduc,              NULL }, /* v1adduc */
2862   { CODE_FOR_insn_v1adiffu,             NULL }, /* v1adiffu */
2863   { CODE_FOR_insn_v1avgu,               NULL }, /* v1avgu */
2864   { CODE_FOR_insn_v1cmpeq,              NULL }, /* v1cmpeq */
2865   { CODE_FOR_insn_v1cmpeqi,             NULL }, /* v1cmpeqi */
2866   { CODE_FOR_insn_v1cmples,             NULL }, /* v1cmples */
2867   { CODE_FOR_insn_v1cmpleu,             NULL }, /* v1cmpleu */
2868   { CODE_FOR_insn_v1cmplts,             NULL }, /* v1cmplts */
2869   { CODE_FOR_insn_v1cmpltsi,            NULL }, /* v1cmpltsi */
2870   { CODE_FOR_insn_v1cmpltu,             NULL }, /* v1cmpltu */
2871   { CODE_FOR_insn_v1cmpltui,            NULL }, /* v1cmpltui */
2872   { CODE_FOR_insn_v1cmpne,              NULL }, /* v1cmpne */
2873   { CODE_FOR_insn_v1ddotpu,             NULL }, /* v1ddotpu */
2874   { CODE_FOR_insn_v1ddotpua,            NULL }, /* v1ddotpua */
2875   { CODE_FOR_insn_v1ddotpus,            NULL }, /* v1ddotpus */
2876   { CODE_FOR_insn_v1ddotpusa,           NULL }, /* v1ddotpusa */
2877   { CODE_FOR_insn_v1dotp,               NULL }, /* v1dotp */
2878   { CODE_FOR_insn_v1dotpa,              NULL }, /* v1dotpa */
2879   { CODE_FOR_insn_v1dotpu,              NULL }, /* v1dotpu */
2880   { CODE_FOR_insn_v1dotpua,             NULL }, /* v1dotpua */
2881   { CODE_FOR_insn_v1dotpus,             NULL }, /* v1dotpus */
2882   { CODE_FOR_insn_v1dotpusa,            NULL }, /* v1dotpusa */
2883   { CODE_FOR_insn_v1int_h,              NULL }, /* v1int_h */
2884   { CODE_FOR_insn_v1int_l,              NULL }, /* v1int_l */
2885   { CODE_FOR_insn_v1maxu,               NULL }, /* v1maxu */
2886   { CODE_FOR_insn_v1maxui,              NULL }, /* v1maxui */
2887   { CODE_FOR_insn_v1minu,               NULL }, /* v1minu */
2888   { CODE_FOR_insn_v1minui,              NULL }, /* v1minui */
2889   { CODE_FOR_insn_v1mnz,                NULL }, /* v1mnz */
2890   { CODE_FOR_insn_v1multu,              NULL }, /* v1multu */
2891   { CODE_FOR_insn_v1mulu,               NULL }, /* v1mulu */
2892   { CODE_FOR_insn_v1mulus,              NULL }, /* v1mulus */
2893   { CODE_FOR_insn_v1mz,                 NULL }, /* v1mz */
2894   { CODE_FOR_insn_v1sadau,              NULL }, /* v1sadau */
2895   { CODE_FOR_insn_v1sadu,               NULL }, /* v1sadu */
2896   { CODE_FOR_insn_v1shl,                NULL }, /* v1shl */
2897   { CODE_FOR_insn_v1shl,                NULL }, /* v1shli */
2898   { CODE_FOR_insn_v1shrs,               NULL }, /* v1shrs */
2899   { CODE_FOR_insn_v1shrs,               NULL }, /* v1shrsi */
2900   { CODE_FOR_insn_v1shru,               NULL }, /* v1shru */
2901   { CODE_FOR_insn_v1shru,               NULL }, /* v1shrui */
2902   { CODE_FOR_insn_v1sub,                NULL }, /* v1sub */
2903   { CODE_FOR_insn_v1subuc,              NULL }, /* v1subuc */
2904   { CODE_FOR_insn_v2add,                NULL }, /* v2add */
2905   { CODE_FOR_insn_v2addi,               NULL }, /* v2addi */
2906   { CODE_FOR_insn_v2addsc,              NULL }, /* v2addsc */
2907   { CODE_FOR_insn_v2adiffs,             NULL }, /* v2adiffs */
2908   { CODE_FOR_insn_v2avgs,               NULL }, /* v2avgs */
2909   { CODE_FOR_insn_v2cmpeq,              NULL }, /* v2cmpeq */
2910   { CODE_FOR_insn_v2cmpeqi,             NULL }, /* v2cmpeqi */
2911   { CODE_FOR_insn_v2cmples,             NULL }, /* v2cmples */
2912   { CODE_FOR_insn_v2cmpleu,             NULL }, /* v2cmpleu */
2913   { CODE_FOR_insn_v2cmplts,             NULL }, /* v2cmplts */
2914   { CODE_FOR_insn_v2cmpltsi,            NULL }, /* v2cmpltsi */
2915   { CODE_FOR_insn_v2cmpltu,             NULL }, /* v2cmpltu */
2916   { CODE_FOR_insn_v2cmpltui,            NULL }, /* v2cmpltui */
2917   { CODE_FOR_insn_v2cmpne,              NULL }, /* v2cmpne */
2918   { CODE_FOR_insn_v2dotp,               NULL }, /* v2dotp */
2919   { CODE_FOR_insn_v2dotpa,              NULL }, /* v2dotpa */
2920   { CODE_FOR_insn_v2int_h,              NULL }, /* v2int_h */
2921   { CODE_FOR_insn_v2int_l,              NULL }, /* v2int_l */
2922   { CODE_FOR_insn_v2maxs,               NULL }, /* v2maxs */
2923   { CODE_FOR_insn_v2maxsi,              NULL }, /* v2maxsi */
2924   { CODE_FOR_insn_v2mins,               NULL }, /* v2mins */
2925   { CODE_FOR_insn_v2minsi,              NULL }, /* v2minsi */
2926   { CODE_FOR_insn_v2mnz,                NULL }, /* v2mnz */
2927   { CODE_FOR_insn_v2mulfsc,             NULL }, /* v2mulfsc */
2928   { CODE_FOR_insn_v2muls,               NULL }, /* v2muls */
2929   { CODE_FOR_insn_v2mults,              NULL }, /* v2mults */
2930   { CODE_FOR_insn_v2mz,                 NULL }, /* v2mz */
2931   { CODE_FOR_insn_v2packh,              NULL }, /* v2packh */
2932   { CODE_FOR_insn_v2packl,              NULL }, /* v2packl */
2933   { CODE_FOR_insn_v2packuc,             NULL }, /* v2packuc */
2934   { CODE_FOR_insn_v2sadas,              NULL }, /* v2sadas */
2935   { CODE_FOR_insn_v2sadau,              NULL }, /* v2sadau */
2936   { CODE_FOR_insn_v2sads,               NULL }, /* v2sads */
2937   { CODE_FOR_insn_v2sadu,               NULL }, /* v2sadu */
2938   { CODE_FOR_insn_v2shl,                NULL }, /* v2shl */
2939   { CODE_FOR_insn_v2shl,                NULL }, /* v2shli */
2940   { CODE_FOR_insn_v2shlsc,              NULL }, /* v2shlsc */
2941   { CODE_FOR_insn_v2shrs,               NULL }, /* v2shrs */
2942   { CODE_FOR_insn_v2shrs,               NULL }, /* v2shrsi */
2943   { CODE_FOR_insn_v2shru,               NULL }, /* v2shru */
2944   { CODE_FOR_insn_v2shru,               NULL }, /* v2shrui */
2945   { CODE_FOR_insn_v2sub,                NULL }, /* v2sub */
2946   { CODE_FOR_insn_v2subsc,              NULL }, /* v2subsc */
2947   { CODE_FOR_insn_v4add,                NULL }, /* v4add */
2948   { CODE_FOR_insn_v4addsc,              NULL }, /* v4addsc */
2949   { CODE_FOR_insn_v4int_h,              NULL }, /* v4int_h */
2950   { CODE_FOR_insn_v4int_l,              NULL }, /* v4int_l */
2951   { CODE_FOR_insn_v4packsc,             NULL }, /* v4packsc */
2952   { CODE_FOR_insn_v4shl,                NULL }, /* v4shl */
2953   { CODE_FOR_insn_v4shlsc,              NULL }, /* v4shlsc */
2954   { CODE_FOR_insn_v4shrs,               NULL }, /* v4shrs */
2955   { CODE_FOR_insn_v4shru,               NULL }, /* v4shru */
2956   { CODE_FOR_insn_v4sub,                NULL }, /* v4sub */
2957   { CODE_FOR_insn_v4subsc,              NULL }, /* v4subsc */
2958   { CODE_FOR_insn_wh64,                 NULL }, /* wh64 */
2959   { CODE_FOR_xordi3,                    NULL }, /* xor */
2960   { CODE_FOR_tilegx_network_barrier,    NULL }, /* network_barrier */
2961   { CODE_FOR_tilegx_idn0_receive,       NULL }, /* idn0_receive */
2962   { CODE_FOR_tilegx_idn1_receive,       NULL }, /* idn1_receive */
2963   { CODE_FOR_tilegx_idn_send,           NULL }, /* idn_send */
2964   { CODE_FOR_tilegx_udn0_receive,       NULL }, /* udn0_receive */
2965   { CODE_FOR_tilegx_udn1_receive,       NULL }, /* udn1_receive */
2966   { CODE_FOR_tilegx_udn2_receive,       NULL }, /* udn2_receive */
2967   { CODE_FOR_tilegx_udn3_receive,       NULL }, /* udn3_receive */
2968   { CODE_FOR_tilegx_udn_send,           NULL }, /* udn_send */
2969 };
2970
2971
2972 struct tilegx_builtin_def
2973 {
2974   const char *name;
2975   enum tilegx_builtin code;
2976   bool is_const;
2977   /* The first character is the return type.  Subsequent characters
2978      are the argument types. See char_to_type.  */
2979   const char *type;
2980 };
2981
2982
2983 static const struct tilegx_builtin_def tilegx_builtins[] = {
2984   { "__insn_add",                TILEGX_INSN_ADD,                true,  "lll"  },
2985   { "__insn_addi",               TILEGX_INSN_ADD,                true,  "lll"  },
2986   { "__insn_addli",              TILEGX_INSN_ADD,                true,  "lll"  },
2987   { "__insn_addx",               TILEGX_INSN_ADDX,               true,  "iii"  },
2988   { "__insn_addxi",              TILEGX_INSN_ADDX,               true,  "iii"  },
2989   { "__insn_addxli",             TILEGX_INSN_ADDX,               true,  "iii"  },
2990   { "__insn_addxsc",             TILEGX_INSN_ADDXSC,             true,  "iii"  },
2991   { "__insn_and",                TILEGX_INSN_AND,                true,  "lll"  },
2992   { "__insn_andi",               TILEGX_INSN_AND,                true,  "lll"  },
2993   { "__insn_bfexts",             TILEGX_INSN_BFEXTS,             true,  "llll" },
2994   { "__insn_bfextu",             TILEGX_INSN_BFEXTU,             true,  "llll" },
2995   { "__insn_bfins",              TILEGX_INSN_BFINS,              true,  "lllll"},
2996   { "__insn_clz",                TILEGX_INSN_CLZ,                true,  "ll"   },
2997   { "__insn_cmoveqz",            TILEGX_INSN_CMOVEQZ,            true,  "llll" },
2998   { "__insn_cmovnez",            TILEGX_INSN_CMOVNEZ,            true,  "llll" },
2999   { "__insn_cmpeq",              TILEGX_INSN_CMPEQ,              true,  "lll"  },
3000   { "__insn_cmpeqi",             TILEGX_INSN_CMPEQ,              true,  "lll"  },
3001   { "__insn_cmpexch",            TILEGX_INSN_CMPEXCH,            false, "lpl"  },
3002   { "__insn_cmpexch4",           TILEGX_INSN_CMPEXCH4,           false, "ipi"  },
3003   { "__insn_cmples",             TILEGX_INSN_CMPLES,             true,  "lll"  },
3004   { "__insn_cmpleu",             TILEGX_INSN_CMPLEU,             true,  "lll"  },
3005   { "__insn_cmplts",             TILEGX_INSN_CMPLTS,             true,  "lll"  },
3006   { "__insn_cmpltsi",            TILEGX_INSN_CMPLTS,             true,  "lll"  },
3007   { "__insn_cmpltu",             TILEGX_INSN_CMPLTU,             true,  "lll"  },
3008   { "__insn_cmpltui",            TILEGX_INSN_CMPLTU,             true,  "lll"  },
3009   { "__insn_cmpne",              TILEGX_INSN_CMPNE,              true,  "lll"  },
3010   { "__insn_cmul",               TILEGX_INSN_CMUL,               true,  "lll"  },
3011   { "__insn_cmula",              TILEGX_INSN_CMULA,              true,  "llll" },
3012   { "__insn_cmulaf",             TILEGX_INSN_CMULAF,             true,  "llll" },
3013   { "__insn_cmulf",              TILEGX_INSN_CMULF,              true,  "lll"  },
3014   { "__insn_cmulfr",             TILEGX_INSN_CMULFR,             true,  "lll"  },
3015   { "__insn_cmulh",              TILEGX_INSN_CMULH,              true,  "lll"  },
3016   { "__insn_cmulhr",             TILEGX_INSN_CMULHR,             true,  "lll"  },
3017   { "__insn_crc32_32",           TILEGX_INSN_CRC32_32,           true,  "lll"  },
3018   { "__insn_crc32_8",            TILEGX_INSN_CRC32_8,            true,  "lll"  },
3019   { "__insn_ctz",                TILEGX_INSN_CTZ,                true,  "ll"   },
3020   { "__insn_dblalign",           TILEGX_INSN_DBLALIGN,           true,  "lllk" },
3021   { "__insn_dblalign2",          TILEGX_INSN_DBLALIGN2,          true,  "lll"  },
3022   { "__insn_dblalign4",          TILEGX_INSN_DBLALIGN4,          true,  "lll"  },
3023   { "__insn_dblalign6",          TILEGX_INSN_DBLALIGN6,          true,  "lll"  },
3024   { "__insn_drain",              TILEGX_INSN_DRAIN,              false, "v"    },
3025   { "__insn_dtlbpr",             TILEGX_INSN_DTLBPR,             false, "vl"   },
3026   { "__insn_exch",               TILEGX_INSN_EXCH,               false, "lpl"  },
3027   { "__insn_exch4",              TILEGX_INSN_EXCH4,              false, "ipi"  },
3028   { "__insn_fdouble_add_flags",  TILEGX_INSN_FDOUBLE_ADD_FLAGS,  true,  "lll"  },
3029   { "__insn_fdouble_addsub",     TILEGX_INSN_FDOUBLE_ADDSUB,     true,  "llll" },
3030   { "__insn_fdouble_mul_flags",  TILEGX_INSN_FDOUBLE_MUL_FLAGS,  true,  "lll"  },
3031   { "__insn_fdouble_pack1",      TILEGX_INSN_FDOUBLE_PACK1,      true,  "lll"  },
3032   { "__insn_fdouble_pack2",      TILEGX_INSN_FDOUBLE_PACK2,      true,  "llll" },
3033   { "__insn_fdouble_sub_flags",  TILEGX_INSN_FDOUBLE_SUB_FLAGS,  true,  "lll"  },
3034   { "__insn_fdouble_unpack_max", TILEGX_INSN_FDOUBLE_UNPACK_MAX, true,  "lll"  },
3035   { "__insn_fdouble_unpack_min", TILEGX_INSN_FDOUBLE_UNPACK_MIN, true,  "lll"  },
3036   { "__insn_fetchadd",           TILEGX_INSN_FETCHADD,           false, "lpl"  },
3037   { "__insn_fetchadd4",          TILEGX_INSN_FETCHADD4,          false, "ipi"  },
3038   { "__insn_fetchaddgez",        TILEGX_INSN_FETCHADDGEZ,        false, "lpl"  },
3039   { "__insn_fetchaddgez4",       TILEGX_INSN_FETCHADDGEZ4,       false, "ipi"  },
3040   { "__insn_fetchand",           TILEGX_INSN_FETCHAND,           false, "lpl"  },
3041   { "__insn_fetchand4",          TILEGX_INSN_FETCHAND4,          false, "ipi"  },
3042   { "__insn_fetchor",            TILEGX_INSN_FETCHOR,            false, "lpl"  },
3043   { "__insn_fetchor4",           TILEGX_INSN_FETCHOR4,           false, "ipi"  },
3044   { "__insn_finv",               TILEGX_INSN_FINV,               false, "vk"   },
3045   { "__insn_flush",              TILEGX_INSN_FLUSH,              false, "vk"   },
3046   { "__insn_flushwb",            TILEGX_INSN_FLUSHWB,            false, "v"    },
3047   { "__insn_fnop",               TILEGX_INSN_FNOP,               false, "v"    },
3048   { "__insn_fsingle_add1",       TILEGX_INSN_FSINGLE_ADD1,       true,  "lll"  },
3049   { "__insn_fsingle_addsub2",    TILEGX_INSN_FSINGLE_ADDSUB2,    true,  "llll" },
3050   { "__insn_fsingle_mul1",       TILEGX_INSN_FSINGLE_MUL1,       true,  "lll"  },
3051   { "__insn_fsingle_mul2",       TILEGX_INSN_FSINGLE_MUL2,       true,  "lll"  },
3052   { "__insn_fsingle_pack1",      TILEGX_INSN_FSINGLE_PACK1,      true,  "ll"   },
3053   { "__insn_fsingle_pack2",      TILEGX_INSN_FSINGLE_PACK2,      true,  "lll"  },
3054   { "__insn_fsingle_sub1",       TILEGX_INSN_FSINGLE_SUB1,       true,  "lll"  },
3055   { "__insn_icoh",               TILEGX_INSN_ICOH,               false, "vk"   },
3056   { "__insn_ill",                TILEGX_INSN_ILL,                false, "v"    },
3057   { "__insn_info",               TILEGX_INSN_INFO,               false, "vl"   },
3058   { "__insn_infol",              TILEGX_INSN_INFOL,              false, "vl"   },
3059   { "__insn_inv",                TILEGX_INSN_INV,                false, "vp"   },
3060   { "__insn_ld",                 TILEGX_INSN_LD,                 false, "lk"   },
3061   { "__insn_ld1s",               TILEGX_INSN_LD1S,               false, "lk"   },
3062   { "__insn_ld1u",               TILEGX_INSN_LD1U,               false, "lk"   },
3063   { "__insn_ld2s",               TILEGX_INSN_LD2S,               false, "lk"   },
3064   { "__insn_ld2u",               TILEGX_INSN_LD2U,               false, "lk"   },
3065   { "__insn_ld4s",               TILEGX_INSN_LD4S,               false, "lk"   },
3066   { "__insn_ld4u",               TILEGX_INSN_LD4U,               false, "lk"   },
3067   { "__insn_ldna",               TILEGX_INSN_LDNA,               false, "lk"   },
3068   { "__insn_ldnt",               TILEGX_INSN_LDNT,               false, "lk"   },
3069   { "__insn_ldnt1s",             TILEGX_INSN_LDNT1S,             false, "lk"   },
3070   { "__insn_ldnt1u",             TILEGX_INSN_LDNT1U,             false, "lk"   },
3071   { "__insn_ldnt2s",             TILEGX_INSN_LDNT2S,             false, "lk"   },
3072   { "__insn_ldnt2u",             TILEGX_INSN_LDNT2U,             false, "lk"   },
3073   { "__insn_ldnt4s",             TILEGX_INSN_LDNT4S,             false, "lk"   },
3074   { "__insn_ldnt4u",             TILEGX_INSN_LDNT4U,             false, "lk"   },
3075   { "__insn_ld_L2",              TILEGX_INSN_LD_L2,              false, "lk"   },
3076   { "__insn_ld1s_L2",            TILEGX_INSN_LD1S_L2,            false, "lk"   },
3077   { "__insn_ld1u_L2",            TILEGX_INSN_LD1U_L2,            false, "lk"   },
3078   { "__insn_ld2s_L2",            TILEGX_INSN_LD2S_L2,            false, "lk"   },
3079   { "__insn_ld2u_L2",            TILEGX_INSN_LD2U_L2,            false, "lk"   },
3080   { "__insn_ld4s_L2",            TILEGX_INSN_LD4S_L2,            false, "lk"   },
3081   { "__insn_ld4u_L2",            TILEGX_INSN_LD4U_L2,            false, "lk"   },
3082   { "__insn_ldna_L2",            TILEGX_INSN_LDNA_L2,            false, "lk"   },
3083   { "__insn_ldnt_L2",            TILEGX_INSN_LDNT_L2,            false, "lk"   },
3084   { "__insn_ldnt1s_L2",          TILEGX_INSN_LDNT1S_L2,          false, "lk"   },
3085   { "__insn_ldnt1u_L2",          TILEGX_INSN_LDNT1U_L2,          false, "lk"   },
3086   { "__insn_ldnt2s_L2",          TILEGX_INSN_LDNT2S_L2,          false, "lk"   },
3087   { "__insn_ldnt2u_L2",          TILEGX_INSN_LDNT2U_L2,          false, "lk"   },
3088   { "__insn_ldnt4s_L2",          TILEGX_INSN_LDNT4S_L2,          false, "lk"   },
3089   { "__insn_ldnt4u_L2",          TILEGX_INSN_LDNT4U_L2,          false, "lk"   },
3090   { "__insn_ld_miss",            TILEGX_INSN_LD_MISS,            false, "lk"   },
3091   { "__insn_ld1s_miss",          TILEGX_INSN_LD1S_MISS,          false, "lk"   },
3092   { "__insn_ld1u_miss",          TILEGX_INSN_LD1U_MISS,          false, "lk"   },
3093   { "__insn_ld2s_miss",          TILEGX_INSN_LD2S_MISS,          false, "lk"   },
3094   { "__insn_ld2u_miss",          TILEGX_INSN_LD2U_MISS,          false, "lk"   },
3095   { "__insn_ld4s_miss",          TILEGX_INSN_LD4S_MISS,          false, "lk"   },
3096   { "__insn_ld4u_miss",          TILEGX_INSN_LD4U_MISS,          false, "lk"   },
3097   { "__insn_ldna_miss",          TILEGX_INSN_LDNA_MISS,          false, "lk"   },
3098   { "__insn_ldnt_miss",          TILEGX_INSN_LDNT_MISS,          false, "lk"   },
3099   { "__insn_ldnt1s_miss",        TILEGX_INSN_LDNT1S_MISS,        false, "lk"   },
3100   { "__insn_ldnt1u_miss",        TILEGX_INSN_LDNT1U_MISS,        false, "lk"   },
3101   { "__insn_ldnt2s_miss",        TILEGX_INSN_LDNT2S_MISS,        false, "lk"   },
3102   { "__insn_ldnt2u_miss",        TILEGX_INSN_LDNT2U_MISS,        false, "lk"   },
3103   { "__insn_ldnt4s_miss",        TILEGX_INSN_LDNT4S_MISS,        false, "lk"   },
3104   { "__insn_ldnt4u_miss",        TILEGX_INSN_LDNT4U_MISS,        false, "lk"   },
3105   { "__insn_lnk",                TILEGX_INSN_LNK,                true,  "l"    },
3106   { "__insn_mf",                 TILEGX_INSN_MF,                 false, "v"    },
3107   { "__insn_mfspr",              TILEGX_INSN_MFSPR,              false, "ll"   },
3108   { "__insn_mm",                 TILEGX_INSN_MM,                 true,  "lllll"},
3109   { "__insn_mnz",                TILEGX_INSN_MNZ,                true,  "lll"  },
3110   { "__insn_move",               TILEGX_INSN_MOVE,               true,  "ll"   },
3111   { "__insn_movei",              TILEGX_INSN_MOVE,               true,  "ll"   },
3112   { "__insn_moveli",             TILEGX_INSN_MOVE,               true,  "ll"   },
3113   { "__insn_mtspr",              TILEGX_INSN_MTSPR,              false, "vll"  },
3114   { "__insn_mul_hs_hs",          TILEGX_INSN_MUL_HS_HS,          true,  "lll"  },
3115   { "__insn_mul_hs_hu",          TILEGX_INSN_MUL_HS_HU,          true,  "lll"  },
3116   { "__insn_mul_hs_ls",          TILEGX_INSN_MUL_HS_LS,          true,  "lll"  },
3117   { "__insn_mul_hs_lu",          TILEGX_INSN_MUL_HS_LU,          true,  "lll"  },
3118   { "__insn_mul_hu_hu",          TILEGX_INSN_MUL_HU_HU,          true,  "lll"  },
3119   { "__insn_mul_hu_ls",          TILEGX_INSN_MUL_HU_LS,          true,  "lll"  },
3120   { "__insn_mul_hu_lu",          TILEGX_INSN_MUL_HU_LU,          true,  "lll"  },
3121   { "__insn_mul_ls_ls",          TILEGX_INSN_MUL_LS_LS,          true,  "lll"  },
3122   { "__insn_mul_ls_lu",          TILEGX_INSN_MUL_LS_LU,          true,  "lll"  },
3123   { "__insn_mul_lu_lu",          TILEGX_INSN_MUL_LU_LU,          true,  "lll"  },
3124   { "__insn_mula_hs_hs",         TILEGX_INSN_MULA_HS_HS,         true,  "llll" },
3125   { "__insn_mula_hs_hu",         TILEGX_INSN_MULA_HS_HU,         true,  "llll" },
3126   { "__insn_mula_hs_ls",         TILEGX_INSN_MULA_HS_LS,         true,  "llll" },
3127   { "__insn_mula_hs_lu",         TILEGX_INSN_MULA_HS_LU,         true,  "llll" },
3128   { "__insn_mula_hu_hu",         TILEGX_INSN_MULA_HU_HU,         true,  "llll" },
3129   { "__insn_mula_hu_ls",         TILEGX_INSN_MULA_HU_LS,         true,  "llll" },
3130   { "__insn_mula_hu_lu",         TILEGX_INSN_MULA_HU_LU,         true,  "llll" },
3131   { "__insn_mula_ls_ls",         TILEGX_INSN_MULA_LS_LS,         true,  "llll" },
3132   { "__insn_mula_ls_lu",         TILEGX_INSN_MULA_LS_LU,         true,  "llll" },
3133   { "__insn_mula_lu_lu",         TILEGX_INSN_MULA_LU_LU,         true,  "llll" },
3134   { "__insn_mulax",              TILEGX_INSN_MULAX,              true,  "iiii" },
3135   { "__insn_mulx",               TILEGX_INSN_MULX,               true,  "iii"  },
3136   { "__insn_mz",                 TILEGX_INSN_MZ,                 true,  "lll"  },
3137   { "__insn_nap",                TILEGX_INSN_NAP,                false, "v"    },
3138   { "__insn_nop",                TILEGX_INSN_NOP,                true,  "v"    },
3139   { "__insn_nor",                TILEGX_INSN_NOR,                true,  "lll"  },
3140   { "__insn_or",                 TILEGX_INSN_OR,                 true,  "lll"  },
3141   { "__insn_ori",                TILEGX_INSN_OR,                 true,  "lll"  },
3142   { "__insn_pcnt",               TILEGX_INSN_PCNT,               true,  "ll"   },
3143   { "__insn_prefetch",           TILEGX_INSN_PREFETCH_L1,        false, "vk"   },
3144   { "__insn_prefetch_l1",        TILEGX_INSN_PREFETCH_L1,        false, "vk"   },
3145   { "__insn_prefetch_l1_fault",  TILEGX_INSN_PREFETCH_L1_FAULT,  false, "vk"   },
3146   { "__insn_prefetch_l2",        TILEGX_INSN_PREFETCH_L2,        false, "vk"   },
3147   { "__insn_prefetch_l2_fault",  TILEGX_INSN_PREFETCH_L2_FAULT,  false, "vk"   },
3148   { "__insn_prefetch_l3",        TILEGX_INSN_PREFETCH_L3,        false, "vk"   },
3149   { "__insn_prefetch_l3_fault",  TILEGX_INSN_PREFETCH_L3_FAULT,  false, "vk"   },
3150   { "__insn_revbits",            TILEGX_INSN_REVBITS,            true,  "ll"   },
3151   { "__insn_revbytes",           TILEGX_INSN_REVBYTES,           true,  "ll"   },
3152   { "__insn_rotl",               TILEGX_INSN_ROTL,               true,  "lli"  },
3153   { "__insn_rotli",              TILEGX_INSN_ROTL,               true,  "lli"  },
3154   { "__insn_shl",                TILEGX_INSN_SHL,                true,  "lli"  },
3155   { "__insn_shl16insli",         TILEGX_INSN_SHL16INSLI,         true,  "lll"  },
3156   { "__insn_shl1add",            TILEGX_INSN_SHL1ADD,            true,  "lll"  },
3157   { "__insn_shl1addx",           TILEGX_INSN_SHL1ADDX,           true,  "iii"  },
3158   { "__insn_shl2add",            TILEGX_INSN_SHL2ADD,            true,  "lll"  },
3159   { "__insn_shl2addx",           TILEGX_INSN_SHL2ADDX,           true,  "iii"  },
3160   { "__insn_shl3add",            TILEGX_INSN_SHL3ADD,            true,  "lll"  },
3161   { "__insn_shl3addx",           TILEGX_INSN_SHL3ADDX,           true,  "iii"  },
3162   { "__insn_shli",               TILEGX_INSN_SHL,                true,  "lli"  },
3163   { "__insn_shlx",               TILEGX_INSN_SHLX,               true,  "iii"  },
3164   { "__insn_shlxi",              TILEGX_INSN_SHLX,               true,  "iii"  },
3165   { "__insn_shrs",               TILEGX_INSN_SHRS,               true,  "lli"  },
3166   { "__insn_shrsi",              TILEGX_INSN_SHRS,               true,  "lli"  },
3167   { "__insn_shru",               TILEGX_INSN_SHRU,               true,  "lli"  },
3168   { "__insn_shrui",              TILEGX_INSN_SHRU,               true,  "lli"  },
3169   { "__insn_shrux",              TILEGX_INSN_SHRUX,              true,  "iii"  },
3170   { "__insn_shruxi",             TILEGX_INSN_SHRUX,              true,  "iii"  },
3171   { "__insn_shufflebytes",       TILEGX_INSN_SHUFFLEBYTES,       true,  "llll" },
3172   { "__insn_st",                 TILEGX_INSN_ST,                 false, "vpl"  },
3173   { "__insn_st1",                TILEGX_INSN_ST1,                false, "vpl"  },
3174   { "__insn_st2",                TILEGX_INSN_ST2,                false, "vpl"  },
3175   { "__insn_st4",                TILEGX_INSN_ST4,                false, "vpl"  },
3176   { "__insn_stnt",               TILEGX_INSN_STNT,               false, "vpl"  },
3177   { "__insn_stnt1",              TILEGX_INSN_STNT1,              false, "vpl"  },
3178   { "__insn_stnt2",              TILEGX_INSN_STNT2,              false, "vpl"  },
3179   { "__insn_stnt4",              TILEGX_INSN_STNT4,              false, "vpl"  },
3180   { "__insn_sub",                TILEGX_INSN_SUB,                true,  "lll"  },
3181   { "__insn_subx",               TILEGX_INSN_SUBX,               true,  "iii"  },
3182   { "__insn_subxsc",             TILEGX_INSN_SUBXSC,             true,  "iii"  },
3183   { "__insn_tblidxb0",           TILEGX_INSN_TBLIDXB0,           true,  "lll"  },
3184   { "__insn_tblidxb1",           TILEGX_INSN_TBLIDXB1,           true,  "lll"  },
3185   { "__insn_tblidxb2",           TILEGX_INSN_TBLIDXB2,           true,  "lll"  },
3186   { "__insn_tblidxb3",           TILEGX_INSN_TBLIDXB3,           true,  "lll"  },
3187   { "__insn_v1add",              TILEGX_INSN_V1ADD,              true,  "lll"  },
3188   { "__insn_v1addi",             TILEGX_INSN_V1ADDI,             true,  "lll"  },
3189   { "__insn_v1adduc",            TILEGX_INSN_V1ADDUC,            true,  "lll"  },
3190   { "__insn_v1adiffu",           TILEGX_INSN_V1ADIFFU,           true,  "lll"  },
3191   { "__insn_v1avgu",             TILEGX_INSN_V1AVGU,             true,  "lll"  },
3192   { "__insn_v1cmpeq",            TILEGX_INSN_V1CMPEQ,            true,  "lll"  },
3193   { "__insn_v1cmpeqi",           TILEGX_INSN_V1CMPEQI,           true,  "lll"  },
3194   { "__insn_v1cmples",           TILEGX_INSN_V1CMPLES,           true,  "lll"  },
3195   { "__insn_v1cmpleu",           TILEGX_INSN_V1CMPLEU,           true,  "lll"  },
3196   { "__insn_v1cmplts",           TILEGX_INSN_V1CMPLTS,           true,  "lll"  },
3197   { "__insn_v1cmpltsi",          TILEGX_INSN_V1CMPLTSI,          true,  "lll"  },
3198   { "__insn_v1cmpltu",           TILEGX_INSN_V1CMPLTU,           true,  "lll"  },
3199   { "__insn_v1cmpltui",          TILEGX_INSN_V1CMPLTUI,          true,  "lll"  },
3200   { "__insn_v1cmpne",            TILEGX_INSN_V1CMPNE,            true,  "lll"  },
3201   { "__insn_v1ddotpu",           TILEGX_INSN_V1DDOTPU,           true,  "lll"  },
3202   { "__insn_v1ddotpua",          TILEGX_INSN_V1DDOTPUA,          true,  "llll" },
3203   { "__insn_v1ddotpus",          TILEGX_INSN_V1DDOTPUS,          true,  "lll"  },
3204   { "__insn_v1ddotpusa",         TILEGX_INSN_V1DDOTPUSA,         true,  "llll" },
3205   { "__insn_v1dotp",             TILEGX_INSN_V1DOTP,             true,  "lll"  },
3206   { "__insn_v1dotpa",            TILEGX_INSN_V1DOTPA,            true,  "llll" },
3207   { "__insn_v1dotpu",            TILEGX_INSN_V1DOTPU,            true,  "lll"  },
3208   { "__insn_v1dotpua",           TILEGX_INSN_V1DOTPUA,           true,  "llll" },
3209   { "__insn_v1dotpus",           TILEGX_INSN_V1DOTPUS,           true,  "lll"  },
3210   { "__insn_v1dotpusa",          TILEGX_INSN_V1DOTPUSA,          true,  "llll" },
3211   { "__insn_v1int_h",            TILEGX_INSN_V1INT_H,            true,  "lll"  },
3212   { "__insn_v1int_l",            TILEGX_INSN_V1INT_L,            true,  "lll"  },
3213   { "__insn_v1maxu",             TILEGX_INSN_V1MAXU,             true,  "lll"  },
3214   { "__insn_v1maxui",            TILEGX_INSN_V1MAXUI,            true,  "lll"  },
3215   { "__insn_v1minu",             TILEGX_INSN_V1MINU,             true,  "lll"  },
3216   { "__insn_v1minui",            TILEGX_INSN_V1MINUI,            true,  "lll"  },
3217   { "__insn_v1mnz",              TILEGX_INSN_V1MNZ,              true,  "lll"  },
3218   { "__insn_v1multu",            TILEGX_INSN_V1MULTU,            true,  "lll"  },
3219   { "__insn_v1mulu",             TILEGX_INSN_V1MULU,             true,  "lll"  },
3220   { "__insn_v1mulus",            TILEGX_INSN_V1MULUS,            true,  "lll"  },
3221   { "__insn_v1mz",               TILEGX_INSN_V1MZ,               true,  "lll"  },
3222   { "__insn_v1sadau",            TILEGX_INSN_V1SADAU,            true,  "llll" },
3223   { "__insn_v1sadu",             TILEGX_INSN_V1SADU,             true,  "lll"  },
3224   { "__insn_v1shl",              TILEGX_INSN_V1SHL,              true,  "lll"  },
3225   { "__insn_v1shli",             TILEGX_INSN_V1SHLI,             true,  "lll"  },
3226   { "__insn_v1shrs",             TILEGX_INSN_V1SHRS,             true,  "lll"  },
3227   { "__insn_v1shrsi",            TILEGX_INSN_V1SHRSI,            true,  "lll"  },
3228   { "__insn_v1shru",             TILEGX_INSN_V1SHRU,             true,  "lll"  },
3229   { "__insn_v1shrui",            TILEGX_INSN_V1SHRUI,            true,  "lll"  },
3230   { "__insn_v1sub",              TILEGX_INSN_V1SUB,              true,  "lll"  },
3231   { "__insn_v1subuc",            TILEGX_INSN_V1SUBUC,            true,  "lll"  },
3232   { "__insn_v2add",              TILEGX_INSN_V2ADD,              true,  "lll"  },
3233   { "__insn_v2addi",             TILEGX_INSN_V2ADDI,             true,  "lll"  },
3234   { "__insn_v2addsc",            TILEGX_INSN_V2ADDSC,            true,  "lll"  },
3235   { "__insn_v2adiffs",           TILEGX_INSN_V2ADIFFS,           true,  "lll"  },
3236   { "__insn_v2avgs",             TILEGX_INSN_V2AVGS,             true,  "lll"  },
3237   { "__insn_v2cmpeq",            TILEGX_INSN_V2CMPEQ,            true,  "lll"  },
3238   { "__insn_v2cmpeqi",           TILEGX_INSN_V2CMPEQI,           true,  "lll"  },
3239   { "__insn_v2cmples",           TILEGX_INSN_V2CMPLES,           true,  "lll"  },
3240   { "__insn_v2cmpleu",           TILEGX_INSN_V2CMPLEU,           true,  "lll"  },
3241   { "__insn_v2cmplts",           TILEGX_INSN_V2CMPLTS,           true,  "lll"  },
3242   { "__insn_v2cmpltsi",          TILEGX_INSN_V2CMPLTSI,          true,  "lll"  },
3243   { "__insn_v2cmpltu",           TILEGX_INSN_V2CMPLTU,           true,  "lll"  },
3244   { "__insn_v2cmpltui",          TILEGX_INSN_V2CMPLTUI,          true,  "lll"  },
3245   { "__insn_v2cmpne",            TILEGX_INSN_V2CMPNE,            true,  "lll"  },
3246   { "__insn_v2dotp",             TILEGX_INSN_V2DOTP,             true,  "lll"  },
3247   { "__insn_v2dotpa",            TILEGX_INSN_V2DOTPA,            true,  "llll" },
3248   { "__insn_v2int_h",            TILEGX_INSN_V2INT_H,            true,  "lll"  },
3249   { "__insn_v2int_l",            TILEGX_INSN_V2INT_L,            true,  "lll"  },
3250   { "__insn_v2maxs",             TILEGX_INSN_V2MAXS,             true,  "lll"  },
3251   { "__insn_v2maxsi",            TILEGX_INSN_V2MAXSI,            true,  "lll"  },
3252   { "__insn_v2mins",             TILEGX_INSN_V2MINS,             true,  "lll"  },
3253   { "__insn_v2minsi",            TILEGX_INSN_V2MINSI,            true,  "lll"  },
3254   { "__insn_v2mnz",              TILEGX_INSN_V2MNZ,              true,  "lll"  },
3255   { "__insn_v2mulfsc",           TILEGX_INSN_V2MULFSC,           true,  "lll"  },
3256   { "__insn_v2muls",             TILEGX_INSN_V2MULS,             true,  "lll"  },
3257   { "__insn_v2mults",            TILEGX_INSN_V2MULTS,            true,  "lll"  },
3258   { "__insn_v2mz",               TILEGX_INSN_V2MZ,               true,  "lll"  },
3259   { "__insn_v2packh",            TILEGX_INSN_V2PACKH,            true,  "lll"  },
3260   { "__insn_v2packl",            TILEGX_INSN_V2PACKL,            true,  "lll"  },
3261   { "__insn_v2packuc",           TILEGX_INSN_V2PACKUC,           true,  "lll"  },
3262   { "__insn_v2sadas",            TILEGX_INSN_V2SADAS,            true,  "llll" },
3263   { "__insn_v2sadau",            TILEGX_INSN_V2SADAU,            true,  "llll" },
3264   { "__insn_v2sads",             TILEGX_INSN_V2SADS,             true,  "lll"  },
3265   { "__insn_v2sadu",             TILEGX_INSN_V2SADU,             true,  "lll"  },
3266   { "__insn_v2shl",              TILEGX_INSN_V2SHL,              true,  "lll"  },
3267   { "__insn_v2shli",             TILEGX_INSN_V2SHLI,             true,  "lll"  },
3268   { "__insn_v2shlsc",            TILEGX_INSN_V2SHLSC,            true,  "lll"  },
3269   { "__insn_v2shrs",             TILEGX_INSN_V2SHRS,             true,  "lll"  },
3270   { "__insn_v2shrsi",            TILEGX_INSN_V2SHRSI,            true,  "lll"  },
3271   { "__insn_v2shru",             TILEGX_INSN_V2SHRU,             true,  "lll"  },
3272   { "__insn_v2shrui",            TILEGX_INSN_V2SHRUI,            true,  "lll"  },
3273   { "__insn_v2sub",              TILEGX_INSN_V2SUB,              true,  "lll"  },
3274   { "__insn_v2subsc",            TILEGX_INSN_V2SUBSC,            true,  "lll"  },
3275   { "__insn_v4add",              TILEGX_INSN_V4ADD,              true,  "lll"  },
3276   { "__insn_v4addsc",            TILEGX_INSN_V4ADDSC,            true,  "lll"  },
3277   { "__insn_v4int_h",            TILEGX_INSN_V4INT_H,            true,  "lll"  },
3278   { "__insn_v4int_l",            TILEGX_INSN_V4INT_L,            true,  "lll"  },
3279   { "__insn_v4packsc",           TILEGX_INSN_V4PACKSC,           true,  "lll"  },
3280   { "__insn_v4shl",              TILEGX_INSN_V4SHL,              true,  "lll"  },
3281   { "__insn_v4shlsc",            TILEGX_INSN_V4SHLSC,            true,  "lll"  },
3282   { "__insn_v4shrs",             TILEGX_INSN_V4SHRS,             true,  "lll"  },
3283   { "__insn_v4shru",             TILEGX_INSN_V4SHRU,             true,  "lll"  },
3284   { "__insn_v4sub",              TILEGX_INSN_V4SUB,              true,  "lll"  },
3285   { "__insn_v4subsc",            TILEGX_INSN_V4SUBSC,            true,  "lll"  },
3286   { "__insn_wh64",               TILEGX_INSN_WH64,               false, "vp"   },
3287   { "__insn_xor",                TILEGX_INSN_XOR,                true,  "lll"  },
3288   { "__insn_xori",               TILEGX_INSN_XOR,                true,  "lll"  },
3289   { "__tile_network_barrier",    TILEGX_NETWORK_BARRIER,         false, "v"    },
3290   { "__tile_idn0_receive",       TILEGX_IDN0_RECEIVE,            false, "l"    },
3291   { "__tile_idn1_receive",       TILEGX_IDN1_RECEIVE,            false, "l"    },
3292   { "__tile_idn_send",           TILEGX_IDN_SEND,                false, "vl"   },
3293   { "__tile_udn0_receive",       TILEGX_UDN0_RECEIVE,            false, "l"    },
3294   { "__tile_udn1_receive",       TILEGX_UDN1_RECEIVE,            false, "l"    },
3295   { "__tile_udn2_receive",       TILEGX_UDN2_RECEIVE,            false, "l"    },
3296   { "__tile_udn3_receive",       TILEGX_UDN3_RECEIVE,            false, "l"    },
3297   { "__tile_udn_send",           TILEGX_UDN_SEND,                false, "vl"   },
3298 };
3299
3300
3301 /* Convert a character in a builtin type string to a tree type.  */
3302 static tree
3303 char_to_type (char c)
3304 {
3305   static tree volatile_ptr_type_node = NULL;
3306   static tree volatile_const_ptr_type_node = NULL;
3307
3308   if (volatile_ptr_type_node == NULL)
3309     {
3310       volatile_ptr_type_node =
3311         build_pointer_type (build_qualified_type (void_type_node,
3312                                                   TYPE_QUAL_VOLATILE));
3313       volatile_const_ptr_type_node =
3314         build_pointer_type (build_qualified_type (void_type_node,
3315                                                   TYPE_QUAL_CONST
3316                                                   | TYPE_QUAL_VOLATILE));
3317     }
3318
3319   switch (c)
3320     {
3321     case 'v':
3322       return void_type_node;
3323     case 'i':
3324       return unsigned_type_node;
3325     case 'l':
3326       return long_long_unsigned_type_node;
3327     case 'p':
3328       return volatile_ptr_type_node;
3329     case 'k':
3330       return volatile_const_ptr_type_node;
3331     default:
3332       gcc_unreachable ();
3333     }
3334 }
3335
3336
3337 /* Implement TARGET_INIT_BUILTINS.  */
3338 static void
3339 tilegx_init_builtins (void)
3340 {
3341   size_t i;
3342
3343   for (i = 0; i < ARRAY_SIZE (tilegx_builtins); i++)
3344     {
3345       const struct tilegx_builtin_def *p = &tilegx_builtins[i];
3346       tree ftype, ret_type, arg_type_list = void_list_node;
3347       tree decl;
3348       int j;
3349
3350       for (j = strlen (p->type) - 1; j > 0; j--)
3351         {
3352           arg_type_list =
3353             tree_cons (NULL_TREE, char_to_type (p->type[j]), arg_type_list);
3354         }
3355
3356       ret_type = char_to_type (p->type[0]);
3357
3358       ftype = build_function_type (ret_type, arg_type_list);
3359
3360       decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
3361                                    NULL, NULL);
3362
3363       if (p->is_const)
3364         TREE_READONLY (decl) = 1;
3365       TREE_NOTHROW (decl) = 1;
3366
3367       if (tilegx_builtin_info[p->code].fndecl == NULL)
3368         tilegx_builtin_info[p->code].fndecl = decl;
3369     }
3370 }
3371
3372
3373 /* Implement TARGET_EXPAND_BUILTIN.  */
3374 static rtx
3375 tilegx_expand_builtin (tree exp,
3376                        rtx target,
3377                        rtx subtarget ATTRIBUTE_UNUSED,
3378                        enum machine_mode mode ATTRIBUTE_UNUSED,
3379                        int ignore ATTRIBUTE_UNUSED)
3380 {
3381 #define MAX_BUILTIN_ARGS 4
3382
3383   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3384   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3385   tree arg;
3386   call_expr_arg_iterator iter;
3387   enum insn_code icode;
3388   rtx op[MAX_BUILTIN_ARGS + 1], pat;
3389   int opnum;
3390   bool nonvoid;
3391   insn_gen_fn fn;
3392
3393   if (fcode >= TILEGX_BUILTIN_max)
3394     internal_error ("bad builtin fcode");
3395   icode = tilegx_builtin_info[fcode].icode;
3396   if (icode == 0)
3397     internal_error ("bad builtin icode");
3398
3399   nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
3400
3401   opnum = nonvoid;
3402   FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
3403   {
3404     const struct insn_operand_data *insn_op;
3405
3406     if (arg == error_mark_node)
3407       return NULL_RTX;
3408     if (opnum > MAX_BUILTIN_ARGS)
3409       return NULL_RTX;
3410
3411     insn_op = &insn_data[icode].operand[opnum];
3412
3413     op[opnum] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
3414
3415     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3416       {
3417         enum machine_mode opmode = insn_op->mode;
3418
3419         /* pointer_operand and pmode_register_operand operands do
3420            not specify a mode, so use the operand's mode instead
3421            (which should always be right by the time we get here,
3422            except for constants, which are VOIDmode).  */
3423         if (opmode == VOIDmode)
3424           {
3425             enum machine_mode m = GET_MODE (op[opnum]);
3426             gcc_assert (m == Pmode || m == VOIDmode);
3427             opmode = Pmode;
3428           }
3429
3430         op[opnum] = copy_to_mode_reg (opmode, op[opnum]);
3431       }
3432
3433     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
3434       {
3435         /* We still failed to meet the predicate even after moving
3436            into a register. Assume we needed an immediate.  */
3437         error_at (EXPR_LOCATION (exp),
3438                   "operand must be an immediate of the right size");
3439         return const0_rtx;
3440       }
3441
3442     opnum++;
3443   }
3444
3445   if (nonvoid)
3446     {
3447       enum machine_mode tmode = insn_data[icode].operand[0].mode;
3448       if (!target
3449           || GET_MODE (target) != tmode
3450           || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3451         {
3452           if (tmode == VOIDmode)
3453             {
3454               /* get the mode from the return type.  */
3455               tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
3456             }
3457           target = gen_reg_rtx (tmode);
3458         }
3459       op[0] = target;
3460     }
3461
3462   fn = GEN_FCN (icode);
3463   switch (opnum)
3464     {
3465     case 0:
3466       pat = fn (NULL_RTX);
3467       break;
3468     case 1:
3469       pat = fn (op[0]);
3470       break;
3471     case 2:
3472       pat = fn (op[0], op[1]);
3473       break;
3474     case 3:
3475       pat = fn (op[0], op[1], op[2]);
3476       break;
3477     case 4:
3478       pat = fn (op[0], op[1], op[2], op[3]);
3479       break;
3480     case 5:
3481       pat = fn (op[0], op[1], op[2], op[3], op[4]);
3482       break;
3483     default:
3484       gcc_unreachable ();
3485     }
3486   if (!pat)
3487     return NULL_RTX;
3488   emit_insn (pat);
3489
3490   if (nonvoid)
3491     return target;
3492   else
3493     return const0_rtx;
3494 }
3495
3496
3497 /* Implement TARGET_BUILTIN_DECL.  */
3498 static tree
3499 tilegx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
3500 {
3501   if (code >= TILEGX_BUILTIN_max)
3502     return error_mark_node;
3503
3504   return tilegx_builtin_info[code].fndecl;
3505 }
3506 \f
3507
3508
3509 /* Stack frames  */
3510
3511 /* Return whether REGNO needs to be saved in the stack frame.  */
3512 static bool
3513 need_to_save_reg (unsigned int regno)
3514 {
3515   if (!fixed_regs[regno] && !call_used_regs[regno]
3516       && df_regs_ever_live_p (regno))
3517     return true;
3518
3519   if (flag_pic
3520       && (regno == PIC_OFFSET_TABLE_REGNUM
3521           || regno == TILEGX_PIC_TEXT_LABEL_REGNUM)
3522       && (crtl->uses_pic_offset_table || crtl->saves_all_registers))
3523     return true;
3524
3525   if (crtl->calls_eh_return)
3526     {
3527       unsigned i;
3528       for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
3529         {
3530           if (regno == EH_RETURN_DATA_REGNO (i))
3531             return true;
3532         }
3533     }
3534
3535   return false;
3536 }
3537
3538
3539 /* Return the size of the register savev area.  This function is only
3540    correct starting with local register allocation */
3541 static int
3542 tilegx_saved_regs_size (void)
3543 {
3544   int reg_save_size = 0;
3545   int regno;
3546   int offset_to_frame;
3547   int align_mask;
3548
3549   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
3550     if (need_to_save_reg (regno))
3551       reg_save_size += UNITS_PER_WORD;
3552
3553   /* Pad out the register save area if necessary to make
3554      frame_pointer_rtx be as aligned as the stack pointer.  */
3555   offset_to_frame = crtl->args.pretend_args_size + reg_save_size;
3556   align_mask = (STACK_BOUNDARY / BITS_PER_UNIT) - 1;
3557   reg_save_size += (-offset_to_frame) & align_mask;
3558
3559   return reg_save_size;
3560 }
3561
3562
3563 /* Round up frame size SIZE.  */
3564 static int
3565 round_frame_size (int size)
3566 {
3567   return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
3568           & -STACK_BOUNDARY / BITS_PER_UNIT);
3569 }
3570
3571
3572 /* Emit a store in the stack frame to save REGNO at address ADDR, and
3573    emit the corresponding REG_CFA_OFFSET note described by CFA and
3574    CFA_OFFSET.  Return the emitted insn.  */
3575 static rtx
3576 frame_emit_store (int regno, int regno_note, rtx addr, rtx cfa,
3577                   int cfa_offset)
3578 {
3579   rtx reg = gen_rtx_REG (DImode, regno);
3580   rtx mem = gen_frame_mem (DImode, addr);
3581   rtx mov = gen_movdi (mem, reg);
3582
3583   /* Describe what just happened in a way that dwarf understands.  We
3584      use temporary registers to hold the address to make scheduling
3585      easier, and use the REG_CFA_OFFSET to describe the address as an
3586      offset from the CFA.  */
3587   rtx reg_note = gen_rtx_REG (DImode, regno_note);
3588   rtx cfa_relative_addr = gen_rtx_PLUS (Pmode, cfa, GEN_INT (cfa_offset));
3589   rtx cfa_relative_mem = gen_frame_mem (DImode, cfa_relative_addr);
3590   rtx real = gen_rtx_SET (VOIDmode, cfa_relative_mem, reg_note);
3591   add_reg_note (mov, REG_CFA_OFFSET, real);
3592
3593   return emit_insn (mov);
3594 }
3595
3596
3597 /* Emit a load in the stack frame to load REGNO from address ADDR.
3598    Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
3599    non-null.  Return the emitted insn.  */
3600 static rtx
3601 frame_emit_load (int regno, rtx addr, rtx *cfa_restores)
3602 {
3603   rtx reg = gen_rtx_REG (DImode, regno);
3604   rtx mem = gen_frame_mem (DImode, addr);
3605   if (cfa_restores)
3606     *cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, *cfa_restores);
3607   return emit_insn (gen_movdi (reg, mem));
3608 }
3609
3610
3611 /* Helper function to set RTX_FRAME_RELATED_P on instructions,
3612    including sequences.  */
3613 static rtx
3614 set_frame_related_p (void)
3615 {
3616   rtx seq = get_insns ();
3617   rtx insn;
3618
3619   end_sequence ();
3620
3621   if (!seq)
3622     return NULL_RTX;
3623
3624   if (INSN_P (seq))
3625     {
3626       insn = seq;
3627       while (insn != NULL_RTX)
3628         {
3629           RTX_FRAME_RELATED_P (insn) = 1;
3630           insn = NEXT_INSN (insn);
3631         }
3632       seq = emit_insn (seq);
3633     }
3634   else
3635     {
3636       seq = emit_insn (seq);
3637       RTX_FRAME_RELATED_P (seq) = 1;
3638     }
3639   return seq;
3640 }
3641
3642
3643 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
3644
3645 /* This emits code for 'sp += offset'.
3646    
3647    The ABI only allows us to modify 'sp' in a single 'addi' or
3648    'addli', so the backtracer understands it. Larger amounts cannot
3649    use those instructions, so are added by placing the offset into a
3650    large register and using 'add'.
3651
3652    This happens after reload, so we need to expand it ourselves.  */
3653 static rtx
3654 emit_sp_adjust (int offset, int *next_scratch_regno, bool frame_related,
3655                 rtx reg_notes)
3656 {
3657   rtx to_add;
3658   rtx imm_rtx = GEN_INT (offset);
3659
3660   rtx insn;
3661   if (satisfies_constraint_J (imm_rtx))
3662     {
3663       /* We can add this using a single immediate add.  */
3664       to_add = imm_rtx;
3665     }
3666   else
3667     {
3668       rtx tmp = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3669       tilegx_expand_set_const64 (tmp, imm_rtx);
3670       to_add = tmp;
3671     }
3672
3673   /* Actually adjust the stack pointer.  */
3674   if (TARGET_32BIT)
3675     insn = gen_sp_adjust_32bit (stack_pointer_rtx, stack_pointer_rtx, to_add);
3676   else
3677     insn = gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx, to_add);
3678
3679   insn = emit_insn (insn);
3680   REG_NOTES (insn) = reg_notes;
3681
3682   /* Describe what just happened in a way that dwarf understands.  */
3683   if (frame_related)
3684     {
3685       rtx real = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
3686                               gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3687                                             imm_rtx));
3688       RTX_FRAME_RELATED_P (insn) = 1;
3689       add_reg_note (insn, REG_CFA_ADJUST_CFA, real);
3690     }
3691
3692   return insn;
3693 }
3694
3695
3696 /* Return whether the current function is leaf.  This takes into
3697    account whether the function calls tls_get_addr.  */
3698 static bool
3699 tilegx_current_function_is_leaf (void)
3700 {
3701   return current_function_is_leaf && !cfun->machine->calls_tls_get_addr;
3702 }
3703
3704
3705 /* Return the frame size.  */
3706 static int
3707 compute_total_frame_size (void)
3708 {
3709   int total_size = (get_frame_size () + tilegx_saved_regs_size ()
3710                     + crtl->outgoing_args_size
3711                     + crtl->args.pretend_args_size);
3712
3713   if (!tilegx_current_function_is_leaf () || cfun->calls_alloca)
3714     {
3715       /* Make room for save area in callee.  */
3716       total_size += STACK_POINTER_OFFSET;
3717     }
3718
3719   return round_frame_size (total_size);
3720 }
3721
3722
3723 /* Return nonzero if this function is known to have a null epilogue.
3724    This allows the optimizer to omit jumps to jumps if no stack was
3725    created.  */
3726 bool
3727 tilegx_can_use_return_insn_p (void)
3728 {
3729   return (reload_completed
3730           && cfun->static_chain_decl == 0
3731           && compute_total_frame_size () == 0
3732           && tilegx_current_function_is_leaf ()
3733           && !crtl->profile && !df_regs_ever_live_p (TILEGX_LINK_REGNUM));
3734 }
3735
3736
3737 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'.  If there
3738    is a frame pointer, it computes the value relative to
3739    that. Otherwise it uses the stack pointer.  */
3740 static rtx
3741 compute_frame_addr (int offset_from_fp, int *next_scratch_regno)
3742 {
3743   rtx base_reg_rtx, tmp_reg_rtx, offset_rtx;
3744   int offset_from_base;
3745
3746   if (frame_pointer_needed)
3747     {
3748       base_reg_rtx = hard_frame_pointer_rtx;
3749       offset_from_base = offset_from_fp;
3750     }
3751   else
3752     {
3753       int offset_from_sp = compute_total_frame_size () + offset_from_fp;
3754       offset_from_base = offset_from_sp;
3755       base_reg_rtx = stack_pointer_rtx;
3756     }
3757
3758   if (offset_from_base == 0)
3759     return base_reg_rtx;
3760
3761   /* Compute the new value of the stack pointer.  */
3762   tmp_reg_rtx = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
3763   offset_rtx = GEN_INT (offset_from_base);
3764
3765   if (!add_operand (offset_rtx, Pmode))
3766     {
3767       expand_set_cint64 (tmp_reg_rtx, offset_rtx);
3768       offset_rtx = tmp_reg_rtx;
3769     }
3770
3771   emit_insn (gen_rtx_SET (VOIDmode, tmp_reg_rtx,
3772                           gen_rtx_PLUS (Pmode, base_reg_rtx, offset_rtx)));
3773
3774   return tmp_reg_rtx;
3775 }
3776
3777
3778 /* The stack frame looks like this:
3779          +-------------+
3780          |    ...      | 
3781          |  incoming   | 
3782          | stack args  | 
3783    AP -> +-------------+
3784          | caller's HFP|
3785          +-------------+
3786          | lr save     |
3787   HFP -> +-------------+
3788          |  var args   | 
3789          |  reg save   | crtl->args.pretend_args_size bytes
3790          +-------------+
3791          |    ...      | 
3792          | saved regs  | tilegx_saved_regs_size() bytes
3793    FP -> +-------------+
3794          |    ...      | 
3795          |   vars      | get_frame_size() bytes
3796          +-------------+
3797          |    ...      | 
3798          |  outgoing   | 
3799          |  stack args | crtl->outgoing_args_size bytes
3800          +-------------+
3801          | HFP         | ptr_size bytes (only here if nonleaf / alloca)
3802          +-------------+
3803          | callee lr   | ptr_size bytes (only here if nonleaf / alloca)
3804          | save        | 
3805    SP -> +-------------+
3806
3807   HFP == incoming SP.
3808
3809   For functions with a frame larger than 32767 bytes, or which use
3810   alloca (), r52 is used as a frame pointer.  Otherwise there is no
3811   frame pointer.
3812
3813   FP is saved at SP+ptr_size before calling a subroutine so the callee
3814   can chain.  */
3815 void
3816 tilegx_expand_prologue (void)
3817 {
3818 #define ROUND_ROBIN_SIZE 4
3819   /* We round-robin through four scratch registers to hold temporary
3820      addresses for saving registers, to make instruction scheduling
3821      easier.  */
3822   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
3823     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
3824   };
3825   rtx insn, cfa;
3826   unsigned int which_scratch;
3827   int offset, start_offset, regno;
3828
3829   /* A register that holds a copy of the incoming fp.  */
3830   int fp_copy_regno = -1;
3831
3832   /* A register that holds a copy of the incoming sp.  */
3833   int sp_copy_regno = -1;
3834
3835   /* Next scratch register number to hand out (postdecrementing).  */
3836   int next_scratch_regno = 29;
3837
3838   int total_size = compute_total_frame_size ();
3839
3840   if (flag_stack_usage_info)
3841     current_function_static_stack_size = total_size;
3842
3843   /* Save lr first in its special location because code after this
3844      might use the link register as a scratch register.  */
3845   if (df_regs_ever_live_p (TILEGX_LINK_REGNUM) || crtl->calls_eh_return)
3846     FRP (frame_emit_store (TILEGX_LINK_REGNUM, TILEGX_LINK_REGNUM,
3847                            stack_pointer_rtx, stack_pointer_rtx, 0));
3848
3849   if (total_size == 0)
3850     {
3851       /* Load the PIC register if needed.  */
3852       if (flag_pic && crtl->uses_pic_offset_table)
3853         load_pic_register (false);
3854
3855       return;
3856     }
3857
3858   cfa = stack_pointer_rtx;
3859
3860   if (frame_pointer_needed)
3861     {
3862       fp_copy_regno = next_scratch_regno--;
3863
3864       /* Copy the old frame pointer aside so we can save it later.  */
3865       insn =
3866         FRP (emit_move_insn (gen_rtx_REG (word_mode, fp_copy_regno),
3867                              gen_lowpart (word_mode, hard_frame_pointer_rtx)));
3868       add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
3869
3870       /* Set up the frame pointer.  */
3871       insn = FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
3872       add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
3873       cfa = hard_frame_pointer_rtx;
3874       REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
3875
3876       /* fp holds a copy of the incoming sp, in case we need to store
3877          it.  */
3878       sp_copy_regno = HARD_FRAME_POINTER_REGNUM;
3879     }
3880   else if (!tilegx_current_function_is_leaf ())
3881     {
3882       /* Copy the old stack pointer aside so we can save it later.  */
3883       sp_copy_regno = next_scratch_regno--;
3884       insn = FRP (emit_move_insn (gen_rtx_REG (Pmode, sp_copy_regno),
3885                                   stack_pointer_rtx));
3886       add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
3887     }
3888
3889   if (tilegx_current_function_is_leaf ())
3890     {
3891       /* No need to store chain pointer to caller's frame.  */
3892       emit_sp_adjust (-total_size, &next_scratch_regno,
3893                       !frame_pointer_needed, NULL_RTX);
3894     }
3895   else
3896     {
3897       /* Save the frame pointer (incoming sp value) to support
3898          backtracing.  First we need to create an rtx with the store
3899          address.  */
3900       rtx chain_addr = gen_rtx_REG (Pmode, next_scratch_regno--);
3901       rtx size_rtx = GEN_INT (-(total_size - UNITS_PER_WORD));
3902       int cfa_offset =
3903         frame_pointer_needed ? UNITS_PER_WORD - total_size : UNITS_PER_WORD;
3904
3905       if (add_operand (size_rtx, Pmode))
3906         {
3907           /* Expose more parallelism by computing this value from the
3908              original stack pointer, not the one after we have pushed
3909              the frame.  */
3910           rtx p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx);
3911           emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
3912           emit_sp_adjust (-total_size, &next_scratch_regno,
3913                           !frame_pointer_needed, NULL_RTX);
3914         }
3915       else
3916         {
3917           /* The stack frame is large, so just store the incoming sp
3918              value at *(new_sp + UNITS_PER_WORD).  */
3919           rtx p;
3920           emit_sp_adjust (-total_size, &next_scratch_regno,
3921                           !frame_pointer_needed, NULL_RTX);
3922           p = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
3923                             GEN_INT (UNITS_PER_WORD));
3924           emit_insn (gen_rtx_SET (VOIDmode, chain_addr, p));
3925         }
3926
3927       /* Save our frame pointer for backtrace chaining.  */
3928       FRP (frame_emit_store (sp_copy_regno, STACK_POINTER_REGNUM,
3929                              chain_addr, cfa, cfa_offset));
3930     }
3931
3932   /* Compute where to start storing registers we need to save.  */
3933   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
3934   offset = start_offset;
3935
3936   /* Store all registers that need saving.  */
3937   which_scratch = 0;
3938   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
3939     if (need_to_save_reg (regno))
3940       {
3941         rtx r = reg_save_addr[which_scratch];
3942         int from_regno;
3943         int cfa_offset = frame_pointer_needed ? offset : total_size + offset;
3944
3945         if (r == NULL_RTX)
3946           {
3947             rtx p = compute_frame_addr (offset, &next_scratch_regno);
3948             r = gen_rtx_REG (Pmode, next_scratch_regno--);
3949             reg_save_addr[which_scratch] = r;
3950
3951             emit_insn (gen_rtx_SET (VOIDmode, r, p));
3952           }
3953         else
3954           {
3955             /* Advance to the next stack slot to store this
3956                register.  */
3957             int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
3958             rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
3959             emit_insn (gen_rtx_SET (VOIDmode, r, p));
3960           }
3961
3962         /* Save this register to the stack (but use the old fp value
3963            we copied aside if appropriate).  */
3964         from_regno =
3965           (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
3966           ? fp_copy_regno : regno;
3967         FRP (frame_emit_store (from_regno, regno, r, cfa, cfa_offset));
3968
3969         offset -= UNITS_PER_WORD;
3970         which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
3971       }
3972
3973   /* If profiling, force that to happen after the frame is set up.  */
3974   if (crtl->profile)
3975     emit_insn (gen_blockage ());
3976
3977   /* Load the PIC register if needed.  */
3978   if (flag_pic && crtl->uses_pic_offset_table)
3979     load_pic_register (false);
3980 }
3981
3982
3983 /* Implement the epilogue and sibcall_epilogue patterns.  SIBCALL_P is
3984    true for a sibcall_epilogue pattern, and false for an epilogue
3985    pattern.  */
3986 void
3987 tilegx_expand_epilogue (bool sibcall_p)
3988 {
3989   /* We round-robin through four scratch registers to hold temporary
3990      addresses for saving registers, to make instruction scheduling
3991      easier.  */
3992   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
3993     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
3994   };
3995   rtx last_insn, insn;
3996   unsigned int which_scratch;
3997   int offset, start_offset, regno;
3998   rtx cfa_restores = NULL_RTX;
3999
4000   /* A register that holds a copy of the incoming fp.  */
4001   int fp_copy_regno = -1;
4002
4003   /* Next scratch register number to hand out (postdecrementing).  */
4004   int next_scratch_regno = 29;
4005
4006   int total_size = compute_total_frame_size ();
4007
4008   last_insn = get_last_insn ();
4009
4010   /* Load lr first since we are going to need it first.  */
4011   insn = NULL;
4012   if (df_regs_ever_live_p (TILEGX_LINK_REGNUM))
4013     {
4014       insn = frame_emit_load (TILEGX_LINK_REGNUM,
4015                               compute_frame_addr (0, &next_scratch_regno),
4016                               &cfa_restores);
4017     }
4018
4019   if (total_size == 0)
4020     {
4021       if (insn)
4022         {
4023           RTX_FRAME_RELATED_P (insn) = 1;
4024           REG_NOTES (insn) = cfa_restores;
4025         }
4026       goto done;
4027     }
4028
4029   /* Compute where to start restoring registers.  */
4030   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
4031   offset = start_offset;
4032
4033   if (frame_pointer_needed)
4034     fp_copy_regno = next_scratch_regno--;
4035
4036   /* Restore all callee-saved registers.  */
4037   which_scratch = 0;
4038   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
4039     if (need_to_save_reg (regno))
4040       {
4041         rtx r = reg_save_addr[which_scratch];
4042         if (r == NULL_RTX)
4043           {
4044             r = compute_frame_addr (offset, &next_scratch_regno);
4045             reg_save_addr[which_scratch] = r;
4046           }
4047         else
4048           {
4049             /* Advance to the next stack slot to store this register.  */
4050             int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
4051             rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
4052             emit_insn (gen_rtx_SET (VOIDmode, r, p));
4053           }
4054
4055         if (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
4056           frame_emit_load (fp_copy_regno, r, NULL);
4057         else
4058           frame_emit_load (regno, r, &cfa_restores);
4059
4060         offset -= UNITS_PER_WORD;
4061         which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
4062       }
4063
4064   if (!tilegx_current_function_is_leaf ())
4065     cfa_restores =
4066       alloc_reg_note (REG_CFA_RESTORE, stack_pointer_rtx, cfa_restores);
4067
4068   emit_insn (gen_blockage ());
4069
4070   if (crtl->calls_eh_return)
4071     {
4072       rtx r = compute_frame_addr (-total_size + UNITS_PER_WORD,
4073                                   &next_scratch_regno);
4074       insn = emit_move_insn (gen_lowpart (DImode, stack_pointer_rtx),
4075                              gen_frame_mem (DImode, r));
4076       RTX_FRAME_RELATED_P (insn) = 1;
4077       REG_NOTES (insn) = cfa_restores;
4078     }
4079   else if (frame_pointer_needed)
4080     {
4081       /* Restore the old stack pointer by copying from the frame
4082          pointer.  */
4083       if (TARGET_32BIT)
4084         {
4085           insn = emit_insn (gen_sp_restore_32bit (stack_pointer_rtx,
4086                                                   hard_frame_pointer_rtx));
4087         }
4088       else
4089         {
4090           insn = emit_insn (gen_sp_restore (stack_pointer_rtx,
4091                                             hard_frame_pointer_rtx));
4092         }
4093       RTX_FRAME_RELATED_P (insn) = 1;
4094       REG_NOTES (insn) = cfa_restores;
4095       add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
4096     }
4097   else
4098     {
4099       insn = emit_sp_adjust (total_size, &next_scratch_regno, true,
4100                              cfa_restores);
4101     }
4102
4103   /* Restore the old frame pointer.  */
4104   if (frame_pointer_needed)
4105     {
4106       insn = emit_move_insn (gen_lowpart (DImode, hard_frame_pointer_rtx),
4107                              gen_rtx_REG (DImode, fp_copy_regno));
4108       add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
4109     }
4110
4111   /* Mark the pic registers as live outside of the function.  */
4112   if (flag_pic)
4113     {
4114       emit_use (cfun->machine->text_label_rtx);
4115       emit_use (cfun->machine->got_rtx);
4116     }
4117
4118 done:
4119   if (!sibcall_p)
4120     {
4121       emit_jump_insn (gen__return ());
4122     }
4123   else
4124     {
4125       emit_use (gen_rtx_REG (Pmode, TILEGX_LINK_REGNUM));
4126     }
4127
4128   /* Mark all insns we just emitted as frame-related.  */
4129   for (; last_insn != NULL_RTX; last_insn = next_insn (last_insn))
4130     RTX_FRAME_RELATED_P (last_insn) = 1;
4131 }
4132
4133 #undef ROUND_ROBIN_SIZE
4134
4135
4136 /* Implement INITIAL_ELIMINATION_OFFSET.  */
4137 int
4138 tilegx_initial_elimination_offset (int from, int to)
4139 {
4140   int total_size = compute_total_frame_size ();
4141
4142   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
4143     {
4144       return (total_size - crtl->args.pretend_args_size
4145               - tilegx_saved_regs_size ());
4146     }
4147   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
4148     {
4149       return -(crtl->args.pretend_args_size + tilegx_saved_regs_size ());
4150     }
4151   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
4152     {
4153       return STACK_POINTER_OFFSET + total_size;
4154     }
4155   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
4156     {
4157       return STACK_POINTER_OFFSET;
4158     }
4159   else
4160     gcc_unreachable ();
4161 }
4162
4163
4164 /* Return an RTX indicating where the return address to the calling
4165    function can be found.  */
4166 rtx
4167 tilegx_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
4168 {
4169   if (count != 0)
4170     return const0_rtx;
4171
4172   return get_hard_reg_initial_val (Pmode, TILEGX_LINK_REGNUM);
4173 }
4174
4175
4176 /* Implement EH_RETURN_HANDLER_RTX.  The MEM needs to be volatile to
4177    prevent it from being deleted.  */
4178 rtx
4179 tilegx_eh_return_handler_rtx (void)
4180 {
4181   rtx tmp = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
4182   MEM_VOLATILE_P (tmp) = true;
4183   return tmp;
4184 }
4185 \f
4186
4187
4188 /* Registers  */
4189
4190 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE.  */
4191 static void
4192 tilegx_conditional_register_usage (void)
4193 {
4194   global_regs[TILEGX_NETORDER_REGNUM] = 1;
4195   /* TILEGX_PIC_TEXT_LABEL_REGNUM is conditionally used.  It is a
4196      member of fixed_regs, and therefore must be member of
4197      call_used_regs, but it is not a member of call_really_used_regs[]
4198      because it is not clobbered by a call.  */
4199   if (TILEGX_PIC_TEXT_LABEL_REGNUM != INVALID_REGNUM)
4200     {
4201       fixed_regs[TILEGX_PIC_TEXT_LABEL_REGNUM] = 1;
4202       call_used_regs[TILEGX_PIC_TEXT_LABEL_REGNUM] = 1;
4203     }
4204   if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
4205     {
4206       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4207       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
4208     }
4209 }
4210
4211
4212 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
4213 static bool
4214 tilegx_frame_pointer_required (void)
4215 {
4216   return crtl->calls_eh_return || cfun->calls_alloca;
4217 }
4218 \f
4219
4220
4221 /* Scheduling and reorg  */
4222
4223 /* Return the length of INSN.  LENGTH is the initial length computed
4224    by attributes in the machine-description file.  This is where we
4225    account for bundles.  */
4226 int
4227 tilegx_adjust_insn_length (rtx insn, int length)
4228 {
4229   enum machine_mode mode = GET_MODE (insn);
4230
4231   /* A non-termininating instruction in a bundle has length 0.  */
4232   if (mode == SImode)
4233     return 0;
4234
4235   /* By default, there is not length adjustment.  */
4236   return length;
4237 }
4238
4239
4240 /* Implement TARGET_SCHED_ISSUE_RATE.  */
4241 static int
4242 tilegx_issue_rate (void)
4243 {
4244   return 3;
4245 }
4246
4247
4248 /* Return the rtx for the jump target.  */
4249 static rtx
4250 get_jump_target (rtx branch)
4251 {
4252   if (CALL_P (branch))
4253     {
4254       rtx call;
4255       call = PATTERN (branch);
4256
4257       if (GET_CODE (call) == PARALLEL)
4258         call = XVECEXP (call, 0, 0);
4259
4260       if (GET_CODE (call) == SET)
4261         call = SET_SRC (call);
4262
4263       if (GET_CODE (call) == CALL)
4264         return XEXP (XEXP (call, 0), 0);
4265     }
4266   return 0;
4267 }
4268
4269 /* Implement TARGET_SCHED_ADJUST_COST.  */
4270 static int
4271 tilegx_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
4272 {
4273   /* If we have a true dependence, INSN is a call, and DEP_INSN
4274      defines a register that is needed by the call (argument or stack
4275      pointer) , set its latency to 0 so that it can be bundled with
4276      the call.  Explicitly check for and exclude the case when
4277      DEP_INSN defines the target of the jump.  */
4278   if (CALL_P (insn) && REG_NOTE_KIND (link) == REG_DEP_TRUE)
4279     {
4280       rtx target = get_jump_target (insn);
4281       if (!REG_P (target) || !set_of (target, dep_insn))
4282         return 0;
4283     }
4284
4285   return cost;
4286 }
4287
4288
4289 /* Skip over irrelevant NOTEs and such and look for the next insn we
4290    would consider bundling.  */
4291 static rtx
4292 next_insn_to_bundle (rtx r, rtx end)
4293 {
4294   for (; r != end; r = NEXT_INSN (r))
4295     {
4296       if (NONDEBUG_INSN_P (r)
4297           && GET_CODE (PATTERN (r)) != USE
4298           && GET_CODE (PATTERN (r)) != CLOBBER)
4299         return r;
4300     }
4301
4302   return NULL_RTX;
4303 }
4304
4305
4306 /* Go through all insns, and use the information generated during
4307    scheduling to generate SEQUENCEs to represent bundles of
4308    instructions issued simultaneously.  */
4309 static void
4310 tilegx_gen_bundles (void)
4311 {
4312   basic_block bb;
4313   FOR_EACH_BB (bb)
4314   {
4315     rtx insn, next;
4316     rtx end = NEXT_INSN (BB_END (bb));
4317
4318     for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; insn = next)
4319       {
4320         next = next_insn_to_bundle (NEXT_INSN (insn), end);
4321
4322         /* Never wrap {} around inline asm.  */
4323         if (GET_CODE (PATTERN (insn)) != ASM_INPUT)
4324           {
4325             if (next == NULL_RTX || GET_MODE (next) == TImode
4326                 /* NOTE: The scheduler incorrectly believes a call
4327                    insn can execute in the same cycle as the insn
4328                    after the call.  This is of course impossible.
4329                    Really we need to fix the scheduler somehow, so
4330                    the code after the call gets scheduled
4331                    optimally.  */
4332                 || CALL_P (insn))
4333               {
4334                 /* Mark current insn as the end of a bundle.  */
4335                 PUT_MODE (insn, QImode);
4336               }
4337             else
4338               {
4339                 /* Mark it as part of a bundle.  */
4340                 PUT_MODE (insn, SImode);
4341               }
4342           }
4343       }
4344   }
4345 }
4346
4347
4348 /* Replace OLD_INSN with NEW_INSN.  */
4349 static void
4350 replace_insns (rtx old_insn, rtx new_insns)
4351 {
4352   if (new_insns)
4353     emit_insn_before (new_insns, old_insn);
4354
4355   delete_insn (old_insn);
4356 }
4357
4358
4359 /* Returns true if INSN is the first instruction of a pc-relative
4360    address compuatation.  */
4361 static bool
4362 match_pcrel_step1 (rtx insn)
4363 {
4364   rtx pattern = PATTERN (insn);
4365   rtx src;
4366
4367   if (GET_CODE (pattern) != SET)
4368     return false;
4369
4370   src = SET_SRC (pattern);
4371
4372   return (GET_CODE (src) == CONST
4373           && GET_CODE (XEXP (src, 0)) == UNSPEC
4374           && XINT (XEXP (src, 0), 1) == UNSPEC_HW1_LAST_PCREL);
4375 }
4376
4377
4378 /* Do the first replacement step in tilegx_fixup_pcrel_references.  */
4379 static void
4380 replace_mov_pcrel_step1 (rtx insn)
4381 {
4382   rtx pattern = PATTERN (insn);
4383   rtx unspec;
4384   rtx opnds[2];
4385   rtx new_insns;
4386
4387   gcc_assert (GET_CODE (pattern) == SET);
4388   opnds[0] = SET_DEST (pattern);
4389
4390   gcc_assert (GET_CODE (SET_SRC (pattern)) == CONST);
4391
4392   unspec = XEXP (SET_SRC (pattern), 0);
4393   gcc_assert (GET_CODE (unspec) == UNSPEC);
4394   gcc_assert (XINT (unspec, 1) == UNSPEC_HW1_LAST_PCREL);
4395   opnds[1] = XVECEXP (unspec, 0, 0);
4396
4397   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4398   if (GET_CODE (opnds[1]) != SYMBOL_REF)
4399     return;
4400
4401   start_sequence ();
4402
4403   if (flag_pic != 1)
4404     {
4405       if (TARGET_32BIT)
4406         emit_insn (gen_mov_got32_step1_32bit (opnds[0], opnds[1]));
4407       else
4408         emit_insn (gen_mov_got32_step1 (opnds[0], opnds[1]));
4409     }
4410
4411   new_insns = get_insns ();
4412   end_sequence ();
4413
4414   replace_insns (insn, new_insns);
4415 }
4416
4417
4418 /* Returns true if INSN is the second instruction of a pc-relative
4419    address compuatation.  */
4420 static bool
4421 match_pcrel_step2 (rtx insn)
4422 {
4423   rtx src;
4424   if (TARGET_32BIT)
4425     {
4426       if (recog_memoized (insn) != CODE_FOR_insn_addr_shl16insli_32bit)
4427         return false;
4428     }
4429   else
4430     {
4431       if (recog_memoized (insn) != CODE_FOR_insn_addr_shl16insli)
4432         return false;
4433     }
4434
4435   src = SET_SRC (PATTERN (insn));
4436
4437   return (GET_CODE (src) == CONST
4438           && GET_CODE (XEXP (src, 0)) == UNSPEC
4439           && XINT (XEXP (src, 0), 1) == UNSPEC_HW0_PCREL);
4440 }
4441
4442
4443 /* Do the second replacement step in tilegx_fixup_pcrel_references.  */
4444 static void
4445 replace_mov_pcrel_step2 (rtx insn)
4446 {
4447   rtx pattern = PATTERN (insn);
4448   rtx unspec;
4449   rtx opnds[3];
4450   rtx new_insns;
4451   rtx got_rtx = tilegx_got_rtx ();
4452
4453   gcc_assert (GET_CODE (pattern) == SET);
4454   opnds[0] = SET_DEST (pattern);
4455
4456   unspec = XEXP (SET_SRC (pattern), 0);
4457   gcc_assert (GET_CODE (unspec) == UNSPEC);
4458   gcc_assert (XINT (unspec, 1) == UNSPEC_HW0_PCREL);
4459   opnds[1] = XEXP (XEXP (SET_SRC (pattern), 0), 0);
4460   opnds[2] = XVECEXP (unspec, 0, 0);
4461
4462   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4463   if (GET_CODE (opnds[2]) != SYMBOL_REF)
4464     return;
4465
4466   start_sequence ();
4467
4468   if (flag_pic == 1)
4469     {
4470       if (TARGET_32BIT)
4471         emit_insn (gen_add_got16_32bit (opnds[0], got_rtx, opnds[2]));
4472       else
4473         emit_insn (gen_add_got16 (opnds[0], got_rtx, opnds[2]));
4474     }
4475   else
4476     {
4477       if (TARGET_32BIT)
4478         emit_insn (gen_mov_got32_step2_32bit
4479                    (opnds[0], opnds[1], opnds[2]));
4480       else
4481         emit_insn (gen_mov_got32_step2 (opnds[0], opnds[1], opnds[2]));
4482     }
4483
4484   new_insns = get_insns ();
4485   end_sequence ();
4486
4487   replace_insns (insn, new_insns);
4488 }
4489
4490
4491 /* Do the third replacement step in tilegx_fixup_pcrel_references.  */
4492 static void
4493 replace_mov_pcrel_step3 (rtx insn)
4494 {
4495   rtx pattern = PATTERN (insn);
4496   rtx unspec;
4497   rtx opnds[4];
4498   rtx new_insns;
4499   rtx got_rtx = tilegx_got_rtx ();
4500   rtx text_label_rtx = tilegx_text_label_rtx ();
4501
4502   gcc_assert (GET_CODE (pattern) == SET);
4503   opnds[0] = SET_DEST (pattern);
4504
4505   unspec = SET_SRC (pattern);
4506   gcc_assert (GET_CODE (unspec) == UNSPEC);
4507   gcc_assert (XINT (unspec, 1) == UNSPEC_MOV_PCREL_STEP3);
4508
4509   opnds[1] = got_rtx;
4510
4511   if (XVECEXP (unspec, 0, 0) == text_label_rtx)
4512     opnds[2] = XVECEXP (unspec, 0, 1);
4513   else
4514     {
4515       gcc_assert (XVECEXP (unspec, 0, 1) == text_label_rtx);
4516       opnds[2] = XVECEXP (unspec, 0, 0);
4517     }
4518
4519   opnds[3] = XVECEXP (unspec, 0, 2);
4520
4521   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
4522   if (GET_CODE (opnds[3]) != SYMBOL_REF)
4523     return;
4524
4525   start_sequence ();
4526
4527   if (flag_pic == 1)
4528     {
4529       emit_move_insn (opnds[0], gen_const_mem (Pmode, opnds[2]));
4530     }
4531   else
4532     {
4533       emit_move_insn (opnds[0], gen_rtx_PLUS (Pmode, opnds[1], opnds[2]));
4534       emit_move_insn (opnds[0], gen_const_mem (Pmode, opnds[0]));
4535     }
4536
4537   new_insns = get_insns ();
4538   end_sequence ();
4539
4540   replace_insns (insn, new_insns);
4541 }
4542
4543
4544 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid
4545    going through the GOT when the symbol is local to the compilation
4546    unit.  But such a symbol requires that the common text_label that
4547    we generate at the beginning of the function be in the same section
4548    as the reference to the SYMBOL_REF.  This may not be true if we
4549    generate hot/cold sections.  This function looks for such cases and
4550    replaces such references with the longer sequence going through the
4551    GOT.
4552
4553    We expect following instruction sequence:
4554    moveli      tmp1, hw1_last(x-.L_PICLNK)          [1]
4555    shl16insli  tmp2, tmp1, hw0(x-.L_PICLNK)         [2]
4556    add<x>      tmp3, txt_label_reg, tmp2            [3]
4557
4558    If we're compiling -fpic, we replace with the following sequence
4559    (the numbers in brackets match the instructions they're replacing
4560    above).
4561
4562    add<x>li    tmp2, got_reg, hw0_last_got(x)       [2]
4563    ld<4>       tmp3, tmp2                           [3]
4564
4565    If we're compiling -fPIC, we replace the first instruction with:
4566
4567    moveli      tmp1, hw1_last_got(x)                [1]
4568    shl16insli  tmp2, tmp1, hw0_got(x)               [2]
4569    add<x>      tmp3, got_reg, tmp2                  [3]
4570    ld<4>       tmp3, tmp3                           [3]
4571
4572    Note that we're careful to disturb the instruction sequence as
4573    little as possible, since it's very late in the compilation
4574    process.  */
4575 static void
4576 tilegx_fixup_pcrel_references (void)
4577 {
4578   rtx insn, next_insn;
4579   bool same_section_as_entry = true;
4580
4581   for (insn = get_insns (); insn; insn = next_insn)
4582     {
4583       next_insn = NEXT_INSN (insn);
4584
4585       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
4586         {
4587           same_section_as_entry = !same_section_as_entry;
4588           continue;
4589         }
4590
4591       if (same_section_as_entry)
4592         continue;
4593
4594       if (!(INSN_P (insn)
4595             && GET_CODE (PATTERN (insn)) != USE
4596             && GET_CODE (PATTERN (insn)) != CLOBBER))
4597         continue;
4598
4599       if (TARGET_32BIT)
4600         {
4601           if (match_pcrel_step1 (insn))
4602             replace_mov_pcrel_step1 (insn);
4603           else if (match_pcrel_step2 (insn))
4604             replace_mov_pcrel_step2 (insn);
4605           else if (recog_memoized (insn) == CODE_FOR_mov_pcrel_step3_32bit)
4606             replace_mov_pcrel_step3 (insn);
4607         }
4608       else
4609         {
4610           if (match_pcrel_step1 (insn))
4611             replace_mov_pcrel_step1 (insn);
4612           else if (match_pcrel_step2 (insn))
4613             replace_mov_pcrel_step2 (insn);
4614           else if (recog_memoized (insn) == CODE_FOR_mov_pcrel_step3)
4615             replace_mov_pcrel_step3 (insn);
4616         }
4617     }
4618 }
4619
4620
4621 /* Ensure that no var tracking notes are emitted in the middle of a
4622    three-instruction bundle.  */
4623 static void
4624 reorder_var_tracking_notes (void)
4625 {
4626   basic_block bb;
4627   FOR_EACH_BB (bb)
4628   {
4629     rtx insn, next;
4630     rtx queue = NULL_RTX;
4631     bool in_bundle = false;
4632
4633     for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4634       {
4635         next = NEXT_INSN (insn);
4636
4637         if (INSN_P (insn))
4638           {
4639             /* Emit queued up notes at the last instruction of a
4640                bundle.  */
4641             if (GET_MODE (insn) == QImode)
4642               {
4643                 while (queue)
4644                   {
4645                     rtx next_queue = PREV_INSN (queue);
4646                     PREV_INSN (NEXT_INSN (insn)) = queue;
4647                     NEXT_INSN (queue) = NEXT_INSN (insn);
4648                     NEXT_INSN (insn) = queue;
4649                     PREV_INSN (queue) = insn;
4650                     queue = next_queue;
4651                   }
4652                 in_bundle = false;
4653               }
4654             else if (GET_MODE (insn) == SImode)
4655               in_bundle = true;
4656           }
4657         else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4658           {
4659             if (in_bundle)
4660               {
4661                 rtx prev = PREV_INSN (insn);
4662                 PREV_INSN (next) = prev;
4663                 NEXT_INSN (prev) = next;
4664
4665                 PREV_INSN (insn) = queue;
4666                 queue = insn;
4667               }
4668           }
4669       }
4670   }
4671 }
4672
4673
4674 /* Perform machine dependent operations on the rtl chain INSNS.  */
4675 static void
4676 tilegx_reorg (void)
4677 {
4678   /* We are freeing block_for_insn in the toplev to keep compatibility
4679      with old MDEP_REORGS that are not CFG based.  Recompute it
4680      now.  */
4681   compute_bb_for_insn ();
4682
4683   if (flag_reorder_blocks_and_partition)
4684     {
4685       tilegx_fixup_pcrel_references ();
4686     }
4687
4688   if (flag_schedule_insns_after_reload)
4689     {
4690       split_all_insns ();
4691
4692       timevar_push (TV_SCHED2);
4693       schedule_insns ();
4694       timevar_pop (TV_SCHED2);
4695
4696       /* Examine the schedule to group into bundles.  */
4697       tilegx_gen_bundles ();
4698     }
4699
4700   df_analyze ();
4701
4702   if (flag_var_tracking)
4703     {
4704       timevar_push (TV_VAR_TRACKING);
4705       variable_tracking_main ();
4706       reorder_var_tracking_notes ();
4707       timevar_pop (TV_VAR_TRACKING);
4708     }
4709
4710   df_finish_pass (false);
4711 }
4712 \f
4713
4714
4715 /* Assembly  */
4716
4717 /* Select a format to encode pointers in exception handling data.
4718    CODE is 0 for data, 1 for code labels, 2 for function pointers.
4719    GLOBAL is true if the symbol may be affected by dynamic
4720    relocations.  */
4721 int
4722 tilegx_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
4723 {
4724   if (flag_pic)
4725     {
4726       int type = TARGET_32BIT ? DW_EH_PE_sdata4 : DW_EH_PE_sdata8;
4727       return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
4728     }
4729   else
4730     return DW_EH_PE_absptr;
4731 }
4732
4733
4734 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  */
4735 static void
4736 tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
4737                         HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
4738                         tree function)
4739 {
4740   rtx this_rtx, insn, funexp, addend;
4741
4742   /* Pretend to be a post-reload pass while generating rtl.  */
4743   reload_completed = 1;
4744
4745   /* Mark the end of the (empty) prologue.  */
4746   emit_note (NOTE_INSN_PROLOGUE_END);
4747
4748   /* Find the "this" pointer.  If the function returns a structure,
4749      the structure return pointer is in $1.  */
4750   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
4751     this_rtx = gen_rtx_REG (Pmode, 1);
4752   else
4753     this_rtx = gen_rtx_REG (Pmode, 0);
4754
4755   /* Add DELTA to THIS_RTX.  */
4756   if (!(delta >= -32868 && delta <= 32767))
4757     {
4758       addend = gen_rtx_REG (Pmode, 29);
4759       emit_move_insn (addend, GEN_INT (delta));
4760     }
4761   else
4762     addend = GEN_INT (delta);
4763
4764   if (TARGET_32BIT)
4765     emit_insn (gen_addsi3 (this_rtx, this_rtx, addend));
4766   else
4767     emit_insn (gen_adddi3 (this_rtx, this_rtx, addend));
4768
4769   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
4770   if (vcall_offset)
4771     {
4772       rtx tmp;
4773
4774       tmp = gen_rtx_REG (Pmode, 29);
4775       emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
4776
4777       if (!(vcall_offset >= -32868 && vcall_offset <= 32767))
4778         {
4779           addend = gen_rtx_REG (Pmode, 28);
4780           emit_move_insn (addend, GEN_INT (vcall_offset));
4781         }
4782       else
4783         addend = GEN_INT (vcall_offset);
4784
4785       if (TARGET_32BIT)
4786         emit_insn (gen_addsi3 (tmp, tmp, addend));
4787       else
4788         emit_insn (gen_adddi3 (tmp, tmp, addend));
4789
4790       emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
4791
4792       if (TARGET_32BIT)
4793         emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp));
4794       else
4795         emit_insn (gen_adddi3 (this_rtx, this_rtx, tmp));
4796     }
4797
4798   /* Generate a tail call to the target function.  */
4799   if (!TREE_USED (function))
4800     {
4801       assemble_external (function);
4802       TREE_USED (function) = 1;
4803     }
4804   funexp = XEXP (DECL_RTL (function), 0);
4805   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
4806   insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
4807   SIBLING_CALL_P (insn) = 1;
4808
4809   /* Run just enough of rest_of_compilation to get the insns emitted.
4810      There's not really enough bulk here to make other passes such as
4811      instruction scheduling worth while.  Note that use_thunk calls
4812      assemble_start_function and assemble_end_function.
4813
4814      We don't currently bundle, but the instruciton sequence is all
4815      serial except for the tail call, so we're only wasting one cycle.
4816    */
4817   insn = get_insns ();
4818   insn_locators_alloc ();
4819   shorten_branches (insn);
4820   final_start_function (insn, file, 1);
4821   final (insn, file, 1);
4822   final_end_function ();
4823
4824   /* Stop pretending to be a post-reload pass.  */
4825   reload_completed = 0;
4826 }
4827
4828
4829 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
4830 static void
4831 tilegx_asm_trampoline_template (FILE *file)
4832 {
4833   int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
4834   if (TARGET_32BIT)
4835     {
4836       fprintf (file, "\tlnk      r10\n");
4837       fprintf (file, "\taddxi    r10, r10, 32\n");
4838       fprintf (file, "\tld4s_add r11, r10, %d\n", ptr_mode_size);
4839       fprintf (file, "\tld4s     r10, r10\n");
4840       fprintf (file, "\tjr       r11\n");
4841       fprintf (file, "\t.word 0 # <function address>\n");
4842       fprintf (file, "\t.word 0 # <static chain value>\n");
4843     }
4844   else
4845     {
4846       fprintf (file, "\tlnk      r10\n");
4847       fprintf (file, "\taddi     r10, r10, 32\n");
4848       fprintf (file, "\tld_add   r11, r10, %d\n", ptr_mode_size);
4849       fprintf (file, "\tld       r10, r10\n");
4850       fprintf (file, "\tjr       r11\n");
4851       fprintf (file, "\t.quad 0 # <function address>\n");
4852       fprintf (file, "\t.quad 0 # <static chain value>\n");
4853     }
4854 }
4855
4856
4857 /* Implement TARGET_TRAMPOLINE_INIT.  */
4858 static void
4859 tilegx_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
4860 {
4861   rtx fnaddr, chaddr;
4862   rtx mem;
4863   rtx begin_addr, end_addr;
4864   int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
4865
4866   fnaddr = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
4867   chaddr = copy_to_reg (static_chain);
4868
4869   emit_block_move (m_tramp, assemble_trampoline_template (),
4870                    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
4871
4872   mem = adjust_address (m_tramp, ptr_mode,
4873                         TRAMPOLINE_SIZE - 2 * ptr_mode_size);
4874   emit_move_insn (mem, fnaddr);
4875   mem = adjust_address (m_tramp, ptr_mode,
4876                         TRAMPOLINE_SIZE - ptr_mode_size);
4877   emit_move_insn (mem, chaddr);
4878
4879   /* Get pointers to the beginning and end of the code block.  */
4880   begin_addr = force_reg (Pmode, XEXP (m_tramp, 0));
4881   end_addr = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0),
4882                                               TRAMPOLINE_SIZE));
4883
4884   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
4885                      LCT_NORMAL, VOIDmode, 2, begin_addr, Pmode,
4886                      end_addr, Pmode);
4887 }
4888
4889
4890 /* Implement TARGET_PRINT_OPERAND.  */
4891 static void
4892 tilegx_print_operand (FILE *file, rtx x, int code)
4893 {
4894   switch (code)
4895     {
4896     case 'c':
4897       /* Print the compare operator opcode for conditional moves. */
4898       switch (GET_CODE (x))
4899         {
4900         case EQ:
4901           fputs ("z", file);
4902           break;
4903         case NE:
4904           fputs ("nz", file);
4905           break;
4906         default:
4907           output_operand_lossage ("invalid %%c operand");
4908         }
4909       return;
4910
4911     case 'C':
4912       /* Print the compare operator opcode for conditional moves. */
4913       switch (GET_CODE (x))
4914         {
4915         case EQ:
4916           fputs ("nz", file);
4917           break;
4918         case NE:
4919           fputs ("z", file);
4920           break;
4921         default:
4922           output_operand_lossage ("invalid %%C operand");
4923         }
4924       return;
4925
4926     case 'd':
4927       {
4928         /* Print the compare operator opcode for conditional moves. */
4929         switch (GET_CODE (x))
4930           {
4931           case EQ:
4932             fputs ("eq", file);
4933             break;
4934           case NE:
4935             fputs ("ne", file);
4936             break;
4937           default:
4938             output_operand_lossage ("invalid %%d operand");
4939           }
4940         return;
4941       }
4942
4943     case 'D':
4944       {
4945         /* Print the compare operator opcode for conditional moves. */
4946         switch (GET_CODE (x))
4947           {
4948           case EQ:
4949             fputs ("ne", file);
4950             break;
4951           case NE:
4952             fputs ("eq", file);
4953             break;
4954           default:
4955             output_operand_lossage ("invalid %%D operand");
4956           }
4957         return;
4958       }
4959
4960     case 'H':
4961       {
4962       if (GET_CODE (x) == CONST
4963           && GET_CODE (XEXP (x, 0)) == UNSPEC)
4964         {
4965           rtx addr = XVECEXP (XEXP (x, 0), 0, 0);
4966           int unspec = XINT (XEXP (x, 0), 1);
4967           const char *opstr = NULL;
4968           switch (unspec)
4969             {
4970             case UNSPEC_HW0:
4971             case UNSPEC_HW0_PCREL:
4972               opstr = "hw0";
4973               break;
4974             case UNSPEC_HW1:
4975               opstr = "hw1";
4976               break;
4977             case UNSPEC_HW2:
4978               opstr = "hw2";
4979               break;
4980             case UNSPEC_HW3:
4981               opstr = "hw3";
4982               break;
4983             case UNSPEC_HW0_LAST:
4984               opstr = "hw0_last";
4985               break;
4986             case UNSPEC_HW1_LAST:
4987             case UNSPEC_HW1_LAST_PCREL:
4988               opstr = "hw1_last";
4989               break;
4990             case UNSPEC_HW2_LAST:
4991               opstr = "hw2_last";
4992               break;
4993             case UNSPEC_HW0_GOT:
4994               opstr = "hw0_got";
4995               break;
4996             case UNSPEC_HW0_LAST_GOT:
4997               opstr = "hw0_last_got";
4998               break;
4999             case UNSPEC_HW1_LAST_GOT:
5000               opstr = "hw1_last_got";
5001               break;
5002             case UNSPEC_HW0_TLS_GD:
5003               opstr = "hw0_tls_gd";
5004               break;
5005             case UNSPEC_HW1_LAST_TLS_GD:
5006               opstr = "hw1_last_tls_gd";
5007               break;
5008             case UNSPEC_HW0_TLS_IE:
5009               opstr = "hw0_tls_ie";
5010               break;
5011             case UNSPEC_HW1_LAST_TLS_IE:
5012               opstr = "hw1_last_tls_ie";
5013               break;
5014             case UNSPEC_HW0_TLS_LE:
5015               opstr = "hw0_tls_le";
5016               break;
5017             case UNSPEC_HW1_LAST_TLS_LE:
5018               opstr = "hw1_last_tls_le";
5019               break;
5020             default:
5021               output_operand_lossage ("invalid %%H specifier");
5022             }
5023
5024           fputs (opstr, file);
5025           fputc ('(', file);
5026           output_addr_const (file, addr);
5027
5028           if (unspec == UNSPEC_HW0_PCREL
5029               || unspec == UNSPEC_HW1_LAST_PCREL)
5030             {
5031               rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
5032               fputs (" - " , file);
5033               output_addr_const (file, addr2);
5034             }
5035
5036           fputc (')', file);
5037           return;
5038         }
5039       else if (symbolic_operand (x, VOIDmode))
5040         {
5041           output_addr_const (file, x);
5042           return;
5043         }
5044       }
5045       /* FALLTHRU */
5046
5047     case 'h':
5048       {
5049         /* Print the low 16 bits of a constant.  */
5050         HOST_WIDE_INT i;
5051         if (CONST_INT_P (x))
5052           i = INTVAL (x);
5053         else if (GET_CODE (x) == CONST_DOUBLE)
5054           i = CONST_DOUBLE_LOW (x);
5055         else
5056           {
5057             output_operand_lossage ("invalid %%h operand");
5058             return;
5059           }
5060         i = trunc_int_for_mode (i, HImode);
5061         fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
5062         return;
5063       }
5064
5065     case 'I':
5066       /* Print an auto-inc memory operand.  */
5067       if (!MEM_P (x))
5068         {
5069           output_operand_lossage ("invalid %%I operand");
5070           return;
5071         }
5072
5073       output_memory_reference_mode = GET_MODE (x);
5074       output_memory_autoinc_first = true;
5075       output_address (XEXP (x, 0));
5076       output_memory_reference_mode = VOIDmode;
5077       return;
5078
5079     case 'i':
5080       /* Print an auto-inc memory operand.  */
5081       if (!MEM_P (x))
5082         {
5083           output_operand_lossage ("invalid %%i operand");
5084           return;
5085         }
5086
5087       output_memory_reference_mode = GET_MODE (x);
5088       output_memory_autoinc_first = false;
5089       output_address (XEXP (x, 0));
5090       output_memory_reference_mode = VOIDmode;
5091       return;
5092
5093     case 'j':
5094       {
5095         /* Print the low 8 bits of a constant.  */
5096         HOST_WIDE_INT i;
5097         if (CONST_INT_P (x))
5098           i = INTVAL (x);
5099         else if (GET_CODE (x) == CONST_DOUBLE)
5100           i = CONST_DOUBLE_LOW (x);
5101         else if (GET_CODE (x) == CONST_VECTOR
5102                  && CONST_INT_P (CONST_VECTOR_ELT (x, 0)))
5103           i = INTVAL (CONST_VECTOR_ELT (x, 0));
5104         else
5105           {
5106             output_operand_lossage ("invalid %%j operand");
5107             return;
5108           }
5109         i = trunc_int_for_mode (i, QImode);
5110         fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
5111         return;
5112       }
5113
5114     case 'P':
5115       {
5116         /* Print a constant plus one.  */
5117         if (!CONST_INT_P (x))
5118           {
5119             output_operand_lossage ("invalid %%P operand");
5120             return;
5121           }
5122         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + 1);
5123         return;
5124       }
5125
5126     case 'm':
5127     case 'M':
5128       {
5129         /* Print a bfextu-style bit range.  */
5130         int first_bit, last_bit;
5131         HOST_WIDE_INT flip = (code == 'm') ? ~0 : 0;
5132
5133         if (!CONST_INT_P (x)
5134             || !tilegx_bitfield_operand_p (INTVAL (x) ^ flip,
5135                                            &first_bit, &last_bit))
5136           {
5137             output_operand_lossage ("invalid %%%c operand", code);
5138             return;
5139           }
5140
5141         fprintf (file, "%d, %d", first_bit, last_bit);
5142         return;
5143       }
5144
5145     case 'N':
5146       {
5147         const char *reg = NULL;
5148
5149         /* Print a network register.  */
5150         if (!CONST_INT_P (x))
5151           {
5152             output_operand_lossage ("invalid %%N operand");
5153             return;
5154           }
5155
5156         switch (INTVAL (x))
5157           {
5158           case TILEGX_NETREG_IDN0: reg = "idn0"; break;
5159           case TILEGX_NETREG_IDN1: reg = "idn1"; break;
5160           case TILEGX_NETREG_UDN0: reg = "udn0"; break;
5161           case TILEGX_NETREG_UDN1: reg = "udn1"; break;
5162           case TILEGX_NETREG_UDN2: reg = "udn2"; break;
5163           case TILEGX_NETREG_UDN3: reg = "udn3"; break;
5164           default:
5165             gcc_unreachable ();
5166           }
5167
5168         fprintf (file, reg);
5169         return;
5170       }
5171
5172     case 'p':
5173       if (GET_CODE (x) == SYMBOL_REF)
5174         {
5175           if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
5176             fprintf (file, "plt(");
5177           output_addr_const (file, x);
5178           if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
5179             fprintf (file, ")");
5180         }
5181       else
5182         output_addr_const (file, x);
5183       return;
5184
5185     case 'r':
5186       /* In this case we need a register.  Use 'zero' if the operand
5187          is const0_rtx.  */
5188       if (x == const0_rtx
5189           || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
5190         {
5191           fputs ("zero", file);
5192           return;
5193         }
5194       else if (!REG_P (x))
5195         {
5196           output_operand_lossage ("invalid operand for 'r' specifier");
5197           return;
5198         }
5199       /* FALLTHRU */
5200
5201     case 0:
5202       if (REG_P (x))
5203         {
5204           fprintf (file, "%s", reg_names[REGNO (x)]);
5205           return;
5206         }
5207       else if (MEM_P (x))
5208         {
5209           output_memory_reference_mode = VOIDmode;
5210           output_address (XEXP (x, 0));
5211           return;
5212         }
5213       else
5214         {
5215           output_addr_const (file, x);
5216           return;
5217         }
5218     }
5219
5220   debug_rtx (x);
5221   output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
5222                           code, code);
5223 }
5224
5225
5226 /* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
5227 static void
5228 tilegx_print_operand_address (FILE *file, rtx addr)
5229 {
5230   if (GET_CODE (addr) == POST_DEC
5231       || GET_CODE (addr) == POST_INC)
5232     {
5233       int offset = GET_MODE_SIZE (output_memory_reference_mode);
5234
5235       gcc_assert (output_memory_reference_mode != VOIDmode);
5236
5237       if (output_memory_autoinc_first)
5238         fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
5239       else
5240         fprintf (file, "%d",
5241                  GET_CODE (addr) == POST_DEC ? -offset : offset);
5242     }
5243   else if (GET_CODE (addr) == POST_MODIFY)
5244     {
5245       gcc_assert (output_memory_reference_mode != VOIDmode);
5246
5247       gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
5248
5249       if (output_memory_autoinc_first)
5250         fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
5251       else
5252         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
5253                  INTVAL (XEXP (XEXP (addr, 1), 1)));
5254     }
5255   else
5256     tilegx_print_operand (file, addr, 'r');
5257 }
5258
5259
5260 /* Machine mode of current insn, for determining curly brace
5261    placement.  */
5262 static enum machine_mode insn_mode;
5263
5264
5265 /* Implement FINAL_PRESCAN_INSN.  This is used to emit bundles.  */
5266 void
5267 tilegx_final_prescan_insn (rtx insn)
5268 {
5269   /* Record this for tilegx_asm_output_opcode to examine.  */
5270   insn_mode = GET_MODE (insn);
5271 }
5272
5273
5274 /* While emitting asm, are we currently inside '{' for a bundle? */
5275 static bool tilegx_in_bundle = false;
5276
5277 /* Implement ASM_OUTPUT_OPCODE.  Prepend/append curly braces as
5278    appropriate given the bundling information recorded by
5279    tilegx_gen_bundles.  */
5280 const char *
5281 tilegx_asm_output_opcode (FILE *stream, const char *code)
5282 {
5283   bool pseudo = !strcmp (code, "pseudo");
5284
5285   if (!tilegx_in_bundle && insn_mode == SImode)
5286     {
5287       /* Start a new bundle.  */
5288       fprintf (stream, "{\n\t");
5289       tilegx_in_bundle = true;
5290     }
5291
5292   if (tilegx_in_bundle && insn_mode == QImode)
5293     {
5294       /* Close an existing bundle.  */
5295       static char buf[100];
5296
5297       gcc_assert (strlen (code) + 3 + 1 < sizeof (buf));
5298
5299       strcpy (buf, pseudo ? "" : code);
5300       strcat (buf, "\n\t}");
5301       tilegx_in_bundle = false;
5302
5303       return buf;
5304     }
5305   else
5306     {
5307       return pseudo ? "" : code;
5308     }
5309 }
5310
5311
5312 /* Output assembler code to FILE to increment profiler label # LABELNO
5313    for profiling a function entry.  */
5314 void
5315 tilegx_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
5316 {
5317   if (tilegx_in_bundle)
5318     {
5319       fprintf (file, "\t}\n");
5320     }
5321
5322   if (flag_pic)
5323     {
5324       fprintf (file,
5325                "\t{\n"
5326                "\tmove\tr10, lr\n"
5327                "\tjal\t%s@plt\n"
5328                "\t}\n", MCOUNT_NAME);
5329     }
5330   else
5331     {
5332       fprintf (file,
5333                "\t{\n"
5334                "\tmove\tr10, lr\n"
5335                "\tjal\t%s\n"
5336                "\t}\t\n", MCOUNT_NAME);
5337     }
5338
5339   tilegx_in_bundle = false;
5340 }
5341
5342
5343 /* Implement TARGET_ASM_FILE_END.  */
5344 static void
5345 tilegx_file_end (void)
5346 {
5347   if (NEED_INDICATE_EXEC_STACK)
5348     file_end_indicate_exec_stack ();
5349 }
5350
5351
5352
5353 #undef  TARGET_HAVE_TLS
5354 #define TARGET_HAVE_TLS HAVE_AS_TLS
5355
5356 #undef  TARGET_OPTION_OVERRIDE
5357 #define TARGET_OPTION_OVERRIDE tilegx_option_override
5358
5359 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
5360 #define TARGET_SCALAR_MODE_SUPPORTED_P tilegx_scalar_mode_supported_p
5361
5362 #undef  TARGET_VECTOR_MODE_SUPPORTED_P
5363 #define TARGET_VECTOR_MODE_SUPPORTED_P tilegx_vector_mode_supported_p
5364
5365 #undef  TARGET_CANNOT_FORCE_CONST_MEM
5366 #define TARGET_CANNOT_FORCE_CONST_MEM tilegx_cannot_force_const_mem
5367
5368 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
5369 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilegx_function_ok_for_sibcall
5370
5371 #undef  TARGET_PASS_BY_REFERENCE
5372 #define TARGET_PASS_BY_REFERENCE tilegx_pass_by_reference
5373
5374 #undef  TARGET_RETURN_IN_MEMORY
5375 #define TARGET_RETURN_IN_MEMORY tilegx_return_in_memory
5376
5377 #undef  TARGET_MODE_REP_EXTENDED
5378 #define TARGET_MODE_REP_EXTENDED tilegx_mode_rep_extended
5379
5380 #undef  TARGET_FUNCTION_ARG_BOUNDARY
5381 #define TARGET_FUNCTION_ARG_BOUNDARY tilegx_function_arg_boundary
5382
5383 #undef  TARGET_FUNCTION_ARG
5384 #define TARGET_FUNCTION_ARG tilegx_function_arg
5385
5386 #undef  TARGET_FUNCTION_ARG_ADVANCE
5387 #define TARGET_FUNCTION_ARG_ADVANCE tilegx_function_arg_advance
5388
5389 #undef  TARGET_FUNCTION_VALUE
5390 #define TARGET_FUNCTION_VALUE tilegx_function_value
5391
5392 #undef  TARGET_LIBCALL_VALUE
5393 #define TARGET_LIBCALL_VALUE tilegx_libcall_value
5394
5395 #undef  TARGET_FUNCTION_VALUE_REGNO_P
5396 #define TARGET_FUNCTION_VALUE_REGNO_P tilegx_function_value_regno_p
5397
5398 #undef  TARGET_PROMOTE_FUNCTION_MODE
5399 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5400
5401 #undef  TARGET_PROMOTE_PROTOTYPES
5402 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
5403
5404 #undef  TARGET_BUILD_BUILTIN_VA_LIST
5405 #define TARGET_BUILD_BUILTIN_VA_LIST tilegx_build_builtin_va_list
5406
5407 #undef  TARGET_EXPAND_BUILTIN_VA_START
5408 #define TARGET_EXPAND_BUILTIN_VA_START tilegx_va_start
5409
5410 #undef  TARGET_SETUP_INCOMING_VARARGS
5411 #define TARGET_SETUP_INCOMING_VARARGS tilegx_setup_incoming_varargs
5412
5413 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
5414 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilegx_gimplify_va_arg_expr
5415
5416 #undef  TARGET_RTX_COSTS
5417 #define TARGET_RTX_COSTS tilegx_rtx_costs
5418
5419 #undef  TARGET_SHIFT_TRUNCATION_MASK
5420 #define TARGET_SHIFT_TRUNCATION_MASK tilegx_shift_truncation_mask
5421
5422 #undef  TARGET_INIT_LIBFUNCS
5423 #define TARGET_INIT_LIBFUNCS tilegx_init_libfuncs
5424
5425 /* Limit to what we can reach in one addli.  */
5426 #undef  TARGET_MIN_ANCHOR_OFFSET
5427 #define TARGET_MIN_ANCHOR_OFFSET -32768
5428 #undef  TARGET_MAX_ANCHOR_OFFSET
5429 #define TARGET_MAX_ANCHOR_OFFSET 32767
5430
5431 #undef  TARGET_LEGITIMATE_CONSTANT_P
5432 #define TARGET_LEGITIMATE_CONSTANT_P tilegx_legitimate_constant_p
5433
5434 #undef  TARGET_LEGITIMATE_ADDRESS_P
5435 #define TARGET_LEGITIMATE_ADDRESS_P tilegx_legitimate_address_p
5436
5437 #undef  TARGET_LEGITIMIZE_ADDRESS
5438 #define TARGET_LEGITIMIZE_ADDRESS tilegx_legitimize_address
5439
5440 #undef  TARGET_DELEGITIMIZE_ADDRESS
5441 #define TARGET_DELEGITIMIZE_ADDRESS tilegx_delegitimize_address
5442
5443 #undef  TARGET_INIT_BUILTINS
5444 #define TARGET_INIT_BUILTINS  tilegx_init_builtins
5445
5446 #undef  TARGET_BUILTIN_DECL
5447 #define TARGET_BUILTIN_DECL tilegx_builtin_decl
5448
5449 #undef   TARGET_EXPAND_BUILTIN
5450 #define TARGET_EXPAND_BUILTIN tilegx_expand_builtin
5451
5452 #undef  TARGET_CONDITIONAL_REGISTER_USAGE
5453 #define TARGET_CONDITIONAL_REGISTER_USAGE tilegx_conditional_register_usage
5454
5455 #undef  TARGET_FRAME_POINTER_REQUIRED
5456 #define TARGET_FRAME_POINTER_REQUIRED tilegx_frame_pointer_required
5457
5458 #undef  TARGET_DELAY_SCHED2
5459 #define TARGET_DELAY_SCHED2 true
5460
5461 #undef  TARGET_DELAY_VARTRACK
5462 #define TARGET_DELAY_VARTRACK true
5463
5464 #undef  TARGET_SCHED_ISSUE_RATE
5465 #define TARGET_SCHED_ISSUE_RATE tilegx_issue_rate
5466
5467 #undef  TARGET_SCHED_ADJUST_COST
5468 #define TARGET_SCHED_ADJUST_COST tilegx_sched_adjust_cost
5469
5470 #undef  TARGET_MACHINE_DEPENDENT_REORG
5471 #define TARGET_MACHINE_DEPENDENT_REORG tilegx_reorg
5472
5473 #undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
5474 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5475   hook_bool_const_tree_hwi_hwi_const_tree_true
5476
5477 #undef  TARGET_ASM_OUTPUT_MI_THUNK
5478 #define TARGET_ASM_OUTPUT_MI_THUNK tilegx_output_mi_thunk
5479
5480 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
5481 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilegx_asm_trampoline_template
5482
5483 #undef  TARGET_TRAMPOLINE_INIT
5484 #define TARGET_TRAMPOLINE_INIT tilegx_trampoline_init
5485
5486 #undef  TARGET_PRINT_OPERAND
5487 #define TARGET_PRINT_OPERAND tilegx_print_operand
5488
5489 #undef  TARGET_PRINT_OPERAND_ADDRESS
5490 #define TARGET_PRINT_OPERAND_ADDRESS tilegx_print_operand_address
5491
5492 #undef  TARGET_ASM_FILE_END
5493 #define TARGET_ASM_FILE_END tilegx_file_end
5494
5495 #undef  TARGET_ASM_ALIGNED_DI_OP
5496 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
5497
5498
5499 struct gcc_target targetm = TARGET_INITIALIZER;
5500
5501 #include "gt-tilegx.h"