1 /* Subroutines used for code generation on the Tilera TILEPro.
2 Copyright (C) 2011-2013 Free Software Foundation, Inc.
3 Contributed by Walter Lee (walt@tilera.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "insn-config.h"
29 #include "insn-attr.h"
32 #include "langhooks.h"
34 #include "sched-int.h"
35 #include "sel-sched.h"
37 #include "tm-constrs.h"
39 #include "target-def.h"
46 #include "tilepro-builtins.h"
47 #include "tilepro-multiply.h"
48 #include "diagnostic.h"
50 /* SYMBOL_REF for GOT */
51 static GTY(()) rtx g_got_symbol
= NULL
;
53 /* In case of a POST_INC or POST_DEC memory reference, we must report
54 the mode of the memory reference from TARGET_PRINT_OPERAND to
55 TARGET_PRINT_OPERAND_ADDRESS. */
56 static enum machine_mode output_memory_reference_mode
;
58 /* Report whether we're printing out the first address fragment of a
59 POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
60 TARGET_PRINT_OPERAND_ADDRESS. */
61 static bool output_memory_autoinc_first
;
67 /* Implement TARGET_OPTION_OVERRIDE. */
69 tilepro_option_override (void)
71 /* When modulo scheduling is enabled, we still rely on regular
72 scheduler for bundling. */
73 if (flag_modulo_sched
)
74 flag_resched_modulo_sched
= 1;
79 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
81 tilepro_scalar_mode_supported_p (enum machine_mode mode
)
101 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */
103 tile_vector_mode_supported_p (enum machine_mode mode
)
105 return mode
== V4QImode
|| mode
== V2HImode
;
109 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
111 tilepro_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED
,
112 rtx x ATTRIBUTE_UNUSED
)
118 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
120 tilepro_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
126 /* Implement TARGET_PASS_BY_REFERENCE. Variable sized types are
127 passed by reference. */
129 tilepro_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED
,
130 enum machine_mode mode ATTRIBUTE_UNUSED
,
131 const_tree type
, bool named ATTRIBUTE_UNUSED
)
133 return (type
&& TYPE_SIZE (type
)
134 && TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
);
138 /* Implement TARGET_RETURN_IN_MEMORY. */
140 tilepro_return_in_memory (const_tree type
, const_tree fndecl ATTRIBUTE_UNUSED
)
142 return !IN_RANGE (int_size_in_bytes (type
),
143 0, TILEPRO_NUM_RETURN_REGS
* UNITS_PER_WORD
);
147 /* Implement TARGET_FUNCTION_ARG_BOUNDARY. */
149 tilepro_function_arg_boundary (enum machine_mode mode
, const_tree type
)
151 unsigned int alignment
;
153 alignment
= type
? TYPE_ALIGN (type
) : GET_MODE_ALIGNMENT (mode
);
154 if (alignment
< PARM_BOUNDARY
)
155 alignment
= PARM_BOUNDARY
;
156 if (alignment
> STACK_BOUNDARY
)
157 alignment
= STACK_BOUNDARY
;
162 /* Implement TARGET_FUNCTION_ARG. */
164 tilepro_function_arg (cumulative_args_t cum_v
,
165 enum machine_mode mode
,
166 const_tree type
, bool named ATTRIBUTE_UNUSED
)
168 CUMULATIVE_ARGS cum
= *get_cumulative_args (cum_v
);
169 int byte_size
= ((mode
== BLKmode
)
170 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
171 bool doubleword_aligned_p
;
173 if (cum
>= TILEPRO_NUM_ARG_REGS
)
176 /* See whether the argument has doubleword alignment. */
177 doubleword_aligned_p
=
178 tilepro_function_arg_boundary (mode
, type
) > BITS_PER_WORD
;
180 if (doubleword_aligned_p
)
183 /* The ABI does not allow parameters to be passed partially in reg
184 and partially in stack. */
185 if ((cum
+ (byte_size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
)
186 > TILEPRO_NUM_ARG_REGS
)
189 return gen_rtx_REG (mode
, cum
);
193 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
195 tilepro_function_arg_advance (cumulative_args_t cum_v
,
196 enum machine_mode mode
,
197 const_tree type
, bool named ATTRIBUTE_UNUSED
)
199 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
201 int byte_size
= ((mode
== BLKmode
)
202 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
203 int word_size
= (byte_size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
204 bool doubleword_aligned_p
;
206 /* See whether the argument has doubleword alignment. */
207 doubleword_aligned_p
=
208 tilepro_function_arg_boundary (mode
, type
) > BITS_PER_WORD
;
210 if (doubleword_aligned_p
)
213 /* If the current argument does not fit in the pretend_args space,
215 if (*cum
< TILEPRO_NUM_ARG_REGS
216 && *cum
+ word_size
> TILEPRO_NUM_ARG_REGS
)
217 *cum
= TILEPRO_NUM_ARG_REGS
;
223 /* Implement TARGET_FUNCTION_VALUE. */
225 tilepro_function_value (const_tree valtype
, const_tree fn_decl_or_type
,
226 bool outgoing ATTRIBUTE_UNUSED
)
228 enum machine_mode mode
;
231 mode
= TYPE_MODE (valtype
);
232 unsigned_p
= TYPE_UNSIGNED (valtype
);
234 mode
= promote_function_mode (valtype
, mode
, &unsigned_p
,
237 return gen_rtx_REG (mode
, 0);
241 /* Implement TARGET_LIBCALL_VALUE. */
243 tilepro_libcall_value (enum machine_mode mode
,
244 const_rtx fun ATTRIBUTE_UNUSED
)
246 return gen_rtx_REG (mode
, 0);
250 /* Implement FUNCTION_VALUE_REGNO_P. */
252 tilepro_function_value_regno_p (const unsigned int regno
)
254 return regno
< TILEPRO_NUM_RETURN_REGS
;
258 /* Implement TARGET_BUILD_BUILTIN_VA_LIST. */
260 tilepro_build_builtin_va_list (void)
262 tree f_args
, f_skip
, record
, type_decl
;
265 record
= lang_hooks
.types
.make_type (RECORD_TYPE
);
267 type_decl
= build_decl (BUILTINS_LOCATION
, TYPE_DECL
,
268 get_identifier ("__va_list_tag"), record
);
270 f_args
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
271 get_identifier ("__args"), ptr_type_node
);
272 f_skip
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
273 get_identifier ("__skip"), ptr_type_node
);
275 DECL_FIELD_CONTEXT (f_args
) = record
;
277 DECL_FIELD_CONTEXT (f_skip
) = record
;
279 TREE_CHAIN (record
) = type_decl
;
280 TYPE_NAME (record
) = type_decl
;
281 TYPE_FIELDS (record
) = f_args
;
282 TREE_CHAIN (f_args
) = f_skip
;
284 /* We know this is being padded and we want it too. It is an
285 internal type so hide the warnings from the user. */
289 layout_type (record
);
293 /* The correct type is an array type of one element. */
298 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */
300 tilepro_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
305 f_args
= TYPE_FIELDS (TREE_TYPE (valist
));
306 f_skip
= TREE_CHAIN (f_args
);
309 build3 (COMPONENT_REF
, TREE_TYPE (f_args
), valist
, f_args
, NULL_TREE
);
311 build3 (COMPONENT_REF
, TREE_TYPE (f_skip
), valist
, f_skip
, NULL_TREE
);
313 /* Find the __args area. */
314 t
= make_tree (TREE_TYPE (args
), virtual_incoming_args_rtx
);
315 t
= fold_build_pointer_plus_hwi (t
,
317 (crtl
->args
.info
- TILEPRO_NUM_ARG_REGS
));
319 if (crtl
->args
.pretend_args_size
> 0)
320 t
= fold_build_pointer_plus_hwi (t
, -STACK_POINTER_OFFSET
);
322 t
= build2 (MODIFY_EXPR
, TREE_TYPE (args
), args
, t
);
323 TREE_SIDE_EFFECTS (t
) = 1;
324 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
326 /* Find the __skip area. */
327 t
= make_tree (TREE_TYPE (skip
), virtual_incoming_args_rtx
);
328 t
= fold_build_pointer_plus_hwi (t
, -STACK_POINTER_OFFSET
);
329 t
= build2 (MODIFY_EXPR
, TREE_TYPE (skip
), skip
, t
);
330 TREE_SIDE_EFFECTS (t
) = 1;
331 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
335 /* Implement TARGET_SETUP_INCOMING_VARARGS. */
337 tilepro_setup_incoming_varargs (cumulative_args_t cum
,
338 enum machine_mode mode
,
339 tree type
, int *pretend_args
, int no_rtl
)
341 CUMULATIVE_ARGS local_cum
= *get_cumulative_args (cum
);
344 /* The caller has advanced CUM up to, but not beyond, the last named
345 argument. Advance a local copy of CUM past the last "real" named
346 argument, to find out how many registers are left over. */
347 targetm
.calls
.function_arg_advance (pack_cumulative_args (&local_cum
),
349 first_reg
= local_cum
;
351 if (local_cum
< TILEPRO_NUM_ARG_REGS
)
353 *pretend_args
= UNITS_PER_WORD
* (TILEPRO_NUM_ARG_REGS
- first_reg
);
357 alias_set_type set
= get_varargs_alias_set ();
359 gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, \
360 virtual_incoming_args_rtx
,
361 -STACK_POINTER_OFFSET
-
363 (TILEPRO_NUM_ARG_REGS
-
365 MEM_NOTRAP_P (tmp
) = 1;
366 set_mem_alias_set (tmp
, set
);
367 move_block_from_reg (first_reg
, tmp
,
368 TILEPRO_NUM_ARG_REGS
- first_reg
);
376 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. Gimplify va_arg by updating
377 the va_list structure VALIST as required to retrieve an argument of
378 type TYPE, and returning that argument.
380 ret = va_arg(VALIST, TYPE);
382 generates code equivalent to:
384 paddedsize = (sizeof(TYPE) + 3) & -4;
385 if ((VALIST.__args + paddedsize > VALIST.__skip)
386 & (VALIST.__args <= VALIST.__skip))
387 addr = VALIST.__skip + STACK_POINTER_OFFSET;
389 addr = VALIST.__args;
390 VALIST.__args = addr + paddedsize;
391 ret = *(TYPE *)addr; */
393 tilepro_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
* pre_p
,
394 gimple_seq
* post_p ATTRIBUTE_UNUSED
)
398 HOST_WIDE_INT size
, rsize
;
400 bool pass_by_reference_p
;
402 f_args
= TYPE_FIELDS (va_list_type_node
);
403 f_skip
= TREE_CHAIN (f_args
);
406 build3 (COMPONENT_REF
, TREE_TYPE (f_args
), valist
, f_args
, NULL_TREE
);
408 build3 (COMPONENT_REF
, TREE_TYPE (f_skip
), valist
, f_skip
, NULL_TREE
);
410 addr
= create_tmp_var (ptr_type_node
, "va_arg");
412 /* if an object is dynamically sized, a pointer to it is passed
413 instead of the object itself. */
414 pass_by_reference_p
= pass_by_reference (NULL
, TYPE_MODE (type
), type
,
417 if (pass_by_reference_p
)
418 type
= build_pointer_type (type
);
420 size
= int_size_in_bytes (type
);
421 rsize
= ((size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
) * UNITS_PER_WORD
;
423 /* If the alignment of the type is greater than the default for a
424 parameter, align to STACK_BOUNDARY. */
425 if (TYPE_ALIGN (type
) > PARM_BOUNDARY
)
427 /* Assert the only case we generate code for: when
428 stack boundary = 2 * parm boundary. */
429 gcc_assert (STACK_BOUNDARY
== PARM_BOUNDARY
* 2);
431 tmp
= build2 (BIT_AND_EXPR
, sizetype
,
432 fold_convert (sizetype
, unshare_expr (args
)),
433 size_int (PARM_BOUNDARY
/ 8));
434 tmp
= build2 (POINTER_PLUS_EXPR
, ptr_type_node
,
435 unshare_expr (args
), tmp
);
437 gimplify_assign (unshare_expr (args
), tmp
, pre_p
);
440 /* Build conditional expression to calculate addr. The expression
441 will be gimplified later. */
442 tmp
= fold_build_pointer_plus_hwi (unshare_expr (args
), rsize
);
443 tmp
= build2 (TRUTH_AND_EXPR
, boolean_type_node
,
444 build2 (GT_EXPR
, boolean_type_node
, tmp
, unshare_expr (skip
)),
445 build2 (LE_EXPR
, boolean_type_node
, unshare_expr (args
),
446 unshare_expr (skip
)));
448 tmp
= build3 (COND_EXPR
, ptr_type_node
, tmp
,
449 build2 (POINTER_PLUS_EXPR
, ptr_type_node
, unshare_expr (skip
),
450 size_int (STACK_POINTER_OFFSET
)),
451 unshare_expr (args
));
453 gimplify_assign (addr
, tmp
, pre_p
);
455 /* Update VALIST.__args. */
456 tmp
= fold_build_pointer_plus_hwi (addr
, rsize
);
457 gimplify_assign (unshare_expr (args
), tmp
, pre_p
);
459 addr
= fold_convert (build_pointer_type (type
), addr
);
461 if (pass_by_reference_p
)
462 addr
= build_va_arg_indirect_ref (addr
);
464 return build_va_arg_indirect_ref (addr
);
469 /* Implement TARGET_RTX_COSTS. */
471 tilepro_rtx_costs (rtx x
, int code
, int outer_code
, int opno
, int *total
,
477 /* If this is an 8-bit constant, return zero since it can be
478 used nearly anywhere with no cost. If it is a valid operand
479 for an ADD or AND, likewise return 0 if we know it will be
480 used in that context. Otherwise, return 2 since it might be
481 used there later. All other constants take at least two
483 if (satisfies_constraint_I (x
))
488 else if (outer_code
== PLUS
&& add_operand (x
, VOIDmode
))
490 /* Slightly penalize large constants even though we can add
491 them in one instruction, because it forces the use of
492 2-wide bundling mode. */
496 else if (move_operand (x
, SImode
))
498 /* We can materialize in one move. */
499 *total
= COSTS_N_INSNS (1);
504 /* We can materialize in two moves. */
505 *total
= COSTS_N_INSNS (2);
514 *total
= COSTS_N_INSNS (2);
518 *total
= COSTS_N_INSNS (4);
526 /* If outer-code was a sign or zero extension, a cost of
527 COSTS_N_INSNS (1) was already added in, so account for
529 if (outer_code
== ZERO_EXTEND
|| outer_code
== SIGN_EXTEND
)
530 *total
= COSTS_N_INSNS (1);
532 *total
= COSTS_N_INSNS (2);
536 /* Convey that s[123]a are efficient. */
537 if (GET_CODE (XEXP (x
, 0)) == MULT
538 && cint_248_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
540 *total
= (rtx_cost (XEXP (XEXP (x
, 0), 0),
541 (enum rtx_code
) outer_code
, opno
, speed
)
542 + rtx_cost (XEXP (x
, 1),
543 (enum rtx_code
) outer_code
, opno
, speed
)
544 + COSTS_N_INSNS (1));
550 *total
= COSTS_N_INSNS (2);
555 if (outer_code
== MULT
)
558 *total
= COSTS_N_INSNS (1);
565 /* These are handled by software and are very expensive. */
566 *total
= COSTS_N_INSNS (100);
570 case UNSPEC_VOLATILE
:
572 int num
= XINT (x
, 1);
574 if (num
<= TILEPRO_LAST_LATENCY_1_INSN
)
575 *total
= COSTS_N_INSNS (1);
576 else if (num
<= TILEPRO_LAST_LATENCY_2_INSN
)
577 *total
= COSTS_N_INSNS (2);
578 else if (num
> TILEPRO_LAST_LATENCY_INSN
)
580 if (outer_code
== PLUS
)
583 *total
= COSTS_N_INSNS (1);
589 case UNSPEC_BLOCKAGE
:
590 case UNSPEC_NETWORK_BARRIER
:
594 case UNSPEC_LNK_AND_LABEL
:
596 case UNSPEC_NETWORK_RECEIVE
:
597 case UNSPEC_NETWORK_SEND
:
598 case UNSPEC_TLS_GD_ADD
:
599 *total
= COSTS_N_INSNS (1);
602 case UNSPEC_TLS_IE_LOAD
:
603 *total
= COSTS_N_INSNS (2);
607 *total
= COSTS_N_INSNS (3);
611 *total
= COSTS_N_INSNS (4);
614 case UNSPEC_LATENCY_L2
:
615 *total
= COSTS_N_INSNS (8);
618 case UNSPEC_TLS_GD_CALL
:
619 *total
= COSTS_N_INSNS (30);
622 case UNSPEC_LATENCY_MISS
:
623 *total
= COSTS_N_INSNS (80);
627 *total
= COSTS_N_INSNS (1);
640 /* Returns an SImode integer rtx with value VAL. */
642 gen_int_si (HOST_WIDE_INT val
)
644 return gen_int_mode (val
, SImode
);
648 /* Create a temporary variable to hold a partial result, to enable
651 create_temp_reg_if_possible (enum machine_mode mode
, rtx default_reg
)
653 return can_create_pseudo_p ()? gen_reg_rtx (mode
) : default_reg
;
657 /* Functions to save and restore machine-specific function data. */
658 static struct machine_function
*
659 tilepro_init_machine_status (void)
661 return ggc_alloc_cleared_machine_function ();
665 /* Do anything needed before RTL is emitted for each function. */
667 tilepro_init_expanders (void)
669 /* Arrange to initialize and mark the machine per-function
671 init_machine_status
= tilepro_init_machine_status
;
673 if (cfun
&& cfun
->machine
&& flag_pic
)
675 static int label_num
= 0;
677 char text_label_name
[32];
679 struct machine_function
*machine
= cfun
->machine
;
681 ASM_GENERATE_INTERNAL_LABEL (text_label_name
, "L_PICLNK", label_num
++);
683 machine
->text_label_symbol
=
684 gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup (text_label_name
));
686 machine
->text_label_rtx
=
687 gen_rtx_REG (Pmode
, TILEPRO_PIC_TEXT_LABEL_REGNUM
);
689 machine
->got_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
691 machine
->calls_tls_get_addr
= false;
696 /* Return true if X contains a thread-local symbol. */
698 tilepro_tls_referenced_p (rtx x
)
700 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
701 x
= XEXP (XEXP (x
, 0), 0);
703 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x
))
706 /* That's all we handle in tilepro_legitimize_tls_address for
712 /* Return true if X requires a scratch register. It is given that
713 flag_pic is on and that X satisfies CONSTANT_P. */
715 tilepro_pic_address_needs_scratch (rtx x
)
717 if (GET_CODE (x
) == CONST
718 && GET_CODE (XEXP (x
, 0)) == PLUS
719 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
720 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
721 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
728 /* Implement TARGET_LEGITIMATE_CONSTANT_P. This is all constants for
729 which we are willing to load the value into a register via a move
730 pattern. TLS cannot be treated as a constant because it can
731 include a function call. */
733 tilepro_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
735 switch (GET_CODE (x
))
739 return !tilepro_tls_referenced_p (x
);
747 /* Return true if the constant value X is a legitimate general operand
748 when generating PIC code. It is given that flag_pic is on and that
749 X satisfies CONSTANT_P. */
751 tilepro_legitimate_pic_operand_p (rtx x
)
753 if (tilepro_pic_address_needs_scratch (x
))
756 if (tilepro_tls_referenced_p (x
))
763 /* Return true if the rtx X can be used as an address operand. */
765 tilepro_legitimate_address_p (enum machine_mode
ARG_UNUSED (mode
), rtx x
,
768 if (GET_CODE (x
) == SUBREG
)
771 switch (GET_CODE (x
))
775 if (GET_MODE_SIZE (GET_MODE (x
)) > UNITS_PER_WORD
)
782 if (GET_MODE_SIZE (GET_MODE (x
)) > UNITS_PER_WORD
)
785 if (GET_CODE (XEXP (x
, 1)) != PLUS
)
788 if (!rtx_equal_p (XEXP (x
, 0), XEXP (XEXP (x
, 1), 0)))
791 if (!satisfies_constraint_I (XEXP (XEXP (x
, 1), 1)))
804 /* Check if x is a valid reg. */
809 return REGNO_OK_FOR_BASE_P (REGNO (x
));
815 /* Return the rtx containing SYMBOL_REF to the text label. */
817 tilepro_text_label_symbol (void)
819 return cfun
->machine
->text_label_symbol
;
823 /* Return the register storing the value of the text label. */
825 tilepro_text_label_rtx (void)
827 return cfun
->machine
->text_label_rtx
;
831 /* Return the register storing the value of the global offset
834 tilepro_got_rtx (void)
836 return cfun
->machine
->got_rtx
;
840 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_. */
842 tilepro_got_symbol (void)
844 if (g_got_symbol
== NULL
)
845 g_got_symbol
= gen_rtx_SYMBOL_REF (Pmode
, "_GLOBAL_OFFSET_TABLE_");
851 /* Return a reference to the got to be used by tls references. */
853 tilepro_tls_got (void)
858 crtl
->uses_pic_offset_table
= 1;
859 return tilepro_got_rtx ();
862 temp
= gen_reg_rtx (Pmode
);
863 emit_move_insn (temp
, tilepro_got_symbol ());
869 /* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
870 this (thread-local) address. */
872 tilepro_legitimize_tls_address (rtx addr
)
876 gcc_assert (can_create_pseudo_p ());
878 if (GET_CODE (addr
) == SYMBOL_REF
)
879 switch (SYMBOL_REF_TLS_MODEL (addr
))
881 case TLS_MODEL_GLOBAL_DYNAMIC
:
882 case TLS_MODEL_LOCAL_DYNAMIC
:
884 rtx r0
, temp1
, temp2
, temp3
, got
, last
;
886 ret
= gen_reg_rtx (Pmode
);
887 r0
= gen_rtx_REG (Pmode
, 0);
888 temp1
= gen_reg_rtx (Pmode
);
889 temp2
= gen_reg_rtx (Pmode
);
890 temp3
= gen_reg_rtx (Pmode
);
892 got
= tilepro_tls_got ();
893 emit_insn (gen_tls_gd_addhi (temp1
, got
, addr
));
894 emit_insn (gen_tls_gd_addlo (temp2
, temp1
, addr
));
895 emit_move_insn (r0
, temp2
);
896 emit_insn (gen_tls_gd_call (addr
));
897 emit_move_insn (temp3
, r0
);
898 last
= emit_insn (gen_tls_gd_add (ret
, temp3
, addr
));
899 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
902 case TLS_MODEL_INITIAL_EXEC
:
904 rtx temp1
, temp2
, temp3
, got
, last
;
906 ret
= gen_reg_rtx (Pmode
);
907 temp1
= gen_reg_rtx (Pmode
);
908 temp2
= gen_reg_rtx (Pmode
);
909 temp3
= gen_reg_rtx (Pmode
);
911 got
= tilepro_tls_got ();
912 emit_insn (gen_tls_ie_addhi (temp1
, got
, addr
));
913 emit_insn (gen_tls_ie_addlo (temp2
, temp1
, addr
));
914 emit_insn (gen_tls_ie_load (temp3
, temp2
, addr
));
919 THREAD_POINTER_REGNUM
),
921 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
924 case TLS_MODEL_LOCAL_EXEC
:
928 ret
= gen_reg_rtx (Pmode
);
929 temp1
= gen_reg_rtx (Pmode
);
931 emit_insn (gen_tls_le_addhi (temp1
,
933 THREAD_POINTER_REGNUM
),
935 last
= emit_insn (gen_tls_le_addlo (ret
, temp1
, addr
));
936 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
942 else if (GET_CODE (addr
) == CONST
)
946 gcc_assert (GET_CODE (XEXP (addr
, 0)) == PLUS
);
948 base
= tilepro_legitimize_tls_address (XEXP (XEXP (addr
, 0), 0));
949 offset
= XEXP (XEXP (addr
, 0), 1);
951 base
= force_operand (base
, NULL_RTX
);
952 ret
= force_reg (Pmode
, gen_rtx_PLUS (Pmode
, base
, offset
));
961 /* Legitimize PIC addresses. If the address is already
962 position-independent, we return ORIG. Newly generated
963 position-independent addresses go into a reg. This is REG if
964 nonzero, otherwise we allocate register(s) as necessary. */
966 tilepro_legitimize_pic_address (rtx orig
,
967 enum machine_mode mode ATTRIBUTE_UNUSED
,
970 if (GET_CODE (orig
) == SYMBOL_REF
)
972 rtx address
, pic_ref
;
976 gcc_assert (can_create_pseudo_p ());
977 reg
= gen_reg_rtx (Pmode
);
980 if (SYMBOL_REF_LOCAL_P (orig
))
982 /* If not during reload, allocate another temp reg here for
983 loading in the address, so that these instructions can be
984 optimized properly. */
985 rtx temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
986 rtx text_label_symbol
= tilepro_text_label_symbol ();
987 rtx text_label_rtx
= tilepro_text_label_rtx ();
989 emit_insn (gen_addli_pcrel (temp_reg
, text_label_rtx
, orig
,
991 emit_insn (gen_auli_pcrel (temp_reg
, temp_reg
, orig
,
994 /* Note: this is conservative. We use the text_label but we
995 don't use the pic_offset_table. However, in some cases
996 we may need the pic_offset_table (see
997 tilepro_fixup_pcrel_references). */
998 crtl
->uses_pic_offset_table
= 1;
1002 emit_move_insn (reg
, address
);
1007 /* If not during reload, allocate another temp reg here for
1008 loading in the address, so that these instructions can be
1009 optimized properly. */
1010 rtx temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
1012 gcc_assert (flag_pic
);
1015 emit_insn (gen_add_got16 (temp_reg
,
1016 tilepro_got_rtx (), orig
));
1020 rtx temp_reg2
= create_temp_reg_if_possible (Pmode
, reg
);
1021 emit_insn (gen_addhi_got32 (temp_reg2
,
1022 tilepro_got_rtx (), orig
));
1023 emit_insn (gen_addlo_got32 (temp_reg
, temp_reg2
, orig
));
1028 pic_ref
= gen_const_mem (Pmode
, address
);
1029 crtl
->uses_pic_offset_table
= 1;
1030 emit_move_insn (reg
, pic_ref
);
1031 /* The following put a REG_EQUAL note on this insn, so that
1032 it can be optimized by loop. But it causes the label to
1033 be optimized away. */
1034 /* set_unique_reg_note (insn, REG_EQUAL, orig); */
1038 else if (GET_CODE (orig
) == CONST
)
1042 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1043 && XEXP (XEXP (orig
, 0), 0) == tilepro_got_rtx ())
1048 gcc_assert (can_create_pseudo_p ());
1049 reg
= gen_reg_rtx (Pmode
);
1052 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1053 base
= tilepro_legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
,
1056 tilepro_legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1057 base
== reg
? 0 : reg
);
1059 if (CONST_INT_P (offset
))
1061 if (can_create_pseudo_p ())
1062 offset
= force_reg (Pmode
, offset
);
1064 /* If we reach here, then something is seriously
1069 if (can_create_pseudo_p ())
1070 return force_reg (Pmode
, gen_rtx_PLUS (Pmode
, base
, offset
));
1074 else if (GET_CODE (orig
) == LABEL_REF
)
1076 rtx address
, temp_reg
;
1077 rtx text_label_symbol
;
1082 gcc_assert (can_create_pseudo_p ());
1083 reg
= gen_reg_rtx (Pmode
);
1086 /* If not during reload, allocate another temp reg here for
1087 loading in the address, so that these instructions can be
1088 optimized properly. */
1089 temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
1090 text_label_symbol
= tilepro_text_label_symbol ();
1091 text_label_rtx
= tilepro_text_label_rtx ();
1093 emit_insn (gen_addli_pcrel (temp_reg
, text_label_rtx
, orig
,
1094 text_label_symbol
));
1095 emit_insn (gen_auli_pcrel (temp_reg
, temp_reg
, orig
,
1096 text_label_symbol
));
1098 /* Note: this is conservative. We use the text_label but we
1099 don't use the pic_offset_table. */
1100 crtl
->uses_pic_offset_table
= 1;
1104 emit_move_insn (reg
, address
);
1113 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1115 tilepro_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1116 enum machine_mode mode
)
1118 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
1119 && symbolic_operand (x
, Pmode
) && tilepro_tls_referenced_p (x
))
1121 return tilepro_legitimize_tls_address (x
);
1125 return tilepro_legitimize_pic_address (x
, mode
, 0);
1132 /* Implement TARGET_DELEGITIMIZE_ADDRESS. */
1134 tilepro_delegitimize_address (rtx x
)
1136 x
= delegitimize_mem_from_attrs (x
);
1138 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == UNSPEC
)
1140 switch (XINT (XEXP (x
, 0), 1))
1142 case UNSPEC_PCREL_SYM
:
1143 case UNSPEC_GOT16_SYM
:
1144 case UNSPEC_GOT32_SYM
:
1147 x
= XVECEXP (XEXP (x
, 0), 0, 0);
1156 /* Emit code to load the PIC register. */
1158 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED
)
1160 int orig_flag_pic
= flag_pic
;
1162 rtx got_symbol
= tilepro_got_symbol ();
1163 rtx text_label_symbol
= tilepro_text_label_symbol ();
1164 rtx text_label_rtx
= tilepro_text_label_rtx ();
1167 emit_insn (gen_insn_lnk_and_label (text_label_rtx
, text_label_symbol
));
1169 emit_insn (gen_addli_pcrel (tilepro_got_rtx (),
1170 text_label_rtx
, got_symbol
, text_label_symbol
));
1172 emit_insn (gen_auli_pcrel (tilepro_got_rtx (),
1174 got_symbol
, text_label_symbol
));
1176 flag_pic
= orig_flag_pic
;
1178 /* Need to emit this whether or not we obey regdecls, since
1179 setjmp/longjmp can cause life info to screw up. ??? In the case
1180 where we don't obey regdecls, this is not sufficient since we may
1181 not fall out the bottom. */
1182 emit_use (tilepro_got_rtx ());
1186 /* Return the simd variant of the constant NUM of mode MODE, by
1187 replicating it to fill an interger of mode SImode. NUM is first
1188 truncated to fit in MODE. */
1190 tilepro_simd_int (rtx num
, enum machine_mode mode
)
1192 HOST_WIDE_INT n
= 0;
1194 gcc_assert (CONST_INT_P (num
));
1201 n
= 0x01010101 * (n
& 0x000000FF);
1204 n
= 0x00010001 * (n
& 0x0000FFFF);
1214 return gen_int_si (n
);
1218 /* Split one or more DImode RTL references into pairs of SImode
1219 references. The RTL can be REG, offsettable MEM, integer constant,
1220 or CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL
1221 to split and "num" is its length. lo_half and hi_half are output
1222 arrays that parallel "operands". */
1224 split_di (rtx operands
[], int num
, rtx lo_half
[], rtx hi_half
[])
1228 rtx op
= operands
[num
];
1230 /* simplify_subreg refuse to split volatile memory addresses,
1231 but we still have to handle it. */
1234 lo_half
[num
] = adjust_address (op
, SImode
, 0);
1235 hi_half
[num
] = adjust_address (op
, SImode
, 4);
1239 lo_half
[num
] = simplify_gen_subreg (SImode
, op
,
1240 GET_MODE (op
) == VOIDmode
1241 ? DImode
: GET_MODE (op
), 0);
1242 hi_half
[num
] = simplify_gen_subreg (SImode
, op
,
1243 GET_MODE (op
) == VOIDmode
1244 ? DImode
: GET_MODE (op
), 4);
1250 /* Returns true iff val can be moved into a register in one
1251 instruction. And if it can, it emits the code to move the
1254 If three_wide_only is true, this insists on an instruction that
1255 works in a bundle containing three instructions. */
1257 expand_set_cint32_one_inst (rtx dest_reg
,
1258 HOST_WIDE_INT val
, bool three_wide_only
)
1260 val
= trunc_int_for_mode (val
, SImode
);
1262 if (val
== trunc_int_for_mode (val
, QImode
))
1265 emit_move_insn (dest_reg
, GEN_INT (val
));
1268 else if (!three_wide_only
)
1270 rtx imm_op
= GEN_INT (val
);
1272 if (satisfies_constraint_J (imm_op
)
1273 || satisfies_constraint_K (imm_op
)
1274 || satisfies_constraint_N (imm_op
)
1275 || satisfies_constraint_P (imm_op
))
1277 emit_move_insn (dest_reg
, imm_op
);
1286 /* Implement SImode rotatert. */
1287 static HOST_WIDE_INT
1288 rotate_right (HOST_WIDE_INT n
, int count
)
1290 unsigned HOST_WIDE_INT x
= n
& 0xFFFFFFFF;
1293 return ((x
>> count
) | (x
<< (32 - count
))) & 0xFFFFFFFF;
1297 /* Return true iff n contains exactly one contiguous sequence of 1
1298 bits, possibly wrapping around from high bits to low bits. */
1300 tilepro_bitfield_operand_p (HOST_WIDE_INT n
, int *first_bit
, int *last_bit
)
1307 for (i
= 0; i
< 32; i
++)
1309 unsigned HOST_WIDE_INT x
= rotate_right (n
, i
);
1313 /* See if x is a power of two minus one, i.e. only consecutive 1
1314 bits starting from bit 0. */
1315 if ((x
& (x
+ 1)) == 0)
1317 if (first_bit
!= NULL
)
1319 if (last_bit
!= NULL
)
1320 *last_bit
= (i
+ exact_log2 (x
^ (x
>> 1))) & 31;
1330 /* Create code to move the CONST_INT value in src_val to dest_reg. */
1332 expand_set_cint32 (rtx dest_reg
, rtx src_val
)
1335 int leading_zeroes
, trailing_zeroes
;
1337 int three_wide_only
;
1340 gcc_assert (CONST_INT_P (src_val
));
1341 val
= trunc_int_for_mode (INTVAL (src_val
), SImode
);
1343 /* See if we can generate the constant in one instruction. */
1344 if (expand_set_cint32_one_inst (dest_reg
, val
, false))
1347 /* Create a temporary variable to hold a partial result, to enable
1349 temp
= create_temp_reg_if_possible (SImode
, dest_reg
);
1351 leading_zeroes
= 31 - floor_log2 (val
& 0xFFFFFFFF);
1352 trailing_zeroes
= exact_log2 (val
& -val
);
1354 lower
= trunc_int_for_mode (val
, HImode
);
1355 upper
= trunc_int_for_mode ((val
- lower
) >> 16, HImode
);
1357 /* First try all three-wide instructions that generate a constant
1358 (i.e. movei) followed by various shifts and rotates. If none of
1359 those work, try various two-wide ways of generating a constant
1360 followed by various shifts and rotates. */
1361 for (three_wide_only
= 1; three_wide_only
>= 0; three_wide_only
--)
1365 if (expand_set_cint32_one_inst (temp
, val
>> trailing_zeroes
,
1368 /* 0xFFFFA500 becomes:
1369 movei temp, 0xFFFFFFA5
1370 shli dest, temp, 8 */
1371 emit_move_insn (dest_reg
,
1372 gen_rtx_ASHIFT (SImode
, temp
,
1373 GEN_INT (trailing_zeroes
)));
1377 if (expand_set_cint32_one_inst (temp
, val
<< leading_zeroes
,
1380 /* 0x7FFFFFFF becomes:
1382 shri dest, temp, 1 */
1383 emit_move_insn (dest_reg
,
1384 gen_rtx_LSHIFTRT (SImode
, temp
,
1385 GEN_INT (leading_zeroes
)));
1389 /* Try rotating a one-instruction immediate, since rotate is
1391 for (count
= 1; count
< 32; count
++)
1393 HOST_WIDE_INT r
= rotate_right (val
, count
);
1394 if (expand_set_cint32_one_inst (temp
, r
, three_wide_only
))
1396 /* 0xFFA5FFFF becomes:
1397 movei temp, 0xFFFFFFA5
1398 rli dest, temp, 16 */
1399 emit_move_insn (dest_reg
,
1400 gen_rtx_ROTATE (SImode
, temp
, GEN_INT (count
)));
1405 if (lower
== trunc_int_for_mode (lower
, QImode
))
1407 /* We failed to use two 3-wide instructions, but the low 16
1408 bits are a small number so just use a 2-wide + 3-wide
1409 auli + addi pair rather than anything more exotic.
1412 auli temp, zero, 0x1234
1413 addi dest, temp, 0x56 */
1418 /* Fallback case: use a auli + addli/addi pair. */
1419 emit_move_insn (temp
, GEN_INT (upper
<< 16));
1420 emit_move_insn (dest_reg
, (gen_rtx_PLUS (SImode
, temp
, GEN_INT (lower
))));
1424 /* Load OP1, a 32-bit constant, into OP0, a register. We know it
1425 can't be done in one insn when we get here, the move expander
1428 tilepro_expand_set_const32 (rtx op0
, rtx op1
)
1430 enum machine_mode mode
= GET_MODE (op0
);
1433 if (CONST_INT_P (op1
))
1435 /* TODO: I don't know if we want to split large constants now,
1436 or wait until later (with a define_split).
1438 Does splitting early help CSE? Does it harm other
1439 optimizations that might fold loads? */
1440 expand_set_cint32 (op0
, op1
);
1444 temp
= create_temp_reg_if_possible (mode
, op0
);
1446 /* A symbol, emit in the traditional way. */
1447 emit_move_insn (temp
, gen_rtx_HIGH (mode
, op1
));
1448 emit_move_insn (op0
, gen_rtx_LO_SUM (mode
, temp
, op1
));
1453 /* Expand a move instruction. Return true if all work is done. */
1455 tilepro_expand_mov (enum machine_mode mode
, rtx
*operands
)
1457 /* Handle sets of MEM first. */
1458 if (MEM_P (operands
[0]))
1460 if (can_create_pseudo_p ())
1461 operands
[0] = validize_mem (operands
[0]);
1463 if (reg_or_0_operand (operands
[1], mode
))
1466 if (!reload_in_progress
)
1467 operands
[1] = force_reg (mode
, operands
[1]);
1470 /* Fixup TLS cases. */
1471 if (CONSTANT_P (operands
[1]) && tilepro_tls_referenced_p (operands
[1]))
1473 operands
[1] = tilepro_legitimize_tls_address (operands
[1]);
1477 /* Fixup PIC cases. */
1478 if (flag_pic
&& CONSTANT_P (operands
[1]))
1480 if (tilepro_pic_address_needs_scratch (operands
[1]))
1481 operands
[1] = tilepro_legitimize_pic_address (operands
[1], mode
, 0);
1483 if (symbolic_operand (operands
[1], mode
))
1485 operands
[1] = tilepro_legitimize_pic_address (operands
[1],
1487 (reload_in_progress
?
1494 /* Fixup for UNSPEC addresses. */
1496 && GET_CODE (operands
[1]) == HIGH
1497 && GET_CODE (XEXP (operands
[1], 0)) == CONST
1498 && GET_CODE (XEXP (XEXP (operands
[1], 0), 0)) == UNSPEC
)
1500 rtx unspec
= XEXP (XEXP (operands
[1], 0), 0);
1501 int unspec_num
= XINT (unspec
, 1);
1502 if (unspec_num
== UNSPEC_PCREL_SYM
)
1504 emit_insn (gen_auli_pcrel (operands
[0], const0_rtx
,
1505 XVECEXP (unspec
, 0, 0),
1506 XVECEXP (unspec
, 0, 1)));
1509 else if (flag_pic
== 2 && unspec_num
== UNSPEC_GOT32_SYM
)
1511 emit_insn (gen_addhi_got32 (operands
[0], const0_rtx
,
1512 XVECEXP (unspec
, 0, 0)));
1515 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_GD
)
1517 emit_insn (gen_tls_gd_addhi (operands
[0], const0_rtx
,
1518 XVECEXP (unspec
, 0, 0)));
1521 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_IE
)
1523 emit_insn (gen_tls_ie_addhi (operands
[0], const0_rtx
,
1524 XVECEXP (unspec
, 0, 0)));
1527 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_LE
)
1529 emit_insn (gen_tls_le_addhi (operands
[0], const0_rtx
,
1530 XVECEXP (unspec
, 0, 0)));
1535 /* Accept non-constants and valid constants unmodified. */
1536 if (!CONSTANT_P (operands
[1])
1537 || GET_CODE (operands
[1]) == HIGH
|| move_operand (operands
[1], mode
))
1540 /* Split large integers. */
1541 if (GET_MODE_SIZE (mode
) <= 4)
1543 tilepro_expand_set_const32 (operands
[0], operands
[1]);
1551 /* Expand the "insv" pattern. */
1553 tilepro_expand_insv (rtx operands
[4])
1555 rtx first_rtx
= operands
[2];
1556 HOST_WIDE_INT first
= INTVAL (first_rtx
);
1557 HOST_WIDE_INT width
= INTVAL (operands
[1]);
1558 rtx v
= operands
[3];
1560 /* Shift the inserted bits into position. */
1563 if (CONST_INT_P (v
))
1565 /* Shift the constant into mm position. */
1566 v
= gen_int_si (INTVAL (v
) << first
);
1570 /* Shift over the value to be inserted. */
1571 rtx tmp
= gen_reg_rtx (SImode
);
1572 emit_insn (gen_ashlsi3 (tmp
, v
, first_rtx
));
1577 /* Insert the shifted bits using an 'mm' insn. */
1578 emit_insn (gen_insn_mm (operands
[0], v
, operands
[0], first_rtx
,
1579 GEN_INT (first
+ width
- 1)));
1583 /* Expand unaligned loads. */
1585 tilepro_expand_unaligned_load (rtx dest_reg
, rtx mem
, HOST_WIDE_INT bitsize
,
1586 HOST_WIDE_INT bit_offset
, bool sign
)
1588 enum machine_mode mode
;
1589 rtx addr_lo
, addr_hi
;
1590 rtx mem_lo
, mem_hi
, hi
;
1591 rtx mema
, wide_result
;
1592 int last_byte_offset
;
1593 HOST_WIDE_INT byte_offset
= bit_offset
/ BITS_PER_UNIT
;
1595 mode
= GET_MODE (dest_reg
);
1597 hi
= gen_reg_rtx (mode
);
1599 if (bitsize
== 2 * BITS_PER_UNIT
&& (bit_offset
% BITS_PER_UNIT
) == 0)
1603 /* When just loading a two byte value, we can load the two bytes
1604 individually and combine them efficiently. */
1606 mem_lo
= adjust_address (mem
, QImode
, byte_offset
);
1607 mem_hi
= adjust_address (mem
, QImode
, byte_offset
+ 1);
1609 lo
= gen_reg_rtx (mode
);
1610 emit_insn (gen_zero_extendqisi2 (lo
, mem_lo
));
1614 rtx tmp
= gen_reg_rtx (mode
);
1616 /* Do a signed load of the second byte then shift and OR it
1618 emit_insn (gen_extendqisi2 (gen_lowpart (SImode
, hi
), mem_hi
));
1619 emit_insn (gen_ashlsi3 (gen_lowpart (SImode
, tmp
),
1620 gen_lowpart (SImode
, hi
), GEN_INT (8)));
1621 emit_insn (gen_iorsi3 (gen_lowpart (SImode
, dest_reg
),
1622 gen_lowpart (SImode
, lo
),
1623 gen_lowpart (SImode
, tmp
)));
1627 /* Do two unsigned loads and use intlb to interleave
1629 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode
, hi
), mem_hi
));
1630 emit_insn (gen_insn_intlb (gen_lowpart (SImode
, dest_reg
),
1631 gen_lowpart (SImode
, hi
),
1632 gen_lowpart (SImode
, lo
)));
1638 mema
= XEXP (mem
, 0);
1640 /* AND addresses cannot be in any alias set, since they may
1641 implicitly alias surrounding code. Ideally we'd have some alias
1642 set that covered all types except those with alignment 8 or
1644 addr_lo
= force_reg (Pmode
, plus_constant (Pmode
, mema
, byte_offset
));
1645 mem_lo
= change_address (mem
, mode
,
1646 gen_rtx_AND (Pmode
, addr_lo
, GEN_INT (-4)));
1647 set_mem_alias_set (mem_lo
, 0);
1649 /* Load the high word at an address that will not fault if the low
1650 address is aligned and at the very end of a page. */
1651 last_byte_offset
= (bit_offset
+ bitsize
- 1) / BITS_PER_UNIT
;
1652 addr_hi
= force_reg (Pmode
, plus_constant (Pmode
, mema
, last_byte_offset
));
1653 mem_hi
= change_address (mem
, mode
,
1654 gen_rtx_AND (Pmode
, addr_hi
, GEN_INT (-4)));
1655 set_mem_alias_set (mem_hi
, 0);
1659 addr_lo
= make_safe_from (addr_lo
, dest_reg
);
1660 wide_result
= dest_reg
;
1664 wide_result
= gen_reg_rtx (mode
);
1667 /* Load hi first in case dest_reg is used in mema. */
1668 emit_move_insn (hi
, mem_hi
);
1669 emit_move_insn (wide_result
, mem_lo
);
1671 emit_insn (gen_insn_dword_align (gen_lowpart (SImode
, wide_result
),
1672 gen_lowpart (SImode
, wide_result
),
1673 gen_lowpart (SImode
, hi
), addr_lo
));
1678 extract_bit_field (gen_lowpart (SImode
, wide_result
),
1679 bitsize
, bit_offset
% BITS_PER_UNIT
,
1680 !sign
, gen_lowpart (SImode
, dest_reg
),
1683 if (extracted
!= dest_reg
)
1684 emit_move_insn (dest_reg
, gen_lowpart (SImode
, extracted
));
1689 /* Expand unaligned stores. */
1691 tilepro_expand_unaligned_store (rtx mem
, rtx src
, HOST_WIDE_INT bitsize
,
1692 HOST_WIDE_INT bit_offset
)
1694 HOST_WIDE_INT byte_offset
= bit_offset
/ BITS_PER_UNIT
;
1695 HOST_WIDE_INT bytesize
= bitsize
/ BITS_PER_UNIT
;
1696 HOST_WIDE_INT shift_amt
;
1701 for (i
= 0, shift_amt
= 0; i
< bytesize
; i
++, shift_amt
+= BITS_PER_UNIT
)
1703 mem_addr
= adjust_address (mem
, QImode
, byte_offset
+ i
);
1707 store_val
= expand_simple_binop (SImode
, LSHIFTRT
,
1708 gen_lowpart (SImode
, src
),
1709 GEN_INT (shift_amt
), NULL
, 1,
1711 store_val
= gen_lowpart (QImode
, store_val
);
1715 store_val
= gen_lowpart (QImode
, src
);
1718 emit_move_insn (mem_addr
, store_val
);
1723 /* Implement the movmisalign patterns. One of the operands is a
1724 memory that is not naturally aligned. Emit instructions to load
1727 tilepro_expand_movmisalign (enum machine_mode mode
, rtx
*operands
)
1729 if (MEM_P (operands
[1]))
1733 if (register_operand (operands
[0], mode
))
1736 tmp
= gen_reg_rtx (mode
);
1738 tilepro_expand_unaligned_load (tmp
, operands
[1],
1739 GET_MODE_BITSIZE (mode
), 0, true);
1741 if (tmp
!= operands
[0])
1742 emit_move_insn (operands
[0], tmp
);
1744 else if (MEM_P (operands
[0]))
1746 if (!reg_or_0_operand (operands
[1], mode
))
1747 operands
[1] = force_reg (mode
, operands
[1]);
1749 tilepro_expand_unaligned_store (operands
[0], operands
[1],
1750 GET_MODE_BITSIZE (mode
), 0);
1757 /* Implement the addsi3 pattern. */
1759 tilepro_expand_addsi (rtx op0
, rtx op1
, rtx op2
)
1765 /* Skip anything that only takes one instruction. */
1766 if (add_operand (op2
, SImode
))
1769 /* We can only optimize ints here (it should be impossible to get
1770 here with any other type, but it is harmless to check. */
1771 if (!CONST_INT_P (op2
))
1774 temp
= create_temp_reg_if_possible (SImode
, op0
);
1776 high
= (n
+ (n
& 0x8000)) & ~0xffff;
1778 emit_move_insn (temp
, gen_rtx_PLUS (SImode
, op1
, gen_int_si (high
)));
1779 emit_move_insn (op0
, gen_rtx_PLUS (SImode
, temp
, gen_int_si (n
- high
)));
1785 /* Implement the allocate_stack pattern (alloca). */
1787 tilepro_allocate_stack (rtx op0
, rtx op1
)
1789 /* Technically the correct way to initialize chain_loc is with
1790 * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
1791 * sets the alias_set to that of a frame reference. Some of our
1792 * tests rely on some unsafe assumption about when the chaining
1793 * update is done, we need to be conservative about reordering the
1794 * chaining instructions.
1796 rtx fp_addr
= gen_reg_rtx (Pmode
);
1797 rtx fp_value
= gen_reg_rtx (Pmode
);
1800 emit_move_insn (fp_addr
, gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
1801 GEN_INT (UNITS_PER_WORD
)));
1803 fp_loc
= gen_frame_mem (Pmode
, fp_addr
);
1805 emit_move_insn (fp_value
, fp_loc
);
1807 op1
= force_reg (Pmode
, op1
);
1809 emit_move_insn (stack_pointer_rtx
,
1810 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, op1
));
1812 emit_move_insn (fp_addr
, gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
1813 GEN_INT (UNITS_PER_WORD
)));
1815 fp_loc
= gen_frame_mem (Pmode
, fp_addr
);
1817 emit_move_insn (fp_loc
, fp_value
);
1819 emit_move_insn (op0
, virtual_stack_dynamic_rtx
);
1826 /* Returns the insn_code in ENTRY. */
1827 static enum insn_code
1828 tilepro_multiply_get_opcode (const struct tilepro_multiply_insn_seq_entry
1831 return tilepro_multiply_insn_seq_decode_opcode
[entry
->compressed_opcode
];
1835 /* Returns the length of the 'op' array. */
1837 tilepro_multiply_get_num_ops (const struct tilepro_multiply_insn_seq
*seq
)
1839 /* The array either uses all of its allocated slots or is terminated
1840 by a bogus opcode. Either way, the array size is the index of the
1841 last valid opcode plus one. */
1843 for (i
= tilepro_multiply_insn_seq_MAX_OPERATIONS
- 1; i
>= 0; i
--)
1844 if (tilepro_multiply_get_opcode (&seq
->op
[i
]) != CODE_FOR_nothing
)
1847 /* An empty array is not allowed. */
1852 /* We precompute a number of expression trees for multiplying by
1853 constants. This generates code for such an expression tree by
1854 walking through the nodes in the tree (which are conveniently
1855 pre-linearized) and emitting an instruction for each one. */
1857 tilepro_expand_constant_multiply_given_sequence (rtx result
, rtx src
,
1859 tilepro_multiply_insn_seq
1865 /* Keep track of the subexpressions computed so far, so later
1866 instructions can refer to them. We seed the array with zero and
1867 the value being multiplied. */
1868 int num_subexprs
= 2;
1869 rtx subexprs
[tilepro_multiply_insn_seq_MAX_OPERATIONS
+ 2];
1870 subexprs
[0] = const0_rtx
;
1873 /* Determine how many instructions we are going to generate. */
1874 num_ops
= tilepro_multiply_get_num_ops (seq
);
1875 gcc_assert (num_ops
> 0
1876 && num_ops
<= tilepro_multiply_insn_seq_MAX_OPERATIONS
);
1878 for (i
= 0; i
< num_ops
; i
++)
1880 const struct tilepro_multiply_insn_seq_entry
*entry
= &seq
->op
[i
];
1882 /* Figure out where to store the output of this instruction. */
1883 const bool is_last_op
= (i
+ 1 == num_ops
);
1884 rtx out
= is_last_op
? result
: gen_reg_rtx (SImode
);
1886 enum insn_code opcode
= tilepro_multiply_get_opcode (entry
);
1887 if (opcode
== CODE_FOR_ashlsi3
)
1889 /* Handle shift by immediate. This is a special case because
1890 the meaning of the second operand is a constant shift
1891 count rather than an operand index. */
1893 /* Make sure the shift count is in range. Zero should not
1895 const int shift_count
= entry
->rhs
;
1896 gcc_assert (shift_count
> 0 && shift_count
< 32);
1898 /* Emit the actual instruction. */
1899 emit_insn (GEN_FCN (opcode
)
1900 (out
, subexprs
[entry
->lhs
],
1901 gen_rtx_CONST_INT (SImode
, shift_count
)));
1905 /* Handle a normal two-operand instruction, such as add or
1908 /* Make sure we are referring to a previously computed
1910 gcc_assert (entry
->rhs
< num_subexprs
);
1912 /* Emit the actual instruction. */
1913 emit_insn (GEN_FCN (opcode
)
1914 (out
, subexprs
[entry
->lhs
], subexprs
[entry
->rhs
]));
1917 /* Record this subexpression for use by later expressions. */
1918 subexprs
[num_subexprs
++] = out
;
1923 /* bsearch helper function. */
1925 tilepro_compare_multipliers (const void *key
, const void *t
)
1927 return *(const int *) key
-
1928 ((const struct tilepro_multiply_insn_seq
*) t
)->multiplier
;
1932 /* Returns the tilepro_multiply_insn_seq for multiplier, or NULL if
1934 static const struct tilepro_multiply_insn_seq
*
1935 tilepro_find_multiply_insn_seq_for_constant (int multiplier
)
1937 return ((const struct tilepro_multiply_insn_seq
*)
1938 bsearch (&multiplier
, tilepro_multiply_insn_seq_table
,
1939 tilepro_multiply_insn_seq_table_size
,
1940 sizeof tilepro_multiply_insn_seq_table
[0],
1941 tilepro_compare_multipliers
));
1945 /* Try to a expand constant multiply in SImode by looking it up in a
1946 precompiled table. OP0 is the result operand, OP1 is the source
1947 operand, and MULTIPLIER is the value of the constant. Return true
1950 tilepro_expand_const_mulsi (rtx op0
, rtx op1
, int multiplier
)
1952 /* See if we have precomputed an efficient way to multiply by this
1954 const struct tilepro_multiply_insn_seq
*seq
=
1955 tilepro_find_multiply_insn_seq_for_constant (multiplier
);
1958 tilepro_expand_constant_multiply_given_sequence (op0
, op1
, seq
);
1966 /* Expand the mulsi pattern. */
1968 tilepro_expand_mulsi (rtx op0
, rtx op1
, rtx op2
)
1970 if (CONST_INT_P (op2
))
1972 HOST_WIDE_INT n
= trunc_int_for_mode (INTVAL (op2
), SImode
);
1973 return tilepro_expand_const_mulsi (op0
, op1
, n
);
1979 /* Expand a high multiply pattern in SImode. RESULT, OP1, OP2 are the
1980 operands, and SIGN is true if it's a signed multiply, and false if
1981 it's an unsigned multiply. */
1983 tilepro_expand_high_multiply (rtx result
, rtx op1
, rtx op2
, bool sign
)
1985 rtx tmp0
= gen_reg_rtx (SImode
);
1986 rtx tmp1
= gen_reg_rtx (SImode
);
1987 rtx tmp2
= gen_reg_rtx (SImode
);
1988 rtx tmp3
= gen_reg_rtx (SImode
);
1989 rtx tmp4
= gen_reg_rtx (SImode
);
1990 rtx tmp5
= gen_reg_rtx (SImode
);
1991 rtx tmp6
= gen_reg_rtx (SImode
);
1992 rtx tmp7
= gen_reg_rtx (SImode
);
1993 rtx tmp8
= gen_reg_rtx (SImode
);
1994 rtx tmp9
= gen_reg_rtx (SImode
);
1995 rtx tmp10
= gen_reg_rtx (SImode
);
1996 rtx tmp11
= gen_reg_rtx (SImode
);
1997 rtx tmp12
= gen_reg_rtx (SImode
);
1998 rtx tmp13
= gen_reg_rtx (SImode
);
1999 rtx result_lo
= gen_reg_rtx (SImode
);
2003 emit_insn (gen_insn_mulhl_su (tmp0
, op1
, op2
));
2004 emit_insn (gen_insn_mulhl_su (tmp1
, op2
, op1
));
2005 emit_insn (gen_insn_mulll_uu (tmp2
, op1
, op2
));
2006 emit_insn (gen_insn_mulhh_ss (tmp3
, op1
, op2
));
2010 emit_insn (gen_insn_mulhl_uu (tmp0
, op1
, op2
));
2011 emit_insn (gen_insn_mulhl_uu (tmp1
, op2
, op1
));
2012 emit_insn (gen_insn_mulll_uu (tmp2
, op1
, op2
));
2013 emit_insn (gen_insn_mulhh_uu (tmp3
, op1
, op2
));
2016 emit_move_insn (tmp4
, (gen_rtx_ASHIFT (SImode
, tmp0
, GEN_INT (16))));
2018 emit_move_insn (tmp5
, (gen_rtx_ASHIFT (SImode
, tmp1
, GEN_INT (16))));
2020 emit_move_insn (tmp6
, (gen_rtx_PLUS (SImode
, tmp4
, tmp5
)));
2021 emit_move_insn (result_lo
, (gen_rtx_PLUS (SImode
, tmp2
, tmp6
)));
2023 emit_move_insn (tmp7
, gen_rtx_LTU (SImode
, tmp6
, tmp4
));
2024 emit_move_insn (tmp8
, gen_rtx_LTU (SImode
, result_lo
, tmp2
));
2028 emit_move_insn (tmp9
, (gen_rtx_ASHIFTRT (SImode
, tmp0
, GEN_INT (16))));
2029 emit_move_insn (tmp10
, (gen_rtx_ASHIFTRT (SImode
, tmp1
, GEN_INT (16))));
2033 emit_move_insn (tmp9
, (gen_rtx_LSHIFTRT (SImode
, tmp0
, GEN_INT (16))));
2034 emit_move_insn (tmp10
, (gen_rtx_LSHIFTRT (SImode
, tmp1
, GEN_INT (16))));
2037 emit_move_insn (tmp11
, (gen_rtx_PLUS (SImode
, tmp3
, tmp7
)));
2038 emit_move_insn (tmp12
, (gen_rtx_PLUS (SImode
, tmp8
, tmp9
)));
2039 emit_move_insn (tmp13
, (gen_rtx_PLUS (SImode
, tmp11
, tmp12
)));
2040 emit_move_insn (result
, (gen_rtx_PLUS (SImode
, tmp13
, tmp10
)));
2044 /* Implement smulsi3_highpart. */
2046 tilepro_expand_smulsi3_highpart (rtx op0
, rtx op1
, rtx op2
)
2048 tilepro_expand_high_multiply (op0
, op1
, op2
, true);
2052 /* Implement umulsi3_highpart. */
2054 tilepro_expand_umulsi3_highpart (rtx op0
, rtx op1
, rtx op2
)
2056 tilepro_expand_high_multiply (op0
, op1
, op2
, false);
2061 /* Compare and branches */
2063 /* Helper function to handle DImode for tilepro_emit_setcc_internal. */
2065 tilepro_emit_setcc_internal_di (rtx res
, enum rtx_code code
, rtx op0
, rtx op1
)
2067 rtx operands
[2], lo_half
[2], hi_half
[2];
2068 rtx tmp
, tmp0
, tmp1
, tmp2
;
2071 /* Reduce the number of cases we need to handle by reversing the
2081 /* We handle these compares directly. */
2088 /* Reverse the operands. */
2093 /* We should not have called this with any other code. */
2099 code
= swap_condition (code
);
2100 tmp
= op0
, op0
= op1
, op1
= tmp
;
2106 split_di (operands
, 2, lo_half
, hi_half
);
2108 if (!reg_or_0_operand (lo_half
[0], SImode
))
2109 lo_half
[0] = force_reg (SImode
, lo_half
[0]);
2111 if (!reg_or_0_operand (hi_half
[0], SImode
))
2112 hi_half
[0] = force_reg (SImode
, hi_half
[0]);
2114 if (!CONST_INT_P (lo_half
[1]) && !register_operand (lo_half
[1], SImode
))
2115 lo_half
[1] = force_reg (SImode
, lo_half
[1]);
2117 if (!CONST_INT_P (hi_half
[1]) && !register_operand (hi_half
[1], SImode
))
2118 hi_half
[1] = force_reg (SImode
, hi_half
[1]);
2120 tmp0
= gen_reg_rtx (SImode
);
2121 tmp1
= gen_reg_rtx (SImode
);
2122 tmp2
= gen_reg_rtx (SImode
);
2127 emit_insn (gen_insn_seq (tmp0
, lo_half
[0], lo_half
[1]));
2128 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2129 emit_insn (gen_andsi3 (res
, tmp0
, tmp1
));
2133 emit_insn (gen_insn_sne (tmp0
, lo_half
[0], lo_half
[1]));
2134 emit_insn (gen_insn_sne (tmp1
, hi_half
[0], hi_half
[1]));
2135 emit_insn (gen_iorsi3 (res
, tmp0
, tmp1
));
2139 emit_insn (gen_insn_slte (tmp0
, hi_half
[0], hi_half
[1]));
2140 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2141 emit_insn (gen_insn_slte_u (tmp2
, lo_half
[0], lo_half
[1]));
2142 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2145 if (operands
[1] == const0_rtx
)
2147 emit_insn (gen_lshrsi3 (res
, hi_half
[0], GEN_INT (31)));
2152 emit_insn (gen_insn_slt (tmp0
, hi_half
[0], hi_half
[1]));
2153 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2154 emit_insn (gen_insn_slt_u (tmp2
, lo_half
[0], lo_half
[1]));
2155 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2159 emit_insn (gen_insn_slte_u (tmp0
, hi_half
[0], hi_half
[1]));
2160 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2161 emit_insn (gen_insn_slte_u (tmp2
, lo_half
[0], lo_half
[1]));
2162 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2165 emit_insn (gen_insn_slt_u (tmp0
, hi_half
[0], hi_half
[1]));
2166 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2167 emit_insn (gen_insn_slt_u (tmp2
, lo_half
[0], lo_half
[1]));
2168 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2178 /* Certain simplifications can be done to make invalid setcc
2179 operations valid. Return the final comparison, or NULL if we can't
2182 tilepro_emit_setcc_internal (rtx res
, enum rtx_code code
, rtx op0
, rtx op1
,
2183 enum machine_mode cmp_mode
)
2188 if (cmp_mode
== DImode
)
2190 return tilepro_emit_setcc_internal_di (res
, code
, op0
, op1
);
2193 /* The general case: fold the comparison code to the types of
2194 compares that we have, choosing the branch as necessary. */
2204 /* We have these compares. */
2211 /* We do not have these compares, so we reverse the
2217 /* We should not have called this with any other code. */
2223 code
= swap_condition (code
);
2224 tmp
= op0
, op0
= op1
, op1
= tmp
;
2227 if (!reg_or_0_operand (op0
, SImode
))
2228 op0
= force_reg (SImode
, op0
);
2230 if (!CONST_INT_P (op1
) && !register_operand (op1
, SImode
))
2231 op1
= force_reg (SImode
, op1
);
2233 /* Return the setcc comparison. */
2234 emit_insn (gen_rtx_SET (VOIDmode
, res
,
2235 gen_rtx_fmt_ee (code
, SImode
, op0
, op1
)));
2241 /* Implement cstore patterns. */
2243 tilepro_emit_setcc (rtx operands
[], enum machine_mode cmp_mode
)
2246 tilepro_emit_setcc_internal (operands
[0], GET_CODE (operands
[1]),
2247 operands
[2], operands
[3], cmp_mode
);
2251 /* Return whether CODE is a signed comparison. */
2253 signed_compare_p (enum rtx_code code
)
2255 return (code
== EQ
|| code
== NE
|| code
== LT
|| code
== LE
2256 || code
== GT
|| code
== GE
);
2260 /* Generate the comparison for an SImode conditional branch. */
2262 tilepro_emit_cc_test (enum rtx_code code
, rtx op0
, rtx op1
,
2263 enum machine_mode cmp_mode
, bool eq_ne_only
)
2265 enum rtx_code branch_code
;
2268 /* Check for a compare against zero using a comparison we can do
2270 if (cmp_mode
!= DImode
2271 && op1
== const0_rtx
2272 && (code
== EQ
|| code
== NE
2273 || (!eq_ne_only
&& signed_compare_p (code
))))
2275 op0
= force_reg (SImode
, op0
);
2276 return gen_rtx_fmt_ee (code
, VOIDmode
, op0
, const0_rtx
);
2279 /* The general case: fold the comparison code to the types of
2280 compares that we have, choosing the branch as necessary. */
2288 /* We have these compares. */
2297 /* These must be reversed (except NE, but let's
2299 code
= reverse_condition (code
);
2307 if (cmp_mode
!= DImode
2308 && CONST_INT_P (op1
) && (!satisfies_constraint_I (op1
) || code
== LEU
))
2310 HOST_WIDE_INT n
= trunc_int_for_mode (INTVAL (op1
), SImode
);
2315 /* Subtract off the value we want to compare against and see
2316 if we get zero. This is cheaper than creating a constant
2317 in a register. Except that subtracting -128 is more
2318 expensive than seqi to -128, so we leave that alone. */
2319 /* ??? Don't do this when comparing against symbols,
2320 otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
2321 0), which will be declared false out of hand (at least
2323 if (!(symbolic_operand (op0
, VOIDmode
)
2324 || (REG_P (op0
) && REG_POINTER (op0
))))
2326 /* To compare against MIN_INT, we add MIN_INT and check
2329 if (n
!= -2147483647 - 1)
2334 op0
= force_reg (SImode
, op0
);
2335 temp
= gen_reg_rtx (SImode
);
2336 emit_insn (gen_addsi3 (temp
, op0
, gen_int_si (add
)));
2337 return gen_rtx_fmt_ee (reverse_condition (branch_code
),
2338 VOIDmode
, temp
, const0_rtx
);
2348 /* Change ((unsigned)x < 0x1000) into !((unsigned)x >> 12),
2351 int first
= exact_log2 (code
== LTU
? n
: n
+ 1);
2354 op0
= force_reg (SImode
, op0
);
2355 temp
= gen_reg_rtx (SImode
);
2356 emit_move_insn (temp
,
2357 gen_rtx_LSHIFTRT (SImode
, op0
,
2358 gen_int_si (first
)));
2359 return gen_rtx_fmt_ee (reverse_condition (branch_code
),
2360 VOIDmode
, temp
, const0_rtx
);
2370 /* Compute a flag saying whether we should branch. */
2371 temp
= gen_reg_rtx (SImode
);
2372 tilepro_emit_setcc_internal (temp
, code
, op0
, op1
, cmp_mode
);
2374 /* Return the branch comparison. */
2375 return gen_rtx_fmt_ee (branch_code
, VOIDmode
, temp
, const0_rtx
);
2379 /* Generate the comparison for a conditional branch. */
2381 tilepro_emit_conditional_branch (rtx operands
[], enum machine_mode cmp_mode
)
2384 tilepro_emit_cc_test (GET_CODE (operands
[0]), operands
[1], operands
[2],
2386 rtx branch_rtx
= gen_rtx_SET (VOIDmode
, pc_rtx
,
2387 gen_rtx_IF_THEN_ELSE (VOIDmode
, cmp_rtx
,
2392 emit_jump_insn (branch_rtx
);
2396 /* Implement the movsicc pattern. */
2398 tilepro_emit_conditional_move (rtx cmp
)
2401 tilepro_emit_cc_test (GET_CODE (cmp
), XEXP (cmp
, 0), XEXP (cmp
, 1),
2402 GET_MODE (XEXP (cmp
, 0)), true);
2406 /* Return true if INSN is annotated with a REG_BR_PROB note that
2407 indicates it's a branch that's predicted taken. */
2409 cbranch_predicted_p (rtx insn
)
2411 rtx x
= find_reg_note (insn
, REG_BR_PROB
, 0);
2415 int pred_val
= XINT (x
, 0);
2417 return pred_val
>= REG_BR_PROB_BASE
/ 2;
2424 /* Output assembly code for a specific branch instruction, appending
2425 the branch prediction flag to the opcode if appropriate. */
2427 tilepro_output_simple_cbranch_with_opcode (rtx insn
, const char *opcode
,
2428 int regop
, bool netreg_p
,
2429 bool reverse_predicted
)
2431 static char buf
[64];
2432 sprintf (buf
, "%s%s\t%%%c%d, %%l0", opcode
,
2433 (cbranch_predicted_p (insn
) ^ reverse_predicted
) ? "t" : "",
2434 netreg_p
? 'N' : 'r', regop
);
2439 /* Output assembly code for a specific branch instruction, appending
2440 the branch prediction flag to the opcode if appropriate. */
2442 tilepro_output_cbranch_with_opcode (rtx insn
, rtx
*operands
,
2444 const char *rev_opcode
,
2445 int regop
, bool netreg_p
)
2447 const char *branch_if_false
;
2448 rtx taken
, not_taken
;
2449 bool is_simple_branch
;
2451 gcc_assert (LABEL_P (operands
[0]));
2453 is_simple_branch
= true;
2454 if (INSN_ADDRESSES_SET_P ())
2456 int from_addr
= INSN_ADDRESSES (INSN_UID (insn
));
2457 int to_addr
= INSN_ADDRESSES (INSN_UID (operands
[0]));
2458 int delta
= to_addr
- from_addr
;
2459 is_simple_branch
= IN_RANGE (delta
, -524288, 524280);
2462 if (is_simple_branch
)
2464 /* Just a simple conditional branch. */
2466 tilepro_output_simple_cbranch_with_opcode (insn
, opcode
, regop
,
2470 /* Generate a reversed branch around a direct jump. This fallback
2471 does not use branch-likely instructions. */
2472 not_taken
= gen_label_rtx ();
2473 taken
= operands
[0];
2475 /* Generate the reversed branch to NOT_TAKEN. */
2476 operands
[0] = not_taken
;
2478 tilepro_output_simple_cbranch_with_opcode (insn
, rev_opcode
, regop
,
2480 output_asm_insn (branch_if_false
, operands
);
2482 output_asm_insn ("j\t%l0", &taken
);
2484 /* Output NOT_TAKEN. */
2485 targetm
.asm_out
.internal_label (asm_out_file
, "L",
2486 CODE_LABEL_NUMBER (not_taken
));
2491 /* Output assembly code for a conditional branch instruction. */
2493 tilepro_output_cbranch (rtx insn
, rtx
*operands
, bool reversed
)
2495 enum rtx_code code
= GET_CODE (operands
[1]);
2497 const char *rev_opcode
;
2500 code
= reverse_condition (code
);
2518 rev_opcode
= "blez";
2526 rev_opcode
= "bgez";
2533 tilepro_output_cbranch_with_opcode (insn
, operands
, opcode
, rev_opcode
,
2538 /* Implement the tablejump pattern. */
2540 tilepro_expand_tablejump (rtx op0
, rtx op1
)
2544 rtx table
= gen_rtx_LABEL_REF (Pmode
, op1
);
2545 rtx temp
= gen_reg_rtx (Pmode
);
2546 rtx text_label_symbol
= tilepro_text_label_symbol ();
2547 rtx text_label_rtx
= tilepro_text_label_rtx ();
2549 emit_insn (gen_addli_pcrel (temp
, text_label_rtx
,
2550 table
, text_label_symbol
));
2551 emit_insn (gen_auli_pcrel (temp
, temp
, table
, text_label_symbol
));
2552 emit_move_insn (temp
,
2553 gen_rtx_PLUS (Pmode
,
2554 convert_to_mode (Pmode
, op0
, false),
2559 emit_jump_insn (gen_tablejump_aux (op0
, op1
));
2563 /* Expand a builtin vector binary op, by calling gen function GEN with
2564 operands in the proper modes. DEST is converted to DEST_MODE, and
2565 src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE. */
2567 tilepro_expand_builtin_vector_binop (rtx (*gen
) (rtx
, rtx
, rtx
),
2568 enum machine_mode dest_mode
,
2570 enum machine_mode src_mode
,
2571 rtx src0
, rtx src1
, bool do_src1
)
2573 dest
= gen_lowpart (dest_mode
, dest
);
2575 if (src0
== const0_rtx
)
2576 src0
= CONST0_RTX (src_mode
);
2578 src0
= gen_lowpart (src_mode
, src0
);
2582 if (src1
== const0_rtx
)
2583 src1
= CONST0_RTX (src_mode
);
2585 src1
= gen_lowpart (src_mode
, src1
);
2588 emit_insn ((*gen
) (dest
, src0
, src1
));
2595 struct tile_builtin_info
2597 enum insn_code icode
;
2601 static struct tile_builtin_info tilepro_builtin_info
[TILEPRO_BUILTIN_max
] = {
2602 { CODE_FOR_addsi3
, NULL
}, /* add */
2603 { CODE_FOR_insn_addb
, NULL
}, /* addb */
2604 { CODE_FOR_insn_addbs_u
, NULL
}, /* addbs_u */
2605 { CODE_FOR_insn_addh
, NULL
}, /* addh */
2606 { CODE_FOR_insn_addhs
, NULL
}, /* addhs */
2607 { CODE_FOR_insn_addib
, NULL
}, /* addib */
2608 { CODE_FOR_insn_addih
, NULL
}, /* addih */
2609 { CODE_FOR_insn_addlis
, NULL
}, /* addlis */
2610 { CODE_FOR_ssaddsi3
, NULL
}, /* adds */
2611 { CODE_FOR_insn_adiffb_u
, NULL
}, /* adiffb_u */
2612 { CODE_FOR_insn_adiffh
, NULL
}, /* adiffh */
2613 { CODE_FOR_andsi3
, NULL
}, /* and */
2614 { CODE_FOR_insn_auli
, NULL
}, /* auli */
2615 { CODE_FOR_insn_avgb_u
, NULL
}, /* avgb_u */
2616 { CODE_FOR_insn_avgh
, NULL
}, /* avgh */
2617 { CODE_FOR_insn_bitx
, NULL
}, /* bitx */
2618 { CODE_FOR_bswapsi2
, NULL
}, /* bytex */
2619 { CODE_FOR_clzsi2
, NULL
}, /* clz */
2620 { CODE_FOR_insn_crc32_32
, NULL
}, /* crc32_32 */
2621 { CODE_FOR_insn_crc32_8
, NULL
}, /* crc32_8 */
2622 { CODE_FOR_ctzsi2
, NULL
}, /* ctz */
2623 { CODE_FOR_insn_drain
, NULL
}, /* drain */
2624 { CODE_FOR_insn_dtlbpr
, NULL
}, /* dtlbpr */
2625 { CODE_FOR_insn_dword_align
, NULL
}, /* dword_align */
2626 { CODE_FOR_insn_finv
, NULL
}, /* finv */
2627 { CODE_FOR_insn_flush
, NULL
}, /* flush */
2628 { CODE_FOR_insn_fnop
, NULL
}, /* fnop */
2629 { CODE_FOR_insn_icoh
, NULL
}, /* icoh */
2630 { CODE_FOR_insn_ill
, NULL
}, /* ill */
2631 { CODE_FOR_insn_info
, NULL
}, /* info */
2632 { CODE_FOR_insn_infol
, NULL
}, /* infol */
2633 { CODE_FOR_insn_inthb
, NULL
}, /* inthb */
2634 { CODE_FOR_insn_inthh
, NULL
}, /* inthh */
2635 { CODE_FOR_insn_intlb
, NULL
}, /* intlb */
2636 { CODE_FOR_insn_intlh
, NULL
}, /* intlh */
2637 { CODE_FOR_insn_inv
, NULL
}, /* inv */
2638 { CODE_FOR_insn_lb
, NULL
}, /* lb */
2639 { CODE_FOR_insn_lb_u
, NULL
}, /* lb_u */
2640 { CODE_FOR_insn_lh
, NULL
}, /* lh */
2641 { CODE_FOR_insn_lh_u
, NULL
}, /* lh_u */
2642 { CODE_FOR_insn_lnk
, NULL
}, /* lnk */
2643 { CODE_FOR_insn_lw
, NULL
}, /* lw */
2644 { CODE_FOR_insn_lw_na
, NULL
}, /* lw_na */
2645 { CODE_FOR_insn_lb_L2
, NULL
}, /* lb_L2 */
2646 { CODE_FOR_insn_lb_u_L2
, NULL
}, /* lb_u_L2 */
2647 { CODE_FOR_insn_lh_L2
, NULL
}, /* lh_L2 */
2648 { CODE_FOR_insn_lh_u_L2
, NULL
}, /* lh_u_L2 */
2649 { CODE_FOR_insn_lw_L2
, NULL
}, /* lw_L2 */
2650 { CODE_FOR_insn_lw_na_L2
, NULL
}, /* lw_na_L2 */
2651 { CODE_FOR_insn_lb_miss
, NULL
}, /* lb_miss */
2652 { CODE_FOR_insn_lb_u_miss
, NULL
}, /* lb_u_miss */
2653 { CODE_FOR_insn_lh_miss
, NULL
}, /* lh_miss */
2654 { CODE_FOR_insn_lh_u_miss
, NULL
}, /* lh_u_miss */
2655 { CODE_FOR_insn_lw_miss
, NULL
}, /* lw_miss */
2656 { CODE_FOR_insn_lw_na_miss
, NULL
}, /* lw_na_miss */
2657 { CODE_FOR_insn_maxb_u
, NULL
}, /* maxb_u */
2658 { CODE_FOR_insn_maxh
, NULL
}, /* maxh */
2659 { CODE_FOR_insn_maxib_u
, NULL
}, /* maxib_u */
2660 { CODE_FOR_insn_maxih
, NULL
}, /* maxih */
2661 { CODE_FOR_memory_barrier
, NULL
}, /* mf */
2662 { CODE_FOR_insn_mfspr
, NULL
}, /* mfspr */
2663 { CODE_FOR_insn_minb_u
, NULL
}, /* minb_u */
2664 { CODE_FOR_insn_minh
, NULL
}, /* minh */
2665 { CODE_FOR_insn_minib_u
, NULL
}, /* minib_u */
2666 { CODE_FOR_insn_minih
, NULL
}, /* minih */
2667 { CODE_FOR_insn_mm
, NULL
}, /* mm */
2668 { CODE_FOR_insn_mnz
, NULL
}, /* mnz */
2669 { CODE_FOR_insn_mnzb
, NULL
}, /* mnzb */
2670 { CODE_FOR_insn_mnzh
, NULL
}, /* mnzh */
2671 { CODE_FOR_movsi
, NULL
}, /* move */
2672 { CODE_FOR_insn_movelis
, NULL
}, /* movelis */
2673 { CODE_FOR_insn_mtspr
, NULL
}, /* mtspr */
2674 { CODE_FOR_insn_mulhh_ss
, NULL
}, /* mulhh_ss */
2675 { CODE_FOR_insn_mulhh_su
, NULL
}, /* mulhh_su */
2676 { CODE_FOR_insn_mulhh_uu
, NULL
}, /* mulhh_uu */
2677 { CODE_FOR_insn_mulhha_ss
, NULL
}, /* mulhha_ss */
2678 { CODE_FOR_insn_mulhha_su
, NULL
}, /* mulhha_su */
2679 { CODE_FOR_insn_mulhha_uu
, NULL
}, /* mulhha_uu */
2680 { CODE_FOR_insn_mulhhsa_uu
, NULL
}, /* mulhhsa_uu */
2681 { CODE_FOR_insn_mulhl_ss
, NULL
}, /* mulhl_ss */
2682 { CODE_FOR_insn_mulhl_su
, NULL
}, /* mulhl_su */
2683 { CODE_FOR_insn_mulhl_us
, NULL
}, /* mulhl_us */
2684 { CODE_FOR_insn_mulhl_uu
, NULL
}, /* mulhl_uu */
2685 { CODE_FOR_insn_mulhla_ss
, NULL
}, /* mulhla_ss */
2686 { CODE_FOR_insn_mulhla_su
, NULL
}, /* mulhla_su */
2687 { CODE_FOR_insn_mulhla_us
, NULL
}, /* mulhla_us */
2688 { CODE_FOR_insn_mulhla_uu
, NULL
}, /* mulhla_uu */
2689 { CODE_FOR_insn_mulhlsa_uu
, NULL
}, /* mulhlsa_uu */
2690 { CODE_FOR_insn_mulll_ss
, NULL
}, /* mulll_ss */
2691 { CODE_FOR_insn_mulll_su
, NULL
}, /* mulll_su */
2692 { CODE_FOR_insn_mulll_uu
, NULL
}, /* mulll_uu */
2693 { CODE_FOR_insn_mullla_ss
, NULL
}, /* mullla_ss */
2694 { CODE_FOR_insn_mullla_su
, NULL
}, /* mullla_su */
2695 { CODE_FOR_insn_mullla_uu
, NULL
}, /* mullla_uu */
2696 { CODE_FOR_insn_mulllsa_uu
, NULL
}, /* mulllsa_uu */
2697 { CODE_FOR_insn_mvnz
, NULL
}, /* mvnz */
2698 { CODE_FOR_insn_mvz
, NULL
}, /* mvz */
2699 { CODE_FOR_insn_mz
, NULL
}, /* mz */
2700 { CODE_FOR_insn_mzb
, NULL
}, /* mzb */
2701 { CODE_FOR_insn_mzh
, NULL
}, /* mzh */
2702 { CODE_FOR_insn_nap
, NULL
}, /* nap */
2703 { CODE_FOR_nop
, NULL
}, /* nop */
2704 { CODE_FOR_insn_nor
, NULL
}, /* nor */
2705 { CODE_FOR_iorsi3
, NULL
}, /* or */
2706 { CODE_FOR_insn_packbs_u
, NULL
}, /* packbs_u */
2707 { CODE_FOR_insn_packhb
, NULL
}, /* packhb */
2708 { CODE_FOR_insn_packhs
, NULL
}, /* packhs */
2709 { CODE_FOR_insn_packlb
, NULL
}, /* packlb */
2710 { CODE_FOR_popcountsi2
, NULL
}, /* pcnt */
2711 { CODE_FOR_insn_prefetch
, NULL
}, /* prefetch */
2712 { CODE_FOR_insn_prefetch_L1
, NULL
}, /* prefetch_L1 */
2713 { CODE_FOR_rotlsi3
, NULL
}, /* rl */
2714 { CODE_FOR_insn_s1a
, NULL
}, /* s1a */
2715 { CODE_FOR_insn_s2a
, NULL
}, /* s2a */
2716 { CODE_FOR_insn_s3a
, NULL
}, /* s3a */
2717 { CODE_FOR_insn_sadab_u
, NULL
}, /* sadab_u */
2718 { CODE_FOR_insn_sadah
, NULL
}, /* sadah */
2719 { CODE_FOR_insn_sadah_u
, NULL
}, /* sadah_u */
2720 { CODE_FOR_insn_sadb_u
, NULL
}, /* sadb_u */
2721 { CODE_FOR_insn_sadh
, NULL
}, /* sadh */
2722 { CODE_FOR_insn_sadh_u
, NULL
}, /* sadh_u */
2723 { CODE_FOR_insn_sb
, NULL
}, /* sb */
2724 { CODE_FOR_insn_seq
, NULL
}, /* seq */
2725 { CODE_FOR_insn_seqb
, NULL
}, /* seqb */
2726 { CODE_FOR_insn_seqh
, NULL
}, /* seqh */
2727 { CODE_FOR_insn_seqib
, NULL
}, /* seqib */
2728 { CODE_FOR_insn_seqih
, NULL
}, /* seqih */
2729 { CODE_FOR_insn_sh
, NULL
}, /* sh */
2730 { CODE_FOR_ashlsi3
, NULL
}, /* shl */
2731 { CODE_FOR_insn_shlb
, NULL
}, /* shlb */
2732 { CODE_FOR_insn_shlh
, NULL
}, /* shlh */
2733 { CODE_FOR_insn_shlb
, NULL
}, /* shlib */
2734 { CODE_FOR_insn_shlh
, NULL
}, /* shlih */
2735 { CODE_FOR_lshrsi3
, NULL
}, /* shr */
2736 { CODE_FOR_insn_shrb
, NULL
}, /* shrb */
2737 { CODE_FOR_insn_shrh
, NULL
}, /* shrh */
2738 { CODE_FOR_insn_shrb
, NULL
}, /* shrib */
2739 { CODE_FOR_insn_shrh
, NULL
}, /* shrih */
2740 { CODE_FOR_insn_slt
, NULL
}, /* slt */
2741 { CODE_FOR_insn_slt_u
, NULL
}, /* slt_u */
2742 { CODE_FOR_insn_sltb
, NULL
}, /* sltb */
2743 { CODE_FOR_insn_sltb_u
, NULL
}, /* sltb_u */
2744 { CODE_FOR_insn_slte
, NULL
}, /* slte */
2745 { CODE_FOR_insn_slte_u
, NULL
}, /* slte_u */
2746 { CODE_FOR_insn_slteb
, NULL
}, /* slteb */
2747 { CODE_FOR_insn_slteb_u
, NULL
}, /* slteb_u */
2748 { CODE_FOR_insn_slteh
, NULL
}, /* slteh */
2749 { CODE_FOR_insn_slteh_u
, NULL
}, /* slteh_u */
2750 { CODE_FOR_insn_slth
, NULL
}, /* slth */
2751 { CODE_FOR_insn_slth_u
, NULL
}, /* slth_u */
2752 { CODE_FOR_insn_sltib
, NULL
}, /* sltib */
2753 { CODE_FOR_insn_sltib_u
, NULL
}, /* sltib_u */
2754 { CODE_FOR_insn_sltih
, NULL
}, /* sltih */
2755 { CODE_FOR_insn_sltih_u
, NULL
}, /* sltih_u */
2756 { CODE_FOR_insn_sne
, NULL
}, /* sne */
2757 { CODE_FOR_insn_sneb
, NULL
}, /* sneb */
2758 { CODE_FOR_insn_sneh
, NULL
}, /* sneh */
2759 { CODE_FOR_ashrsi3
, NULL
}, /* sra */
2760 { CODE_FOR_insn_srab
, NULL
}, /* srab */
2761 { CODE_FOR_insn_srah
, NULL
}, /* srah */
2762 { CODE_FOR_insn_srab
, NULL
}, /* sraib */
2763 { CODE_FOR_insn_srah
, NULL
}, /* sraih */
2764 { CODE_FOR_subsi3
, NULL
}, /* sub */
2765 { CODE_FOR_insn_subb
, NULL
}, /* subb */
2766 { CODE_FOR_insn_subbs_u
, NULL
}, /* subbs_u */
2767 { CODE_FOR_insn_subh
, NULL
}, /* subh */
2768 { CODE_FOR_insn_subhs
, NULL
}, /* subhs */
2769 { CODE_FOR_sssubsi3
, NULL
}, /* subs */
2770 { CODE_FOR_insn_sw
, NULL
}, /* sw */
2771 { CODE_FOR_insn_tblidxb0
, NULL
}, /* tblidxb0 */
2772 { CODE_FOR_insn_tblidxb1
, NULL
}, /* tblidxb1 */
2773 { CODE_FOR_insn_tblidxb2
, NULL
}, /* tblidxb2 */
2774 { CODE_FOR_insn_tblidxb3
, NULL
}, /* tblidxb3 */
2775 { CODE_FOR_insn_tns
, NULL
}, /* tns */
2776 { CODE_FOR_insn_wh64
, NULL
}, /* wh64 */
2777 { CODE_FOR_xorsi3
, NULL
}, /* xor */
2778 { CODE_FOR_tilepro_network_barrier
, NULL
}, /* network_barrier */
2779 { CODE_FOR_tilepro_idn0_receive
, NULL
}, /* idn0_receive */
2780 { CODE_FOR_tilepro_idn1_receive
, NULL
}, /* idn1_receive */
2781 { CODE_FOR_tilepro_idn_send
, NULL
}, /* idn_send */
2782 { CODE_FOR_tilepro_sn_receive
, NULL
}, /* sn_receive */
2783 { CODE_FOR_tilepro_sn_send
, NULL
}, /* sn_send */
2784 { CODE_FOR_tilepro_udn0_receive
, NULL
}, /* udn0_receive */
2785 { CODE_FOR_tilepro_udn1_receive
, NULL
}, /* udn1_receive */
2786 { CODE_FOR_tilepro_udn2_receive
, NULL
}, /* udn2_receive */
2787 { CODE_FOR_tilepro_udn3_receive
, NULL
}, /* udn3_receive */
2788 { CODE_FOR_tilepro_udn_send
, NULL
}, /* udn_send */
2792 struct tilepro_builtin_def
2795 enum tilepro_builtin code
;
2797 /* The first character is the return type. Subsequent characters
2798 are the argument types. See char_to_type. */
2803 static const struct tilepro_builtin_def tilepro_builtins
[] = {
2804 { "__insn_add", TILEPRO_INSN_ADD
, true, "lll" },
2805 { "__insn_addb", TILEPRO_INSN_ADDB
, true, "lll" },
2806 { "__insn_addbs_u", TILEPRO_INSN_ADDBS_U
, false, "lll" },
2807 { "__insn_addh", TILEPRO_INSN_ADDH
, true, "lll" },
2808 { "__insn_addhs", TILEPRO_INSN_ADDHS
, false, "lll" },
2809 { "__insn_addi", TILEPRO_INSN_ADD
, true, "lll" },
2810 { "__insn_addib", TILEPRO_INSN_ADDIB
, true, "lll" },
2811 { "__insn_addih", TILEPRO_INSN_ADDIH
, true, "lll" },
2812 { "__insn_addli", TILEPRO_INSN_ADD
, true, "lll" },
2813 { "__insn_addlis", TILEPRO_INSN_ADDLIS
, false, "lll" },
2814 { "__insn_adds", TILEPRO_INSN_ADDS
, false, "lll" },
2815 { "__insn_adiffb_u", TILEPRO_INSN_ADIFFB_U
, true, "lll" },
2816 { "__insn_adiffh", TILEPRO_INSN_ADIFFH
, true, "lll" },
2817 { "__insn_and", TILEPRO_INSN_AND
, true, "lll" },
2818 { "__insn_andi", TILEPRO_INSN_AND
, true, "lll" },
2819 { "__insn_auli", TILEPRO_INSN_AULI
, true, "lll" },
2820 { "__insn_avgb_u", TILEPRO_INSN_AVGB_U
, true, "lll" },
2821 { "__insn_avgh", TILEPRO_INSN_AVGH
, true, "lll" },
2822 { "__insn_bitx", TILEPRO_INSN_BITX
, true, "ll" },
2823 { "__insn_bytex", TILEPRO_INSN_BYTEX
, true, "ll" },
2824 { "__insn_clz", TILEPRO_INSN_CLZ
, true, "ll" },
2825 { "__insn_crc32_32", TILEPRO_INSN_CRC32_32
, true, "lll" },
2826 { "__insn_crc32_8", TILEPRO_INSN_CRC32_8
, true, "lll" },
2827 { "__insn_ctz", TILEPRO_INSN_CTZ
, true, "ll" },
2828 { "__insn_drain", TILEPRO_INSN_DRAIN
, false, "v" },
2829 { "__insn_dtlbpr", TILEPRO_INSN_DTLBPR
, false, "vl" },
2830 { "__insn_dword_align", TILEPRO_INSN_DWORD_ALIGN
, true, "lllk" },
2831 { "__insn_finv", TILEPRO_INSN_FINV
, false, "vk" },
2832 { "__insn_flush", TILEPRO_INSN_FLUSH
, false, "vk" },
2833 { "__insn_fnop", TILEPRO_INSN_FNOP
, false, "v" },
2834 { "__insn_icoh", TILEPRO_INSN_ICOH
, false, "vk" },
2835 { "__insn_ill", TILEPRO_INSN_ILL
, false, "v" },
2836 { "__insn_info", TILEPRO_INSN_INFO
, false, "vl" },
2837 { "__insn_infol", TILEPRO_INSN_INFOL
, false, "vl" },
2838 { "__insn_inthb", TILEPRO_INSN_INTHB
, true, "lll" },
2839 { "__insn_inthh", TILEPRO_INSN_INTHH
, true, "lll" },
2840 { "__insn_intlb", TILEPRO_INSN_INTLB
, true, "lll" },
2841 { "__insn_intlh", TILEPRO_INSN_INTLH
, true, "lll" },
2842 { "__insn_inv", TILEPRO_INSN_INV
, false, "vp" },
2843 { "__insn_lb", TILEPRO_INSN_LB
, false, "lk" },
2844 { "__insn_lb_u", TILEPRO_INSN_LB_U
, false, "lk" },
2845 { "__insn_lh", TILEPRO_INSN_LH
, false, "lk" },
2846 { "__insn_lh_u", TILEPRO_INSN_LH_U
, false, "lk" },
2847 { "__insn_lnk", TILEPRO_INSN_LNK
, true, "l" },
2848 { "__insn_lw", TILEPRO_INSN_LW
, false, "lk" },
2849 { "__insn_lw_na", TILEPRO_INSN_LW_NA
, false, "lk" },
2850 { "__insn_lb_L2", TILEPRO_INSN_LB_L2
, false, "lk" },
2851 { "__insn_lb_u_L2", TILEPRO_INSN_LB_U_L2
, false, "lk" },
2852 { "__insn_lh_L2", TILEPRO_INSN_LH_L2
, false, "lk" },
2853 { "__insn_lh_u_L2", TILEPRO_INSN_LH_U_L2
, false, "lk" },
2854 { "__insn_lw_L2", TILEPRO_INSN_LW_L2
, false, "lk" },
2855 { "__insn_lw_na_L2", TILEPRO_INSN_LW_NA_L2
, false, "lk" },
2856 { "__insn_lb_miss", TILEPRO_INSN_LB_MISS
, false, "lk" },
2857 { "__insn_lb_u_miss", TILEPRO_INSN_LB_U_MISS
, false, "lk" },
2858 { "__insn_lh_miss", TILEPRO_INSN_LH_MISS
, false, "lk" },
2859 { "__insn_lh_u_miss", TILEPRO_INSN_LH_U_MISS
, false, "lk" },
2860 { "__insn_lw_miss", TILEPRO_INSN_LW_MISS
, false, "lk" },
2861 { "__insn_lw_na_miss", TILEPRO_INSN_LW_NA_MISS
, false, "lk" },
2862 { "__insn_maxb_u", TILEPRO_INSN_MAXB_U
, true, "lll" },
2863 { "__insn_maxh", TILEPRO_INSN_MAXH
, true, "lll" },
2864 { "__insn_maxib_u", TILEPRO_INSN_MAXIB_U
, true, "lll" },
2865 { "__insn_maxih", TILEPRO_INSN_MAXIH
, true, "lll" },
2866 { "__insn_mf", TILEPRO_INSN_MF
, false, "v" },
2867 { "__insn_mfspr", TILEPRO_INSN_MFSPR
, false, "ll" },
2868 { "__insn_minb_u", TILEPRO_INSN_MINB_U
, true, "lll" },
2869 { "__insn_minh", TILEPRO_INSN_MINH
, true, "lll" },
2870 { "__insn_minib_u", TILEPRO_INSN_MINIB_U
, true, "lll" },
2871 { "__insn_minih", TILEPRO_INSN_MINIH
, true, "lll" },
2872 { "__insn_mm", TILEPRO_INSN_MM
, true, "lllll" },
2873 { "__insn_mnz", TILEPRO_INSN_MNZ
, true, "lll" },
2874 { "__insn_mnzb", TILEPRO_INSN_MNZB
, true, "lll" },
2875 { "__insn_mnzh", TILEPRO_INSN_MNZH
, true, "lll" },
2876 { "__insn_move", TILEPRO_INSN_MOVE
, true, "ll" },
2877 { "__insn_movei", TILEPRO_INSN_MOVE
, true, "ll" },
2878 { "__insn_moveli", TILEPRO_INSN_MOVE
, true, "ll" },
2879 { "__insn_movelis", TILEPRO_INSN_MOVELIS
, false, "ll" },
2880 { "__insn_mtspr", TILEPRO_INSN_MTSPR
, false, "vll" },
2881 { "__insn_mulhh_ss", TILEPRO_INSN_MULHH_SS
, true, "lll" },
2882 { "__insn_mulhh_su", TILEPRO_INSN_MULHH_SU
, true, "lll" },
2883 { "__insn_mulhh_uu", TILEPRO_INSN_MULHH_UU
, true, "lll" },
2884 { "__insn_mulhha_ss", TILEPRO_INSN_MULHHA_SS
, true, "llll" },
2885 { "__insn_mulhha_su", TILEPRO_INSN_MULHHA_SU
, true, "llll" },
2886 { "__insn_mulhha_uu", TILEPRO_INSN_MULHHA_UU
, true, "llll" },
2887 { "__insn_mulhhsa_uu", TILEPRO_INSN_MULHHSA_UU
, true, "llll" },
2888 { "__insn_mulhl_ss", TILEPRO_INSN_MULHL_SS
, true, "lll" },
2889 { "__insn_mulhl_su", TILEPRO_INSN_MULHL_SU
, true, "lll" },
2890 { "__insn_mulhl_us", TILEPRO_INSN_MULHL_US
, true, "lll" },
2891 { "__insn_mulhl_uu", TILEPRO_INSN_MULHL_UU
, true, "lll" },
2892 { "__insn_mulhla_ss", TILEPRO_INSN_MULHLA_SS
, true, "llll" },
2893 { "__insn_mulhla_su", TILEPRO_INSN_MULHLA_SU
, true, "llll" },
2894 { "__insn_mulhla_us", TILEPRO_INSN_MULHLA_US
, true, "llll" },
2895 { "__insn_mulhla_uu", TILEPRO_INSN_MULHLA_UU
, true, "llll" },
2896 { "__insn_mulhlsa_uu", TILEPRO_INSN_MULHLSA_UU
, true, "llll" },
2897 { "__insn_mulll_ss", TILEPRO_INSN_MULLL_SS
, true, "lll" },
2898 { "__insn_mulll_su", TILEPRO_INSN_MULLL_SU
, true, "lll" },
2899 { "__insn_mulll_uu", TILEPRO_INSN_MULLL_UU
, true, "lll" },
2900 { "__insn_mullla_ss", TILEPRO_INSN_MULLLA_SS
, true, "llll" },
2901 { "__insn_mullla_su", TILEPRO_INSN_MULLLA_SU
, true, "llll" },
2902 { "__insn_mullla_uu", TILEPRO_INSN_MULLLA_UU
, true, "llll" },
2903 { "__insn_mulllsa_uu", TILEPRO_INSN_MULLLSA_UU
, true, "llll" },
2904 { "__insn_mvnz", TILEPRO_INSN_MVNZ
, true, "llll" },
2905 { "__insn_mvz", TILEPRO_INSN_MVZ
, true, "llll" },
2906 { "__insn_mz", TILEPRO_INSN_MZ
, true, "lll" },
2907 { "__insn_mzb", TILEPRO_INSN_MZB
, true, "lll" },
2908 { "__insn_mzh", TILEPRO_INSN_MZH
, true, "lll" },
2909 { "__insn_nap", TILEPRO_INSN_NAP
, false, "v" },
2910 { "__insn_nop", TILEPRO_INSN_NOP
, true, "v" },
2911 { "__insn_nor", TILEPRO_INSN_NOR
, true, "lll" },
2912 { "__insn_or", TILEPRO_INSN_OR
, true, "lll" },
2913 { "__insn_ori", TILEPRO_INSN_OR
, true, "lll" },
2914 { "__insn_packbs_u", TILEPRO_INSN_PACKBS_U
, false, "lll" },
2915 { "__insn_packhb", TILEPRO_INSN_PACKHB
, true, "lll" },
2916 { "__insn_packhs", TILEPRO_INSN_PACKHS
, false, "lll" },
2917 { "__insn_packlb", TILEPRO_INSN_PACKLB
, true, "lll" },
2918 { "__insn_pcnt", TILEPRO_INSN_PCNT
, true, "ll" },
2919 { "__insn_prefetch", TILEPRO_INSN_PREFETCH
, false, "vk" },
2920 { "__insn_prefetch_L1", TILEPRO_INSN_PREFETCH_L1
, false, "vk" },
2921 { "__insn_rl", TILEPRO_INSN_RL
, true, "lll" },
2922 { "__insn_rli", TILEPRO_INSN_RL
, true, "lll" },
2923 { "__insn_s1a", TILEPRO_INSN_S1A
, true, "lll" },
2924 { "__insn_s2a", TILEPRO_INSN_S2A
, true, "lll" },
2925 { "__insn_s3a", TILEPRO_INSN_S3A
, true, "lll" },
2926 { "__insn_sadab_u", TILEPRO_INSN_SADAB_U
, true, "llll" },
2927 { "__insn_sadah", TILEPRO_INSN_SADAH
, true, "llll" },
2928 { "__insn_sadah_u", TILEPRO_INSN_SADAH_U
, true, "llll" },
2929 { "__insn_sadb_u", TILEPRO_INSN_SADB_U
, true, "lll" },
2930 { "__insn_sadh", TILEPRO_INSN_SADH
, true, "lll" },
2931 { "__insn_sadh_u", TILEPRO_INSN_SADH_U
, true, "lll" },
2932 { "__insn_sb", TILEPRO_INSN_SB
, false, "vpl" },
2933 { "__insn_seq", TILEPRO_INSN_SEQ
, true, "lll" },
2934 { "__insn_seqb", TILEPRO_INSN_SEQB
, true, "lll" },
2935 { "__insn_seqh", TILEPRO_INSN_SEQH
, true, "lll" },
2936 { "__insn_seqi", TILEPRO_INSN_SEQ
, true, "lll" },
2937 { "__insn_seqib", TILEPRO_INSN_SEQIB
, true, "lll" },
2938 { "__insn_seqih", TILEPRO_INSN_SEQIH
, true, "lll" },
2939 { "__insn_sh", TILEPRO_INSN_SH
, false, "vpl" },
2940 { "__insn_shl", TILEPRO_INSN_SHL
, true, "lll" },
2941 { "__insn_shlb", TILEPRO_INSN_SHLB
, true, "lll" },
2942 { "__insn_shlh", TILEPRO_INSN_SHLH
, true, "lll" },
2943 { "__insn_shli", TILEPRO_INSN_SHL
, true, "lll" },
2944 { "__insn_shlib", TILEPRO_INSN_SHLIB
, true, "lll" },
2945 { "__insn_shlih", TILEPRO_INSN_SHLIH
, true, "lll" },
2946 { "__insn_shr", TILEPRO_INSN_SHR
, true, "lll" },
2947 { "__insn_shrb", TILEPRO_INSN_SHRB
, true, "lll" },
2948 { "__insn_shrh", TILEPRO_INSN_SHRH
, true, "lll" },
2949 { "__insn_shri", TILEPRO_INSN_SHR
, true, "lll" },
2950 { "__insn_shrib", TILEPRO_INSN_SHRIB
, true, "lll" },
2951 { "__insn_shrih", TILEPRO_INSN_SHRIH
, true, "lll" },
2952 { "__insn_slt", TILEPRO_INSN_SLT
, true, "lll" },
2953 { "__insn_slt_u", TILEPRO_INSN_SLT_U
, true, "lll" },
2954 { "__insn_sltb", TILEPRO_INSN_SLTB
, true, "lll" },
2955 { "__insn_sltb_u", TILEPRO_INSN_SLTB_U
, true, "lll" },
2956 { "__insn_slte", TILEPRO_INSN_SLTE
, true, "lll" },
2957 { "__insn_slte_u", TILEPRO_INSN_SLTE_U
, true, "lll" },
2958 { "__insn_slteb", TILEPRO_INSN_SLTEB
, true, "lll" },
2959 { "__insn_slteb_u", TILEPRO_INSN_SLTEB_U
, true, "lll" },
2960 { "__insn_slteh", TILEPRO_INSN_SLTEH
, true, "lll" },
2961 { "__insn_slteh_u", TILEPRO_INSN_SLTEH_U
, true, "lll" },
2962 { "__insn_slth", TILEPRO_INSN_SLTH
, true, "lll" },
2963 { "__insn_slth_u", TILEPRO_INSN_SLTH_U
, true, "lll" },
2964 { "__insn_slti", TILEPRO_INSN_SLT
, true, "lll" },
2965 { "__insn_slti_u", TILEPRO_INSN_SLT_U
, true, "lll" },
2966 { "__insn_sltib", TILEPRO_INSN_SLTIB
, true, "lll" },
2967 { "__insn_sltib_u", TILEPRO_INSN_SLTIB_U
, true, "lll" },
2968 { "__insn_sltih", TILEPRO_INSN_SLTIH
, true, "lll" },
2969 { "__insn_sltih_u", TILEPRO_INSN_SLTIH_U
, true, "lll" },
2970 { "__insn_sne", TILEPRO_INSN_SNE
, true, "lll" },
2971 { "__insn_sneb", TILEPRO_INSN_SNEB
, true, "lll" },
2972 { "__insn_sneh", TILEPRO_INSN_SNEH
, true, "lll" },
2973 { "__insn_sra", TILEPRO_INSN_SRA
, true, "lll" },
2974 { "__insn_srab", TILEPRO_INSN_SRAB
, true, "lll" },
2975 { "__insn_srah", TILEPRO_INSN_SRAH
, true, "lll" },
2976 { "__insn_srai", TILEPRO_INSN_SRA
, true, "lll" },
2977 { "__insn_sraib", TILEPRO_INSN_SRAIB
, true, "lll" },
2978 { "__insn_sraih", TILEPRO_INSN_SRAIH
, true, "lll" },
2979 { "__insn_sub", TILEPRO_INSN_SUB
, true, "lll" },
2980 { "__insn_subb", TILEPRO_INSN_SUBB
, true, "lll" },
2981 { "__insn_subbs_u", TILEPRO_INSN_SUBBS_U
, false, "lll" },
2982 { "__insn_subh", TILEPRO_INSN_SUBH
, true, "lll" },
2983 { "__insn_subhs", TILEPRO_INSN_SUBHS
, false, "lll" },
2984 { "__insn_subs", TILEPRO_INSN_SUBS
, false, "lll" },
2985 { "__insn_sw", TILEPRO_INSN_SW
, false, "vpl" },
2986 { "__insn_tblidxb0", TILEPRO_INSN_TBLIDXB0
, true, "lll" },
2987 { "__insn_tblidxb1", TILEPRO_INSN_TBLIDXB1
, true, "lll" },
2988 { "__insn_tblidxb2", TILEPRO_INSN_TBLIDXB2
, true, "lll" },
2989 { "__insn_tblidxb3", TILEPRO_INSN_TBLIDXB3
, true, "lll" },
2990 { "__insn_tns", TILEPRO_INSN_TNS
, false, "lp" },
2991 { "__insn_wh64", TILEPRO_INSN_WH64
, false, "vp" },
2992 { "__insn_xor", TILEPRO_INSN_XOR
, true, "lll" },
2993 { "__insn_xori", TILEPRO_INSN_XOR
, true, "lll" },
2994 { "__tile_network_barrier", TILEPRO_NETWORK_BARRIER
, false, "v" },
2995 { "__tile_idn0_receive", TILEPRO_IDN0_RECEIVE
, false, "l" },
2996 { "__tile_idn1_receive", TILEPRO_IDN1_RECEIVE
, false, "l" },
2997 { "__tile_idn_send", TILEPRO_IDN_SEND
, false, "vl" },
2998 { "__tile_sn_receive", TILEPRO_SN_RECEIVE
, false, "l" },
2999 { "__tile_sn_send", TILEPRO_SN_SEND
, false, "vl" },
3000 { "__tile_udn0_receive", TILEPRO_UDN0_RECEIVE
, false, "l" },
3001 { "__tile_udn1_receive", TILEPRO_UDN1_RECEIVE
, false, "l" },
3002 { "__tile_udn2_receive", TILEPRO_UDN2_RECEIVE
, false, "l" },
3003 { "__tile_udn3_receive", TILEPRO_UDN3_RECEIVE
, false, "l" },
3004 { "__tile_udn_send", TILEPRO_UDN_SEND
, false, "vl" },
3008 /* Convert a character in a builtin type string to a tree type. */
3010 char_to_type (char c
)
3012 static tree volatile_ptr_type_node
= NULL
;
3013 static tree volatile_const_ptr_type_node
= NULL
;
3015 if (volatile_ptr_type_node
== NULL
)
3017 volatile_ptr_type_node
=
3018 build_pointer_type (build_qualified_type (void_type_node
,
3019 TYPE_QUAL_VOLATILE
));
3020 volatile_const_ptr_type_node
=
3021 build_pointer_type (build_qualified_type (void_type_node
,
3023 | TYPE_QUAL_VOLATILE
));
3029 return void_type_node
;
3031 return long_unsigned_type_node
;
3033 return volatile_ptr_type_node
;
3035 return volatile_const_ptr_type_node
;
3042 /* Implement TARGET_INIT_BUILTINS. */
3044 tilepro_init_builtins (void)
3048 for (i
= 0; i
< ARRAY_SIZE (tilepro_builtins
); i
++)
3050 const struct tilepro_builtin_def
*p
= &tilepro_builtins
[i
];
3051 tree ftype
, ret_type
, arg_type_list
= void_list_node
;
3055 for (j
= strlen (p
->type
) - 1; j
> 0; j
--)
3058 tree_cons (NULL_TREE
, char_to_type (p
->type
[j
]), arg_type_list
);
3061 ret_type
= char_to_type (p
->type
[0]);
3063 ftype
= build_function_type (ret_type
, arg_type_list
);
3065 decl
= add_builtin_function (p
->name
, ftype
, p
->code
, BUILT_IN_MD
,
3069 TREE_READONLY (decl
) = 1;
3070 TREE_NOTHROW (decl
) = 1;
3072 if (tilepro_builtin_info
[p
->code
].fndecl
== NULL
)
3073 tilepro_builtin_info
[p
->code
].fndecl
= decl
;
3078 /* Implement TARGET_EXPAND_BUILTIN. */
3080 tilepro_expand_builtin (tree exp
,
3082 rtx subtarget ATTRIBUTE_UNUSED
,
3083 enum machine_mode mode ATTRIBUTE_UNUSED
,
3084 int ignore ATTRIBUTE_UNUSED
)
3086 #define MAX_BUILTIN_ARGS 4
3088 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
3089 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
3091 call_expr_arg_iterator iter
;
3092 enum insn_code icode
;
3093 rtx op
[MAX_BUILTIN_ARGS
+ 1], pat
;
3098 if (fcode
>= TILEPRO_BUILTIN_max
)
3099 internal_error ("bad builtin fcode");
3100 icode
= tilepro_builtin_info
[fcode
].icode
;
3102 internal_error ("bad builtin icode");
3104 nonvoid
= TREE_TYPE (TREE_TYPE (fndecl
)) != void_type_node
;
3107 FOR_EACH_CALL_EXPR_ARG (arg
, iter
, exp
)
3109 const struct insn_operand_data
*insn_op
;
3111 if (arg
== error_mark_node
)
3113 if (opnum
> MAX_BUILTIN_ARGS
)
3116 insn_op
= &insn_data
[icode
].operand
[opnum
];
3118 op
[opnum
] = expand_expr (arg
, NULL_RTX
, insn_op
->mode
, EXPAND_NORMAL
);
3120 if (!(*insn_op
->predicate
) (op
[opnum
], insn_op
->mode
))
3121 op
[opnum
] = copy_to_mode_reg (insn_op
->mode
, op
[opnum
]);
3123 if (!(*insn_op
->predicate
) (op
[opnum
], insn_op
->mode
))
3125 /* We still failed to meet the predicate even after moving
3126 into a register. Assume we needed an immediate. */
3127 error_at (EXPR_LOCATION (exp
),
3128 "operand must be an immediate of the right size");
3137 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
3139 || GET_MODE (target
) != tmode
3140 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
3141 target
= gen_reg_rtx (tmode
);
3145 fn
= GEN_FCN (icode
);
3149 pat
= fn (NULL_RTX
);
3155 pat
= fn (op
[0], op
[1]);
3158 pat
= fn (op
[0], op
[1], op
[2]);
3161 pat
= fn (op
[0], op
[1], op
[2], op
[3]);
3164 pat
= fn (op
[0], op
[1], op
[2], op
[3], op
[4]);
3180 /* Implement TARGET_BUILTIN_DECL. */
3182 tilepro_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
3184 if (code
>= TILEPRO_BUILTIN_max
)
3185 return error_mark_node
;
3187 return tilepro_builtin_info
[code
].fndecl
;
3194 /* Return whether REGNO needs to be saved in the stack frame. */
3196 need_to_save_reg (unsigned int regno
)
3198 if (!fixed_regs
[regno
] && !call_used_regs
[regno
]
3199 && df_regs_ever_live_p (regno
))
3203 && (regno
== PIC_OFFSET_TABLE_REGNUM
3204 || regno
== TILEPRO_PIC_TEXT_LABEL_REGNUM
)
3205 && (crtl
->uses_pic_offset_table
|| crtl
->saves_all_registers
))
3208 if (crtl
->calls_eh_return
)
3211 for (i
= 0; EH_RETURN_DATA_REGNO (i
) != INVALID_REGNUM
; i
++)
3213 if (regno
== EH_RETURN_DATA_REGNO (i
))
3222 /* Return the size of the register savev area. This function is only
3223 correct starting with local register allocation */
3225 tilepro_saved_regs_size (void)
3227 int reg_save_size
= 0;
3229 int offset_to_frame
;
3232 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3233 if (need_to_save_reg (regno
))
3234 reg_save_size
+= UNITS_PER_WORD
;
3236 /* Pad out the register save area if necessary to make
3237 frame_pointer_rtx be as aligned as the stack pointer. */
3238 offset_to_frame
= crtl
->args
.pretend_args_size
+ reg_save_size
;
3239 align_mask
= (STACK_BOUNDARY
/ BITS_PER_UNIT
) - 1;
3240 reg_save_size
+= (-offset_to_frame
) & align_mask
;
3242 return reg_save_size
;
3246 /* Round up frame size SIZE. */
3248 round_frame_size (int size
)
3250 return ((size
+ STACK_BOUNDARY
/ BITS_PER_UNIT
- 1)
3251 & -STACK_BOUNDARY
/ BITS_PER_UNIT
);
3255 /* Emit a store in the stack frame to save REGNO at address ADDR, and
3256 emit the corresponding REG_CFA_OFFSET note described by CFA and
3257 CFA_OFFSET. Return the emitted insn. */
3259 frame_emit_store (int regno
, int regno_note
, rtx addr
, rtx cfa
,
3262 rtx reg
= gen_rtx_REG (Pmode
, regno
);
3263 rtx mem
= gen_frame_mem (Pmode
, addr
);
3264 rtx mov
= gen_movsi (mem
, reg
);
3266 /* Describe what just happened in a way that dwarf understands. We
3267 use temporary registers to hold the address to make scheduling
3268 easier, and use the REG_CFA_OFFSET to describe the address as an
3269 offset from the CFA. */
3270 rtx reg_note
= gen_rtx_REG (Pmode
, regno_note
);
3271 rtx cfa_relative_addr
= gen_rtx_PLUS (Pmode
, cfa
, gen_int_si (cfa_offset
));
3272 rtx cfa_relative_mem
= gen_frame_mem (Pmode
, cfa_relative_addr
);
3273 rtx real
= gen_rtx_SET (VOIDmode
, cfa_relative_mem
, reg_note
);
3274 add_reg_note (mov
, REG_CFA_OFFSET
, real
);
3276 return emit_insn (mov
);
3280 /* Emit a load in the stack frame to load REGNO from address ADDR.
3281 Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
3282 non-null. Return the emitted insn. */
3284 frame_emit_load (int regno
, rtx addr
, rtx
*cfa_restores
)
3286 rtx reg
= gen_rtx_REG (Pmode
, regno
);
3287 rtx mem
= gen_frame_mem (Pmode
, addr
);
3289 *cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, *cfa_restores
);
3290 return emit_insn (gen_movsi (reg
, mem
));
3294 /* Helper function to set RTX_FRAME_RELATED_P on instructions,
3295 including sequences. */
3297 set_frame_related_p (void)
3299 rtx seq
= get_insns ();
3310 while (insn
!= NULL_RTX
)
3312 RTX_FRAME_RELATED_P (insn
) = 1;
3313 insn
= NEXT_INSN (insn
);
3315 seq
= emit_insn (seq
);
3319 seq
= emit_insn (seq
);
3320 RTX_FRAME_RELATED_P (seq
) = 1;
3326 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
3328 /* This emits code for 'sp += offset'.
3330 The ABI only allows us to modify 'sp' in a single 'addi' or
3331 'addli', so the backtracer understands it. Larger amounts cannot
3332 use those instructions, so are added by placing the offset into a
3333 large register and using 'add'.
3335 This happens after reload, so we need to expand it ourselves. */
3337 emit_sp_adjust (int offset
, int *next_scratch_regno
, bool frame_related
,
3341 rtx imm_rtx
= gen_int_si (offset
);
3344 if (satisfies_constraint_J (imm_rtx
))
3346 /* We can add this using a single addi or addli. */
3351 rtx tmp
= gen_rtx_REG (Pmode
, (*next_scratch_regno
)--);
3352 tilepro_expand_set_const32 (tmp
, imm_rtx
);
3356 /* Actually adjust the stack pointer. */
3357 insn
= emit_insn (gen_sp_adjust (stack_pointer_rtx
, stack_pointer_rtx
,
3359 REG_NOTES (insn
) = reg_notes
;
3361 /* Describe what just happened in a way that dwarf understands. */
3364 rtx real
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
3365 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3367 RTX_FRAME_RELATED_P (insn
) = 1;
3368 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, real
);
3375 /* Return whether the current function is leaf. This takes into
3376 account whether the function calls tls_get_addr. */
3378 tilepro_current_function_is_leaf (void)
3380 return crtl
->is_leaf
&& !cfun
->machine
->calls_tls_get_addr
;
3384 /* Return the frame size. */
3386 compute_total_frame_size (void)
3388 int total_size
= (get_frame_size () + tilepro_saved_regs_size ()
3389 + crtl
->outgoing_args_size
3390 + crtl
->args
.pretend_args_size
);
3392 if (!tilepro_current_function_is_leaf () || cfun
->calls_alloca
)
3394 /* Make room for save area in callee. */
3395 total_size
+= STACK_POINTER_OFFSET
;
3398 return round_frame_size (total_size
);
3402 /* Return nonzero if this function is known to have a null epilogue.
3403 This allows the optimizer to omit jumps to jumps if no stack was
3406 tilepro_can_use_return_insn_p (void)
3408 return (reload_completed
3409 && cfun
->static_chain_decl
== 0
3410 && compute_total_frame_size () == 0
3411 && tilepro_current_function_is_leaf ()
3412 && !crtl
->profile
&& !df_regs_ever_live_p (TILEPRO_LINK_REGNUM
));
3416 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'. If there
3417 is a frame pointer, it computes the value relative to
3418 that. Otherwise it uses the stack pointer. */
3420 compute_frame_addr (int offset_from_fp
, int *next_scratch_regno
)
3422 rtx base_reg_rtx
, tmp_reg_rtx
, offset_rtx
;
3423 int offset_from_base
;
3425 if (frame_pointer_needed
)
3427 base_reg_rtx
= hard_frame_pointer_rtx
;
3428 offset_from_base
= offset_from_fp
;
3432 int offset_from_sp
= compute_total_frame_size () + offset_from_fp
;
3433 base_reg_rtx
= stack_pointer_rtx
;
3434 offset_from_base
= offset_from_sp
;
3437 if (offset_from_base
== 0)
3438 return base_reg_rtx
;
3440 /* Compute the new value of the stack pointer. */
3441 tmp_reg_rtx
= gen_rtx_REG (Pmode
, (*next_scratch_regno
)--);
3442 offset_rtx
= gen_int_si (offset_from_base
);
3444 if (!tilepro_expand_addsi (tmp_reg_rtx
, base_reg_rtx
, offset_rtx
))
3446 emit_insn (gen_rtx_SET (VOIDmode
, tmp_reg_rtx
,
3447 gen_rtx_PLUS (Pmode
, base_reg_rtx
,
3455 /* The stack frame looks like this:
3460 AP -> +-------------+
3464 HFP -> +-------------+
3466 | reg save | crtl->args.pretend_args_size bytes
3469 | saved regs | tilepro_saved_regs_size() bytes
3470 FP -> +-------------+
3472 | vars | get_frame_size() bytes
3476 | stack args | crtl->outgoing_args_size bytes
3478 | HFP | 4 bytes (only here if nonleaf / alloca)
3480 | callee lr | 4 bytes (only here if nonleaf / alloca)
3482 SP -> +-------------+
3486 For functions with a frame larger than 32767 bytes, or which use
3487 alloca (), r52 is used as a frame pointer. Otherwise there is no
3490 FP is saved at SP+4 before calling a subroutine so the
3491 callee can chain. */
3493 tilepro_expand_prologue (void)
3495 #define ROUND_ROBIN_SIZE 4
3496 /* We round-robin through four scratch registers to hold temporary
3497 addresses for saving registers, to make instruction scheduling
3499 rtx reg_save_addr
[ROUND_ROBIN_SIZE
] = {
3500 NULL_RTX
, NULL_RTX
, NULL_RTX
, NULL_RTX
3503 unsigned int which_scratch
;
3504 int offset
, start_offset
, regno
;
3506 /* A register that holds a copy of the incoming fp. */
3507 int fp_copy_regno
= -1;
3509 /* A register that holds a copy of the incoming sp. */
3510 int sp_copy_regno
= -1;
3512 /* Next scratch register number to hand out (postdecrementing). */
3513 int next_scratch_regno
= 29;
3515 int total_size
= compute_total_frame_size ();
3517 if (flag_stack_usage_info
)
3518 current_function_static_stack_size
= total_size
;
3520 /* Save lr first in its special location because code after this
3521 might use the link register as a scratch register. */
3522 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM
) || crtl
->calls_eh_return
)
3523 FRP (frame_emit_store (TILEPRO_LINK_REGNUM
, TILEPRO_LINK_REGNUM
,
3524 stack_pointer_rtx
, stack_pointer_rtx
, 0));
3526 if (total_size
== 0)
3528 /* Load the PIC register if needed. */
3529 if (flag_pic
&& crtl
->uses_pic_offset_table
)
3530 load_pic_register (false);
3535 cfa
= stack_pointer_rtx
;
3537 if (frame_pointer_needed
)
3539 fp_copy_regno
= next_scratch_regno
--;
3541 /* Copy the old frame pointer aside so we can save it later. */
3542 insn
= FRP (emit_move_insn (gen_rtx_REG (word_mode
, fp_copy_regno
),
3543 hard_frame_pointer_rtx
));
3544 add_reg_note (insn
, REG_CFA_REGISTER
, NULL_RTX
);
3546 /* Set up the frame pointer. */
3547 insn
= FRP (emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
));
3548 add_reg_note (insn
, REG_CFA_DEF_CFA
, hard_frame_pointer_rtx
);
3549 cfa
= hard_frame_pointer_rtx
;
3550 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM
) = STACK_BOUNDARY
;
3552 /* fp holds a copy of the incoming sp, in case we need to store
3554 sp_copy_regno
= HARD_FRAME_POINTER_REGNUM
;
3556 else if (!tilepro_current_function_is_leaf ())
3558 /* Copy the old stack pointer aside so we can save it later. */
3559 sp_copy_regno
= next_scratch_regno
--;
3560 emit_move_insn (gen_rtx_REG (Pmode
, sp_copy_regno
),
3564 if (tilepro_current_function_is_leaf ())
3566 /* No need to store chain pointer to caller's frame. */
3567 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3568 !frame_pointer_needed
, NULL_RTX
);
3572 /* Save the frame pointer (incoming sp value) to support
3573 backtracing. First we need to create an rtx with the store
3575 rtx chain_addr
= gen_rtx_REG (Pmode
, next_scratch_regno
--);
3576 rtx size_rtx
= gen_int_si (-(total_size
- UNITS_PER_WORD
));
3578 if (add_operand (size_rtx
, Pmode
))
3580 /* Expose more parallelism by computing this value from the
3581 original stack pointer, not the one after we have pushed
3583 rtx p
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, size_rtx
);
3584 emit_insn (gen_rtx_SET (VOIDmode
, chain_addr
, p
));
3585 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3586 !frame_pointer_needed
, NULL_RTX
);
3590 /* The stack frame is large, so just store the incoming sp
3591 value at *(new_sp + UNITS_PER_WORD). */
3593 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3594 !frame_pointer_needed
, NULL_RTX
);
3595 p
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3596 GEN_INT (UNITS_PER_WORD
));
3597 emit_insn (gen_rtx_SET (VOIDmode
, chain_addr
, p
));
3600 /* Save our frame pointer for backtrace chaining. */
3601 emit_insn (gen_movsi (gen_frame_mem (SImode
, chain_addr
),
3602 gen_rtx_REG (SImode
, sp_copy_regno
)));
3605 /* Compute where to start storing registers we need to save. */
3606 start_offset
= -crtl
->args
.pretend_args_size
- UNITS_PER_WORD
;
3607 offset
= start_offset
;
3609 /* Store all registers that need saving. */
3611 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
>= 0; regno
--)
3612 if (need_to_save_reg (regno
))
3614 rtx r
= reg_save_addr
[which_scratch
];
3616 int cfa_offset
= frame_pointer_needed
? offset
: total_size
+ offset
;
3620 rtx p
= compute_frame_addr (offset
, &next_scratch_regno
);
3621 r
= gen_rtx_REG (word_mode
, next_scratch_regno
--);
3622 reg_save_addr
[which_scratch
] = r
;
3624 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3628 /* Advance to the next stack slot to store this register. */
3629 int stride
= ROUND_ROBIN_SIZE
* -UNITS_PER_WORD
;
3630 rtx p
= gen_rtx_PLUS (Pmode
, r
, GEN_INT (stride
));
3631 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3634 /* Save this register to the stack (but use the old fp value
3635 we copied aside if appropriate). */
3636 from_regno
= (fp_copy_regno
>= 0
3638 HARD_FRAME_POINTER_REGNUM
) ? fp_copy_regno
: regno
;
3639 FRP (frame_emit_store (from_regno
, regno
, r
, cfa
, cfa_offset
));
3641 offset
-= UNITS_PER_WORD
;
3642 which_scratch
= (which_scratch
+ 1) % ROUND_ROBIN_SIZE
;
3645 /* If profiling, force that to happen after the frame is set up. */
3647 emit_insn (gen_blockage ());
3649 /* Load the PIC register if needed. */
3650 if (flag_pic
&& crtl
->uses_pic_offset_table
)
3651 load_pic_register (false);
3655 /* Implement the epilogue and sibcall_epilogue patterns. SIBCALL_P is
3656 true for a sibcall_epilogue pattern, and false for an epilogue
3659 tilepro_expand_epilogue (bool sibcall_p
)
3661 /* We round-robin through four scratch registers to hold temporary
3662 addresses for saving registers, to make instruction scheduling
3664 rtx reg_save_addr
[ROUND_ROBIN_SIZE
] = {
3665 NULL_RTX
, NULL_RTX
, NULL_RTX
, NULL_RTX
3667 rtx last_insn
, insn
;
3668 unsigned int which_scratch
;
3669 int offset
, start_offset
, regno
;
3670 rtx cfa_restores
= NULL_RTX
;
3672 /* A register that holds a copy of the incoming fp. */
3673 int fp_copy_regno
= -1;
3675 /* Next scratch register number to hand out (postdecrementing). */
3676 int next_scratch_regno
= 29;
3678 int total_size
= compute_total_frame_size ();
3680 last_insn
= get_last_insn ();
3682 /* Load lr first since we are going to need it first. */
3684 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM
))
3686 insn
= frame_emit_load (TILEPRO_LINK_REGNUM
,
3687 compute_frame_addr (0, &next_scratch_regno
),
3691 if (total_size
== 0)
3695 RTX_FRAME_RELATED_P (insn
) = 1;
3696 REG_NOTES (insn
) = cfa_restores
;
3701 /* Compute where to start restoring registers. */
3702 start_offset
= -crtl
->args
.pretend_args_size
- UNITS_PER_WORD
;
3703 offset
= start_offset
;
3705 if (frame_pointer_needed
)
3706 fp_copy_regno
= next_scratch_regno
--;
3708 /* Restore all callee-saved registers. */
3710 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
>= 0; regno
--)
3711 if (need_to_save_reg (regno
))
3713 rtx r
= reg_save_addr
[which_scratch
];
3716 r
= compute_frame_addr (offset
, &next_scratch_regno
);
3717 reg_save_addr
[which_scratch
] = r
;
3721 /* Advance to the next stack slot to store this
3723 int stride
= ROUND_ROBIN_SIZE
* -UNITS_PER_WORD
;
3724 rtx p
= gen_rtx_PLUS (Pmode
, r
, GEN_INT (stride
));
3725 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3728 if (fp_copy_regno
>= 0 && regno
== HARD_FRAME_POINTER_REGNUM
)
3729 frame_emit_load (fp_copy_regno
, r
, NULL
);
3731 frame_emit_load (regno
, r
, &cfa_restores
);
3733 offset
-= UNITS_PER_WORD
;
3734 which_scratch
= (which_scratch
+ 1) % ROUND_ROBIN_SIZE
;
3737 if (!tilepro_current_function_is_leaf ())
3739 alloc_reg_note (REG_CFA_RESTORE
, stack_pointer_rtx
, cfa_restores
);
3741 emit_insn (gen_blockage ());
3743 if (frame_pointer_needed
)
3745 /* Restore the old stack pointer by copying from the frame
3747 insn
= emit_insn (gen_sp_restore (stack_pointer_rtx
,
3748 hard_frame_pointer_rtx
));
3749 RTX_FRAME_RELATED_P (insn
) = 1;
3750 REG_NOTES (insn
) = cfa_restores
;
3751 add_reg_note (insn
, REG_CFA_DEF_CFA
, stack_pointer_rtx
);
3755 insn
= emit_sp_adjust (total_size
, &next_scratch_regno
, true,
3759 if (crtl
->calls_eh_return
)
3760 emit_insn (gen_sp_adjust (stack_pointer_rtx
, stack_pointer_rtx
,
3761 EH_RETURN_STACKADJ_RTX
));
3763 /* Restore the old frame pointer. */
3764 if (frame_pointer_needed
)
3766 insn
= emit_move_insn (hard_frame_pointer_rtx
,
3767 gen_rtx_REG (Pmode
, fp_copy_regno
));
3768 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
3771 /* Mark the pic registers as live outside of the function. */
3774 emit_use (cfun
->machine
->text_label_rtx
);
3775 emit_use (cfun
->machine
->got_rtx
);
3781 /* Emit the actual 'return' instruction. */
3782 emit_jump_insn (gen__return ());
3786 emit_use (gen_rtx_REG (Pmode
, TILEPRO_LINK_REGNUM
));
3789 /* Mark all insns we just emitted as frame-related. */
3790 for (; last_insn
!= NULL_RTX
; last_insn
= next_insn (last_insn
))
3791 RTX_FRAME_RELATED_P (last_insn
) = 1;
3794 #undef ROUND_ROBIN_SIZE
3797 /* Implement INITIAL_ELIMINATION_OFFSET. */
3799 tilepro_initial_elimination_offset (int from
, int to
)
3801 int total_size
= compute_total_frame_size ();
3803 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3805 return (total_size
- crtl
->args
.pretend_args_size
3806 - tilepro_saved_regs_size ());
3808 else if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3810 return -(crtl
->args
.pretend_args_size
+ tilepro_saved_regs_size ());
3812 else if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3814 return STACK_POINTER_OFFSET
+ total_size
;
3816 else if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3818 return STACK_POINTER_OFFSET
;
3825 /* Return an RTX indicating where the return address to the
3826 calling function can be found. */
3828 tilepro_return_addr (int count
, rtx frame ATTRIBUTE_UNUSED
)
3833 return get_hard_reg_initial_val (Pmode
, TILEPRO_LINK_REGNUM
);
3837 /* Implement EH_RETURN_HANDLER_RTX. */
3839 tilepro_eh_return_handler_rtx (void)
3841 /* The MEM needs to be volatile to prevent it from being
3843 rtx tmp
= gen_frame_mem (Pmode
, hard_frame_pointer_rtx
);
3844 MEM_VOLATILE_P (tmp
) = true;
3852 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE. */
3854 tilepro_conditional_register_usage (void)
3856 global_regs
[TILEPRO_NETORDER_REGNUM
] = 1;
3857 /* TILEPRO_PIC_TEXT_LABEL_REGNUM is conditionally used. It is a
3858 member of fixed_regs, and therefore must be member of
3859 call_used_regs, but it is not a member of call_really_used_regs[]
3860 because it is not clobbered by a call. */
3861 if (TILEPRO_PIC_TEXT_LABEL_REGNUM
!= INVALID_REGNUM
)
3863 fixed_regs
[TILEPRO_PIC_TEXT_LABEL_REGNUM
] = 1;
3864 call_used_regs
[TILEPRO_PIC_TEXT_LABEL_REGNUM
] = 1;
3866 if (PIC_OFFSET_TABLE_REGNUM
!= INVALID_REGNUM
)
3868 fixed_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
3869 call_used_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
3874 /* Implement TARGET_FRAME_POINTER_REQUIRED. */
3876 tilepro_frame_pointer_required (void)
3878 return crtl
->calls_eh_return
|| cfun
->calls_alloca
;
3883 /* Scheduling and reorg */
3885 /* Return the length of INSN. LENGTH is the initial length computed
3886 by attributes in the machine-description file. This is where we
3887 account for bundles. */
3889 tilepro_adjust_insn_length (rtx insn
, int length
)
3891 enum machine_mode mode
= GET_MODE (insn
);
3893 /* A non-termininating instruction in a bundle has length 0. */
3897 /* By default, there is not length adjustment. */
3902 /* Implement TARGET_SCHED_ISSUE_RATE. */
3904 tilepro_issue_rate (void)
3910 /* Return the rtx for the jump target. */
3912 get_jump_target (rtx branch
)
3914 if (CALL_P (branch
))
3917 call
= PATTERN (branch
);
3919 if (GET_CODE (call
) == PARALLEL
)
3920 call
= XVECEXP (call
, 0, 0);
3922 if (GET_CODE (call
) == SET
)
3923 call
= SET_SRC (call
);
3925 if (GET_CODE (call
) == CALL
)
3926 return XEXP (XEXP (call
, 0), 0);
3931 /* Implement TARGET_SCHED_ADJUST_COST. */
3933 tilepro_sched_adjust_cost (rtx insn
, rtx link
, rtx dep_insn
, int cost
)
3935 /* If we have a true dependence, INSN is a call, and DEP_INSN
3936 defines a register that is needed by the call (argument or stack
3937 pointer), set its latency to 0 so that it can be bundled with
3938 the call. Explicitly check for and exclude the case when
3939 DEP_INSN defines the target of the jump. */
3940 if (CALL_P (insn
) && REG_NOTE_KIND (link
) == REG_DEP_TRUE
)
3942 rtx target
= get_jump_target (insn
);
3943 if (!REG_P (target
) || !set_of (target
, dep_insn
))
3951 /* Skip over irrelevant NOTEs and such and look for the next insn we
3952 would consider bundling. */
3954 next_insn_to_bundle (rtx r
, rtx end
)
3956 for (; r
!= end
; r
= NEXT_INSN (r
))
3958 if (NONDEBUG_INSN_P (r
)
3959 && GET_CODE (PATTERN (r
)) != USE
3960 && GET_CODE (PATTERN (r
)) != CLOBBER
)
3968 /* Go through all insns, and use the information generated during
3969 scheduling to generate SEQUENCEs to represent bundles of
3970 instructions issued simultaneously. */
3972 tilepro_gen_bundles (void)
3978 rtx end
= NEXT_INSN (BB_END (bb
));
3980 for (insn
= next_insn_to_bundle (BB_HEAD (bb
), end
); insn
; insn
= next
)
3982 next
= next_insn_to_bundle (NEXT_INSN (insn
), end
);
3984 /* Never wrap {} around inline asm. */
3985 if (GET_CODE (PATTERN (insn
)) != ASM_INPUT
)
3987 if (next
== NULL_RTX
|| GET_MODE (next
) == TImode
3988 /* NOTE: The scheduler incorrectly believes a call
3989 insn can execute in the same cycle as the insn
3990 after the call. This is of course impossible.
3991 Really we need to fix the scheduler somehow, so
3992 the code after the call gets scheduled
3996 /* Mark current insn as the end of a bundle. */
3997 PUT_MODE (insn
, QImode
);
4001 /* Mark it as part of a bundle. */
4002 PUT_MODE (insn
, SImode
);
4010 /* Helper function for tilepro_fixup_pcrel_references. */
4012 replace_pc_relative_symbol_ref (rtx insn
, rtx opnds
[4], bool first_insn_p
)
4022 emit_insn (gen_add_got16 (opnds
[0], tilepro_got_rtx (),
4024 emit_insn (gen_insn_lw (opnds
[0], opnds
[0]));
4031 emit_insn (gen_addhi_got32 (opnds
[0], tilepro_got_rtx (),
4036 emit_insn (gen_addlo_got32 (opnds
[0], opnds
[1], opnds
[2]));
4037 emit_insn (gen_insn_lw (opnds
[0], opnds
[0]));
4041 new_insns
= get_insns ();
4045 emit_insn_before (new_insns
, insn
);
4051 /* Returns whether INSN is a pc-relative addli insn. */
4053 match_addli_pcrel (rtx insn
)
4055 rtx pattern
= PATTERN (insn
);
4058 if (GET_CODE (pattern
) != SET
)
4061 if (GET_CODE (SET_SRC (pattern
)) != LO_SUM
)
4064 if (GET_CODE (XEXP (SET_SRC (pattern
), 1)) != CONST
)
4067 unspec
= XEXP (XEXP (SET_SRC (pattern
), 1), 0);
4069 return (GET_CODE (unspec
) == UNSPEC
4070 && XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4074 /* Helper function for tilepro_fixup_pcrel_references. */
4076 replace_addli_pcrel (rtx insn
)
4078 rtx pattern
= PATTERN (insn
);
4084 gcc_assert (GET_CODE (pattern
) == SET
);
4085 opnds
[0] = SET_DEST (pattern
);
4087 set_src
= SET_SRC (pattern
);
4088 gcc_assert (GET_CODE (set_src
) == LO_SUM
);
4089 gcc_assert (GET_CODE (XEXP (set_src
, 1)) == CONST
);
4090 opnds
[1] = XEXP (set_src
, 0);
4092 unspec
= XEXP (XEXP (set_src
, 1), 0);
4093 gcc_assert (GET_CODE (unspec
) == UNSPEC
);
4094 gcc_assert (XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4095 opnds
[2] = XVECEXP (unspec
, 0, 0);
4096 opnds
[3] = XVECEXP (unspec
, 0, 1);
4098 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */
4099 if (GET_CODE (opnds
[2]) != SYMBOL_REF
)
4102 first_insn_p
= (opnds
[1] == tilepro_text_label_rtx ());
4104 replace_pc_relative_symbol_ref (insn
, opnds
, first_insn_p
);
4108 /* Returns whether INSN is a pc-relative auli insn. */
4110 match_auli_pcrel (rtx insn
)
4112 rtx pattern
= PATTERN (insn
);
4116 if (GET_CODE (pattern
) != SET
)
4119 if (GET_CODE (SET_SRC (pattern
)) != PLUS
)
4122 high
= XEXP (SET_SRC (pattern
), 1);
4124 if (GET_CODE (high
) != HIGH
4125 || GET_CODE (XEXP (high
, 0)) != CONST
)
4128 unspec
= XEXP (XEXP (high
, 0), 0);
4130 return (GET_CODE (unspec
) == UNSPEC
4131 && XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4135 /* Helper function for tilepro_fixup_pcrel_references. */
4137 replace_auli_pcrel (rtx insn
)
4139 rtx pattern
= PATTERN (insn
);
4146 gcc_assert (GET_CODE (pattern
) == SET
);
4147 opnds
[0] = SET_DEST (pattern
);
4149 set_src
= SET_SRC (pattern
);
4150 gcc_assert (GET_CODE (set_src
) == PLUS
);
4151 opnds
[1] = XEXP (set_src
, 0);
4153 high
= XEXP (set_src
, 1);
4154 gcc_assert (GET_CODE (high
) == HIGH
);
4155 gcc_assert (GET_CODE (XEXP (high
, 0)) == CONST
);
4157 unspec
= XEXP (XEXP (high
, 0), 0);
4158 gcc_assert (GET_CODE (unspec
) == UNSPEC
);
4159 gcc_assert (XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4160 opnds
[2] = XVECEXP (unspec
, 0, 0);
4161 opnds
[3] = XVECEXP (unspec
, 0, 1);
4163 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */
4164 if (GET_CODE (opnds
[2]) != SYMBOL_REF
)
4167 first_insn_p
= (opnds
[1] == tilepro_text_label_rtx ());
4169 replace_pc_relative_symbol_ref (insn
, opnds
, first_insn_p
);
4173 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid
4174 going through the GOT when the symbol is local to the compilation
4175 unit. But such a symbol requires that the common text_label that
4176 we generate at the beginning of the function be in the same section
4177 as the reference to the SYMBOL_REF. This may not be true if we
4178 generate hot/cold sections. This function looks for such cases and
4179 replaces such references with the longer sequence going through the
4182 We expect one of the following two instruction sequences:
4183 addli tmp1, txt_label_reg, lo16(sym - txt_label)
4184 auli tmp2, tmp1, ha16(sym - txt_label)
4186 auli tmp1, txt_label_reg, ha16(sym - txt_label)
4187 addli tmp2, tmp1, lo16(sym - txt_label)
4189 If we're compiling -fpic, we replace the first instruction with
4190 nothing, and the second instruction with:
4192 addli tmp2, got_rtx, got(sym)
4195 If we're compiling -fPIC, we replace the first instruction with:
4197 auli tmp1, got_rtx, got_ha16(sym)
4199 and the second instruction with:
4201 addli tmp2, tmp1, got_lo16(sym)
4204 Note that we're careful to disturb the instruction sequence as
4205 little as possible, since it's very late in the compilation
4209 tilepro_fixup_pcrel_references (void)
4211 rtx insn
, next_insn
;
4212 bool same_section_as_entry
= true;
4214 for (insn
= get_insns (); insn
; insn
= next_insn
)
4216 next_insn
= NEXT_INSN (insn
);
4218 if (NOTE_P (insn
) && NOTE_KIND (insn
) == NOTE_INSN_SWITCH_TEXT_SECTIONS
)
4220 same_section_as_entry
= !same_section_as_entry
;
4224 if (same_section_as_entry
)
4228 && GET_CODE (PATTERN (insn
)) != USE
4229 && GET_CODE (PATTERN (insn
)) != CLOBBER
))
4232 if (match_addli_pcrel (insn
))
4233 replace_addli_pcrel (insn
);
4234 else if (match_auli_pcrel (insn
))
4235 replace_auli_pcrel (insn
);
4240 /* Ensure that no var tracking notes are emitted in the middle of a
4241 three-instruction bundle. */
4243 reorder_var_tracking_notes (void)
4249 rtx queue
= NULL_RTX
;
4250 bool in_bundle
= false;
4252 for (insn
= BB_HEAD (bb
); insn
!= BB_END (bb
); insn
= next
)
4254 next
= NEXT_INSN (insn
);
4258 /* Emit queued up notes at the last instruction of a bundle. */
4259 if (GET_MODE (insn
) == QImode
)
4263 rtx next_queue
= PREV_INSN (queue
);
4264 PREV_INSN (NEXT_INSN (insn
)) = queue
;
4265 NEXT_INSN (queue
) = NEXT_INSN (insn
);
4266 NEXT_INSN (insn
) = queue
;
4267 PREV_INSN (queue
) = insn
;
4272 else if (GET_MODE (insn
) == SImode
)
4275 else if (NOTE_P (insn
) && NOTE_KIND (insn
) == NOTE_INSN_VAR_LOCATION
)
4279 rtx prev
= PREV_INSN (insn
);
4280 PREV_INSN (next
) = prev
;
4281 NEXT_INSN (prev
) = next
;
4283 PREV_INSN (insn
) = queue
;
4292 /* Perform machine dependent operations on the rtl chain INSNS. */
4294 tilepro_reorg (void)
4296 /* We are freeing block_for_insn in the toplev to keep compatibility
4297 with old MDEP_REORGS that are not CFG based. Recompute it
4299 compute_bb_for_insn ();
4301 if (flag_reorder_blocks_and_partition
)
4303 tilepro_fixup_pcrel_references ();
4306 if (flag_schedule_insns_after_reload
)
4310 timevar_push (TV_SCHED2
);
4312 timevar_pop (TV_SCHED2
);
4314 /* Examine the schedule to group into bundles. */
4315 tilepro_gen_bundles ();
4320 if (flag_var_tracking
)
4322 timevar_push (TV_VAR_TRACKING
);
4323 variable_tracking_main ();
4324 reorder_var_tracking_notes ();
4325 timevar_pop (TV_VAR_TRACKING
);
4328 df_finish_pass (false);
4335 /* Select a format to encode pointers in exception handling data.
4336 CODE is 0 for data, 1 for code labels, 2 for function pointers.
4337 GLOBAL is true if the symbol may be affected by dynamic
4340 tilepro_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED
, int global
)
4342 return (global
? DW_EH_PE_indirect
: 0) | DW_EH_PE_pcrel
| DW_EH_PE_sdata4
;
4346 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
4348 tilepro_asm_output_mi_thunk (FILE *file
, tree thunk_fndecl ATTRIBUTE_UNUSED
,
4349 HOST_WIDE_INT delta
, HOST_WIDE_INT vcall_offset
,
4352 rtx this_rtx
, insn
, funexp
;
4354 /* Pretend to be a post-reload pass while generating rtl. */
4355 reload_completed
= 1;
4357 /* Mark the end of the (empty) prologue. */
4358 emit_note (NOTE_INSN_PROLOGUE_END
);
4360 /* Find the "this" pointer. If the function returns a structure,
4361 the structure return pointer is in $1. */
4362 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
))
4363 this_rtx
= gen_rtx_REG (Pmode
, 1);
4365 this_rtx
= gen_rtx_REG (Pmode
, 0);
4367 /* Add DELTA to THIS_RTX. */
4368 emit_insn (gen_addsi3 (this_rtx
, this_rtx
, GEN_INT (delta
)));
4370 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
4375 tmp
= gen_rtx_REG (Pmode
, 29);
4376 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, this_rtx
));
4378 emit_insn (gen_addsi3 (tmp
, tmp
, GEN_INT (vcall_offset
)));
4380 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, tmp
));
4382 emit_insn (gen_addsi3 (this_rtx
, this_rtx
, tmp
));
4385 /* Generate a tail call to the target function. */
4386 if (!TREE_USED (function
))
4388 assemble_external (function
);
4389 TREE_USED (function
) = 1;
4391 funexp
= XEXP (DECL_RTL (function
), 0);
4392 funexp
= gen_rtx_MEM (FUNCTION_MODE
, funexp
);
4393 insn
= emit_call_insn (gen_sibcall (funexp
, const0_rtx
));
4394 SIBLING_CALL_P (insn
) = 1;
4396 /* Run just enough of rest_of_compilation to get the insns emitted.
4397 There's not really enough bulk here to make other passes such as
4398 instruction scheduling worth while. Note that use_thunk calls
4399 assemble_start_function and assemble_end_function.
4401 We don't currently bundle, but the instruciton sequence is all
4402 serial except for the tail call, so we're only wasting one cycle.
4404 insn
= get_insns ();
4405 shorten_branches (insn
);
4406 final_start_function (insn
, file
, 1);
4407 final (insn
, file
, 1);
4408 final_end_function ();
4410 /* Stop pretending to be a post-reload pass. */
4411 reload_completed
= 0;
4415 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */
4417 tilepro_asm_trampoline_template (FILE *file
)
4419 fprintf (file
, "\tlnk r10\n");
4420 fprintf (file
, "\taddi r10, r10, 32\n");
4421 fprintf (file
, "\tlwadd r11, r10, %d\n", GET_MODE_SIZE (ptr_mode
));
4422 fprintf (file
, "\tlw r10, r10\n");
4423 fprintf (file
, "\tjr r11\n");
4424 fprintf (file
, "\t.word 0 # <function address>\n");
4425 fprintf (file
, "\t.word 0 # <static chain value>\n");
4429 /* Implement TARGET_TRAMPOLINE_INIT. */
4431 tilepro_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
4435 rtx begin_addr
, end_addr
;
4436 int ptr_mode_size
= GET_MODE_SIZE (ptr_mode
);
4438 fnaddr
= copy_to_reg (XEXP (DECL_RTL (fndecl
), 0));
4439 chaddr
= copy_to_reg (static_chain
);
4441 emit_block_move (m_tramp
, assemble_trampoline_template (),
4442 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
4444 mem
= adjust_address (m_tramp
, ptr_mode
,
4445 TRAMPOLINE_SIZE
- 2 * ptr_mode_size
);
4446 emit_move_insn (mem
, fnaddr
);
4447 mem
= adjust_address (m_tramp
, ptr_mode
,
4448 TRAMPOLINE_SIZE
- ptr_mode_size
);
4449 emit_move_insn (mem
, chaddr
);
4451 /* Get pointers to the beginning and end of the code block. */
4452 begin_addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
4453 end_addr
= force_reg (Pmode
, plus_constant (Pmode
, XEXP (m_tramp
, 0),
4456 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__clear_cache"),
4457 LCT_NORMAL
, VOIDmode
, 2, begin_addr
, Pmode
,
4462 /* Implement TARGET_PRINT_OPERAND. */
4464 tilepro_print_operand (FILE *file
, rtx x
, int code
)
4469 /* Print the compare operator opcode for conditional moves. */
4470 switch (GET_CODE (x
))
4479 output_operand_lossage ("invalid %%c operand");
4484 /* Print the compare operator opcode for conditional moves. */
4485 switch (GET_CODE (x
))
4494 output_operand_lossage ("invalid %%C operand");
4500 /* Print the high 16 bits of a 32-bit constant. */
4502 if (CONST_INT_P (x
))
4504 else if (GET_CODE (x
) == CONST_DOUBLE
)
4505 i
= CONST_DOUBLE_LOW (x
);
4508 output_operand_lossage ("invalid %%h operand");
4511 i
= trunc_int_for_mode (i
>> 16, HImode
);
4512 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4519 const char *opstr
= NULL
;
4521 if (GET_CODE (x
) == CONST
4522 && GET_CODE (XEXP (x
, 0)) == UNSPEC
)
4524 addr
= XVECEXP (XEXP (x
, 0), 0, 0);
4525 switch (XINT (XEXP (x
, 0), 1))
4527 case UNSPEC_GOT32_SYM
:
4530 case UNSPEC_PCREL_SYM
:
4535 opstr
= "tls_gd_ha16";
4538 opstr
= "tls_ie_ha16";
4541 opstr
= "tls_le_ha16";
4544 output_operand_lossage ("invalid %%H operand");
4553 fputs (opstr
, file
);
4555 output_addr_const (file
, addr
);
4559 rtx addr2
= XVECEXP (XEXP (x
, 0), 0, 1);
4560 fputs (" - " , file
);
4561 output_addr_const (file
, addr2
);
4569 /* Print an auto-inc memory operand. */
4572 output_operand_lossage ("invalid %%I operand");
4576 output_memory_reference_mode
= GET_MODE (x
);
4577 output_memory_autoinc_first
= true;
4578 output_address (XEXP (x
, 0));
4579 output_memory_reference_mode
= VOIDmode
;
4583 /* Print an auto-inc memory operand. */
4586 output_operand_lossage ("invalid %%i operand");
4590 output_memory_reference_mode
= GET_MODE (x
);
4591 output_memory_autoinc_first
= false;
4592 output_address (XEXP (x
, 0));
4593 output_memory_reference_mode
= VOIDmode
;
4598 /* Print the low 8 bits of a constant. */
4600 if (CONST_INT_P (x
))
4602 else if (GET_CODE (x
) == CONST_DOUBLE
)
4603 i
= CONST_DOUBLE_LOW (x
);
4604 else if (GET_CODE (x
) == CONST_VECTOR
4605 && CONST_INT_P (CONST_VECTOR_ELT (x
, 0)))
4606 i
= INTVAL (CONST_VECTOR_ELT (x
, 0));
4609 output_operand_lossage ("invalid %%j operand");
4612 i
= trunc_int_for_mode (i
, QImode
);
4613 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4620 const char *opstr
= NULL
;
4622 if (GET_CODE (x
) == CONST
4623 && GET_CODE (XEXP (x
, 0)) == UNSPEC
)
4625 addr
= XVECEXP (XEXP (x
, 0), 0, 0);
4626 switch (XINT (XEXP (x
, 0), 1))
4628 case UNSPEC_GOT16_SYM
:
4631 case UNSPEC_GOT32_SYM
:
4634 case UNSPEC_PCREL_SYM
:
4639 opstr
= "tls_gd_lo16";
4642 opstr
= "tls_ie_lo16";
4645 opstr
= "tls_le_lo16";
4648 output_operand_lossage ("invalid %%L operand");
4657 fputs (opstr
, file
);
4659 output_addr_const (file
, addr
);
4663 rtx addr2
= XVECEXP (XEXP (x
, 0), 0, 1);
4664 fputs (" - " , file
);
4665 output_addr_const (file
, addr2
);
4673 if (GET_CODE (x
) == SYMBOL_REF
)
4675 if (flag_pic
&& !SYMBOL_REF_LOCAL_P (x
))
4676 fprintf (file
, "plt(");
4677 output_addr_const (file
, x
);
4678 if (flag_pic
&& !SYMBOL_REF_LOCAL_P (x
))
4679 fprintf (file
, ")");
4682 output_addr_const (file
, x
);
4687 /* Print a 32-bit constant plus one. */
4689 if (!CONST_INT_P (x
))
4691 output_operand_lossage ("invalid %%P operand");
4694 i
= trunc_int_for_mode (INTVAL (x
) + 1, SImode
);
4695 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4701 /* Print an mm-style bit range. */
4702 int first_bit
, last_bit
;
4704 if (!CONST_INT_P (x
)
4705 || !tilepro_bitfield_operand_p (INTVAL (x
), &first_bit
,
4708 output_operand_lossage ("invalid %%M operand");
4712 fprintf (file
, "%d, %d", first_bit
, last_bit
);
4718 const char *reg
= NULL
;
4720 /* Print a network register. */
4721 if (!CONST_INT_P (x
))
4723 output_operand_lossage ("invalid %%N operand");
4729 case TILEPRO_NETREG_IDN0
: reg
= "idn0"; break;
4730 case TILEPRO_NETREG_IDN1
: reg
= "idn1"; break;
4731 case TILEPRO_NETREG_SN
: reg
= "sn"; break;
4732 case TILEPRO_NETREG_UDN0
: reg
= "udn0"; break;
4733 case TILEPRO_NETREG_UDN1
: reg
= "udn1"; break;
4734 case TILEPRO_NETREG_UDN2
: reg
= "udn2"; break;
4735 case TILEPRO_NETREG_UDN3
: reg
= "udn3"; break;
4736 default: gcc_unreachable ();
4739 fprintf (file
, reg
);
4745 /* Log base 2 of a power of two. */
4749 if (!CONST_INT_P (x
))
4751 output_operand_lossage ("invalid %%t operand");
4754 n
= trunc_int_for_mode (INTVAL (x
), SImode
);
4758 output_operand_lossage ("invalid %%t operand '"
4759 HOST_WIDE_INT_PRINT_DEC
"'", n
);
4763 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4769 /* In this case we need a register. Use 'zero' if the
4770 operand is const0_rtx. */
4772 || (GET_MODE (x
) != VOIDmode
&& x
== CONST0_RTX (GET_MODE (x
))))
4774 fputs ("zero", file
);
4777 else if (!REG_P (x
))
4779 output_operand_lossage ("invalid %%r operand");
4787 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
4792 output_memory_reference_mode
= VOIDmode
;
4793 output_address (XEXP (x
, 0));
4798 output_addr_const (file
, x
);
4805 output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
4810 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
4812 tilepro_print_operand_address (FILE *file
, rtx addr
)
4814 if (GET_CODE (addr
) == POST_DEC
4815 || GET_CODE (addr
) == POST_INC
)
4817 int offset
= GET_MODE_SIZE (output_memory_reference_mode
);
4819 gcc_assert (output_memory_reference_mode
!= VOIDmode
);
4821 if (output_memory_autoinc_first
)
4822 fprintf (file
, "%s", reg_names
[REGNO (XEXP (addr
, 0))]);
4824 fprintf (file
, "%d",
4825 GET_CODE (addr
) == POST_DEC
? -offset
: offset
);
4827 else if (GET_CODE (addr
) == POST_MODIFY
)
4829 gcc_assert (output_memory_reference_mode
!= VOIDmode
);
4831 gcc_assert (GET_CODE (XEXP (addr
, 1)) == PLUS
);
4833 if (output_memory_autoinc_first
)
4834 fprintf (file
, "%s", reg_names
[REGNO (XEXP (addr
, 0))]);
4836 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4837 INTVAL (XEXP (XEXP (addr
, 1), 1)));
4840 tilepro_print_operand (file
, addr
, 'r');
4844 /* Machine mode of current insn, for determining curly brace
4846 static enum machine_mode insn_mode
;
4849 /* Implement FINAL_PRESCAN_INSN. This is used to emit bundles. */
4851 tilepro_final_prescan_insn (rtx insn
)
4853 /* Record this for tilepro_asm_output_opcode to examine. */
4854 insn_mode
= GET_MODE (insn
);
4858 /* While emitting asm, are we currently inside '{' for a bundle? */
4859 static bool tilepro_in_bundle
= false;
4861 /* Implement ASM_OUTPUT_OPCODE. Prepend/append curly braces as
4862 appropriate given the bundling information recorded by
4863 tilepro_gen_bundles. */
4865 tilepro_asm_output_opcode (FILE *stream
, const char *code
)
4867 bool pseudo
= !strcmp (code
, "pseudo");
4869 if (!tilepro_in_bundle
&& insn_mode
== SImode
)
4871 /* Start a new bundle. */
4872 fprintf (stream
, "{\n\t");
4873 tilepro_in_bundle
= true;
4876 if (tilepro_in_bundle
&& insn_mode
== QImode
)
4878 /* Close an existing bundle. */
4879 static char buf
[100];
4881 gcc_assert (strlen (code
) + 3 + 1 < sizeof (buf
));
4883 strcpy (buf
, pseudo
? "" : code
);
4884 strcat (buf
, "\n\t}");
4885 tilepro_in_bundle
= false;
4891 return pseudo
? "" : code
;
4896 /* Output assembler code to FILE to increment profiler label # LABELNO
4897 for profiling a function entry. */
4899 tilepro_function_profiler (FILE *file
, int labelno ATTRIBUTE_UNUSED
)
4901 if (tilepro_in_bundle
)
4903 fprintf (file
, "\t}\n");
4912 "\t}\n", MCOUNT_NAME
);
4920 "\t}\n", MCOUNT_NAME
);
4923 tilepro_in_bundle
= false;
4927 /* Implement TARGET_ASM_FILE_END. */
4929 tilepro_file_end (void)
4931 if (NEED_INDICATE_EXEC_STACK
)
4932 file_end_indicate_exec_stack ();
4936 #undef TARGET_HAVE_TLS
4937 #define TARGET_HAVE_TLS HAVE_AS_TLS
4939 #undef TARGET_OPTION_OVERRIDE
4940 #define TARGET_OPTION_OVERRIDE tilepro_option_override
4942 #undef TARGET_SCALAR_MODE_SUPPORTED_P
4943 #define TARGET_SCALAR_MODE_SUPPORTED_P tilepro_scalar_mode_supported_p
4945 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4946 #define TARGET_VECTOR_MODE_SUPPORTED_P tile_vector_mode_supported_p
4948 #undef TARGET_CANNOT_FORCE_CONST_MEM
4949 #define TARGET_CANNOT_FORCE_CONST_MEM tilepro_cannot_force_const_mem
4951 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4952 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilepro_function_ok_for_sibcall
4954 #undef TARGET_PASS_BY_REFERENCE
4955 #define TARGET_PASS_BY_REFERENCE tilepro_pass_by_reference
4957 #undef TARGET_RETURN_IN_MEMORY
4958 #define TARGET_RETURN_IN_MEMORY tilepro_return_in_memory
4960 #undef TARGET_FUNCTION_ARG_BOUNDARY
4961 #define TARGET_FUNCTION_ARG_BOUNDARY tilepro_function_arg_boundary
4963 #undef TARGET_FUNCTION_ARG
4964 #define TARGET_FUNCTION_ARG tilepro_function_arg
4966 #undef TARGET_FUNCTION_ARG_ADVANCE
4967 #define TARGET_FUNCTION_ARG_ADVANCE tilepro_function_arg_advance
4969 #undef TARGET_FUNCTION_VALUE
4970 #define TARGET_FUNCTION_VALUE tilepro_function_value
4972 #undef TARGET_LIBCALL_VALUE
4973 #define TARGET_LIBCALL_VALUE tilepro_libcall_value
4975 #undef TARGET_FUNCTION_VALUE_REGNO_P
4976 #define TARGET_FUNCTION_VALUE_REGNO_P tilepro_function_value_regno_p
4978 #undef TARGET_PROMOTE_FUNCTION_MODE
4979 #define TARGET_PROMOTE_FUNCTION_MODE \
4980 default_promote_function_mode_always_promote
4982 #undef TARGET_PROMOTE_PROTOTYPES
4983 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
4985 #undef TARGET_BUILD_BUILTIN_VA_LIST
4986 #define TARGET_BUILD_BUILTIN_VA_LIST tilepro_build_builtin_va_list
4988 #undef TARGET_EXPAND_BUILTIN_VA_START
4989 #define TARGET_EXPAND_BUILTIN_VA_START tilepro_va_start
4991 #undef TARGET_SETUP_INCOMING_VARARGS
4992 #define TARGET_SETUP_INCOMING_VARARGS tilepro_setup_incoming_varargs
4994 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
4995 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilepro_gimplify_va_arg_expr
4997 #undef TARGET_RTX_COSTS
4998 #define TARGET_RTX_COSTS tilepro_rtx_costs
5000 /* Limit to what we can reach in one addli. */
5001 #undef TARGET_MIN_ANCHOR_OFFSET
5002 #define TARGET_MIN_ANCHOR_OFFSET -32768
5003 #undef TARGET_MAX_ANCHOR_OFFSET
5004 #define TARGET_MAX_ANCHOR_OFFSET 32767
5006 #undef TARGET_LEGITIMATE_CONSTANT_P
5007 #define TARGET_LEGITIMATE_CONSTANT_P tilepro_legitimate_constant_p
5009 #undef TARGET_LEGITIMATE_ADDRESS_P
5010 #define TARGET_LEGITIMATE_ADDRESS_P tilepro_legitimate_address_p
5012 #undef TARGET_LEGITIMIZE_ADDRESS
5013 #define TARGET_LEGITIMIZE_ADDRESS tilepro_legitimize_address
5015 #undef TARGET_DELEGITIMIZE_ADDRESS
5016 #define TARGET_DELEGITIMIZE_ADDRESS tilepro_delegitimize_address
5018 #undef TARGET_INIT_BUILTINS
5019 #define TARGET_INIT_BUILTINS tilepro_init_builtins
5021 #undef TARGET_BUILTIN_DECL
5022 #define TARGET_BUILTIN_DECL tilepro_builtin_decl
5024 #undef TARGET_EXPAND_BUILTIN
5025 #define TARGET_EXPAND_BUILTIN tilepro_expand_builtin
5027 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5028 #define TARGET_CONDITIONAL_REGISTER_USAGE tilepro_conditional_register_usage
5030 #undef TARGET_FRAME_POINTER_REQUIRED
5031 #define TARGET_FRAME_POINTER_REQUIRED tilepro_frame_pointer_required
5033 #undef TARGET_DELAY_SCHED2
5034 #define TARGET_DELAY_SCHED2 true
5036 #undef TARGET_DELAY_VARTRACK
5037 #define TARGET_DELAY_VARTRACK true
5039 #undef TARGET_SCHED_ISSUE_RATE
5040 #define TARGET_SCHED_ISSUE_RATE tilepro_issue_rate
5042 #undef TARGET_SCHED_ADJUST_COST
5043 #define TARGET_SCHED_ADJUST_COST tilepro_sched_adjust_cost
5045 #undef TARGET_MACHINE_DEPENDENT_REORG
5046 #define TARGET_MACHINE_DEPENDENT_REORG tilepro_reorg
5048 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5049 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5050 hook_bool_const_tree_hwi_hwi_const_tree_true
5052 #undef TARGET_ASM_OUTPUT_MI_THUNK
5053 #define TARGET_ASM_OUTPUT_MI_THUNK tilepro_asm_output_mi_thunk
5055 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5056 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilepro_asm_trampoline_template
5058 #undef TARGET_TRAMPOLINE_INIT
5059 #define TARGET_TRAMPOLINE_INIT tilepro_trampoline_init
5061 #undef TARGET_PRINT_OPERAND
5062 #define TARGET_PRINT_OPERAND tilepro_print_operand
5064 #undef TARGET_PRINT_OPERAND_ADDRESS
5065 #define TARGET_PRINT_OPERAND_ADDRESS tilepro_print_operand_address
5067 #undef TARGET_ASM_FILE_END
5068 #define TARGET_ASM_FILE_END tilepro_file_end
5071 struct gcc_target targetm
= TARGET_INITIALIZER
;
5073 #include "gt-tilepro.h"