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