1 /* Subroutines used for code generation on the Tilera TILEPro.
2 Copyright (C) 2011-2015 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"
35 #include "hard-reg-set.h"
39 #include "statistics.h"
40 #include "double-int.h"
42 #include "fixed-value.h"
56 #include "langhooks.h"
57 #include "insn-codes.h"
59 #include "dominance.h"
65 #include "cfgcleanup.h"
67 #include "basic-block.h"
68 #include "sched-int.h"
69 #include "sel-sched.h"
71 #include "tm-constrs.h"
73 #include "target-def.h"
76 #include "fold-const.h"
77 #include "hash-table.h"
79 #include "tree-ssa-alias.h"
80 #include "internal-fn.h"
81 #include "gimple-fold.h"
83 #include "gimple-expr.h"
86 #include "stringpool.h"
87 #include "stor-layout.h"
90 #include "tilepro-builtins.h"
91 #include "tilepro-multiply.h"
92 #include "diagnostic.h"
95 /* SYMBOL_REF for GOT */
96 static GTY(()) rtx g_got_symbol
= NULL
;
98 /* In case of a POST_INC or POST_DEC memory reference, we must report
99 the mode of the memory reference from TARGET_PRINT_OPERAND to
100 TARGET_PRINT_OPERAND_ADDRESS. */
101 static machine_mode output_memory_reference_mode
;
103 /* Report whether we're printing out the first address fragment of a
104 POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
105 TARGET_PRINT_OPERAND_ADDRESS. */
106 static bool output_memory_autoinc_first
;
110 /* Option handling */
112 /* Implement TARGET_OPTION_OVERRIDE. */
114 tilepro_option_override (void)
116 /* When modulo scheduling is enabled, we still rely on regular
117 scheduler for bundling. */
118 if (flag_modulo_sched
)
119 flag_resched_modulo_sched
= 1;
124 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
126 tilepro_scalar_mode_supported_p (machine_mode mode
)
146 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */
148 tile_vector_mode_supported_p (machine_mode mode
)
150 return mode
== V4QImode
|| mode
== V2HImode
;
154 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
156 tilepro_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED
,
157 rtx x ATTRIBUTE_UNUSED
)
163 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
165 tilepro_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
171 /* Implement TARGET_PASS_BY_REFERENCE. Variable sized types are
172 passed by reference. */
174 tilepro_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED
,
175 machine_mode mode ATTRIBUTE_UNUSED
,
176 const_tree type
, bool named ATTRIBUTE_UNUSED
)
178 return (type
&& TYPE_SIZE (type
)
179 && TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
);
183 /* Implement TARGET_RETURN_IN_MEMORY. */
185 tilepro_return_in_memory (const_tree type
, const_tree fndecl ATTRIBUTE_UNUSED
)
187 return !IN_RANGE (int_size_in_bytes (type
),
188 0, TILEPRO_NUM_RETURN_REGS
* UNITS_PER_WORD
);
192 /* Implement TARGET_FUNCTION_ARG_BOUNDARY. */
194 tilepro_function_arg_boundary (machine_mode mode
, const_tree type
)
196 unsigned int alignment
;
198 alignment
= type
? TYPE_ALIGN (type
) : GET_MODE_ALIGNMENT (mode
);
199 if (alignment
< PARM_BOUNDARY
)
200 alignment
= PARM_BOUNDARY
;
201 if (alignment
> STACK_BOUNDARY
)
202 alignment
= STACK_BOUNDARY
;
207 /* Implement TARGET_FUNCTION_ARG. */
209 tilepro_function_arg (cumulative_args_t cum_v
,
211 const_tree type
, bool named ATTRIBUTE_UNUSED
)
213 CUMULATIVE_ARGS cum
= *get_cumulative_args (cum_v
);
214 int byte_size
= ((mode
== BLKmode
)
215 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
216 bool doubleword_aligned_p
;
218 if (cum
>= TILEPRO_NUM_ARG_REGS
)
221 /* See whether the argument has doubleword alignment. */
222 doubleword_aligned_p
=
223 tilepro_function_arg_boundary (mode
, type
) > BITS_PER_WORD
;
225 if (doubleword_aligned_p
)
228 /* The ABI does not allow parameters to be passed partially in reg
229 and partially in stack. */
230 if ((cum
+ (byte_size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
)
231 > TILEPRO_NUM_ARG_REGS
)
234 return gen_rtx_REG (mode
, cum
);
238 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
240 tilepro_function_arg_advance (cumulative_args_t cum_v
,
242 const_tree type
, bool named ATTRIBUTE_UNUSED
)
244 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
246 int byte_size
= ((mode
== BLKmode
)
247 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
248 int word_size
= (byte_size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
249 bool doubleword_aligned_p
;
251 /* See whether the argument has doubleword alignment. */
252 doubleword_aligned_p
=
253 tilepro_function_arg_boundary (mode
, type
) > BITS_PER_WORD
;
255 if (doubleword_aligned_p
)
258 /* If the current argument does not fit in the pretend_args space,
260 if (*cum
< TILEPRO_NUM_ARG_REGS
261 && *cum
+ word_size
> TILEPRO_NUM_ARG_REGS
)
262 *cum
= TILEPRO_NUM_ARG_REGS
;
268 /* Implement TARGET_FUNCTION_VALUE. */
270 tilepro_function_value (const_tree valtype
, const_tree fn_decl_or_type
,
271 bool outgoing ATTRIBUTE_UNUSED
)
276 mode
= TYPE_MODE (valtype
);
277 unsigned_p
= TYPE_UNSIGNED (valtype
);
279 mode
= promote_function_mode (valtype
, mode
, &unsigned_p
,
282 return gen_rtx_REG (mode
, 0);
286 /* Implement TARGET_LIBCALL_VALUE. */
288 tilepro_libcall_value (machine_mode mode
,
289 const_rtx fun ATTRIBUTE_UNUSED
)
291 return gen_rtx_REG (mode
, 0);
295 /* Implement FUNCTION_VALUE_REGNO_P. */
297 tilepro_function_value_regno_p (const unsigned int regno
)
299 return regno
< TILEPRO_NUM_RETURN_REGS
;
303 /* Implement TARGET_BUILD_BUILTIN_VA_LIST. */
305 tilepro_build_builtin_va_list (void)
307 tree f_args
, f_skip
, record
, type_decl
;
310 record
= lang_hooks
.types
.make_type (RECORD_TYPE
);
312 type_decl
= build_decl (BUILTINS_LOCATION
, TYPE_DECL
,
313 get_identifier ("__va_list_tag"), record
);
315 f_args
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
316 get_identifier ("__args"), ptr_type_node
);
317 f_skip
= build_decl (BUILTINS_LOCATION
, FIELD_DECL
,
318 get_identifier ("__skip"), ptr_type_node
);
320 DECL_FIELD_CONTEXT (f_args
) = record
;
322 DECL_FIELD_CONTEXT (f_skip
) = record
;
324 TREE_CHAIN (record
) = type_decl
;
325 TYPE_NAME (record
) = type_decl
;
326 TYPE_FIELDS (record
) = f_args
;
327 TREE_CHAIN (f_args
) = f_skip
;
329 /* We know this is being padded and we want it too. It is an
330 internal type so hide the warnings from the user. */
334 layout_type (record
);
338 /* The correct type is an array type of one element. */
343 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */
345 tilepro_va_start (tree valist
, rtx nextarg ATTRIBUTE_UNUSED
)
350 f_args
= TYPE_FIELDS (TREE_TYPE (valist
));
351 f_skip
= TREE_CHAIN (f_args
);
354 build3 (COMPONENT_REF
, TREE_TYPE (f_args
), valist
, f_args
, NULL_TREE
);
356 build3 (COMPONENT_REF
, TREE_TYPE (f_skip
), valist
, f_skip
, NULL_TREE
);
358 /* Find the __args area. */
359 t
= make_tree (TREE_TYPE (args
), virtual_incoming_args_rtx
);
360 t
= fold_build_pointer_plus_hwi (t
,
362 (crtl
->args
.info
- TILEPRO_NUM_ARG_REGS
));
364 if (crtl
->args
.pretend_args_size
> 0)
365 t
= fold_build_pointer_plus_hwi (t
, -STACK_POINTER_OFFSET
);
367 t
= build2 (MODIFY_EXPR
, TREE_TYPE (args
), args
, t
);
368 TREE_SIDE_EFFECTS (t
) = 1;
369 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
371 /* Find the __skip area. */
372 t
= make_tree (TREE_TYPE (skip
), virtual_incoming_args_rtx
);
373 t
= fold_build_pointer_plus_hwi (t
, -STACK_POINTER_OFFSET
);
374 t
= build2 (MODIFY_EXPR
, TREE_TYPE (skip
), skip
, t
);
375 TREE_SIDE_EFFECTS (t
) = 1;
376 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
380 /* Implement TARGET_SETUP_INCOMING_VARARGS. */
382 tilepro_setup_incoming_varargs (cumulative_args_t cum
,
384 tree type
, int *pretend_args
, int no_rtl
)
386 CUMULATIVE_ARGS local_cum
= *get_cumulative_args (cum
);
389 /* The caller has advanced CUM up to, but not beyond, the last named
390 argument. Advance a local copy of CUM past the last "real" named
391 argument, to find out how many registers are left over. */
392 targetm
.calls
.function_arg_advance (pack_cumulative_args (&local_cum
),
394 first_reg
= local_cum
;
396 if (local_cum
< TILEPRO_NUM_ARG_REGS
)
398 *pretend_args
= UNITS_PER_WORD
* (TILEPRO_NUM_ARG_REGS
- first_reg
);
402 alias_set_type set
= get_varargs_alias_set ();
404 gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, \
405 virtual_incoming_args_rtx
,
406 -STACK_POINTER_OFFSET
-
408 (TILEPRO_NUM_ARG_REGS
-
410 MEM_NOTRAP_P (tmp
) = 1;
411 set_mem_alias_set (tmp
, set
);
412 move_block_from_reg (first_reg
, tmp
,
413 TILEPRO_NUM_ARG_REGS
- first_reg
);
421 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. Gimplify va_arg by updating
422 the va_list structure VALIST as required to retrieve an argument of
423 type TYPE, and returning that argument.
425 ret = va_arg(VALIST, TYPE);
427 generates code equivalent to:
429 paddedsize = (sizeof(TYPE) + 3) & -4;
430 if ((VALIST.__args + paddedsize > VALIST.__skip)
431 & (VALIST.__args <= VALIST.__skip))
432 addr = VALIST.__skip + STACK_POINTER_OFFSET;
434 addr = VALIST.__args;
435 VALIST.__args = addr + paddedsize;
436 ret = *(TYPE *)addr; */
438 tilepro_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
* pre_p
,
439 gimple_seq
* post_p ATTRIBUTE_UNUSED
)
443 HOST_WIDE_INT size
, rsize
;
445 bool pass_by_reference_p
;
447 f_args
= TYPE_FIELDS (va_list_type_node
);
448 f_skip
= TREE_CHAIN (f_args
);
451 build3 (COMPONENT_REF
, TREE_TYPE (f_args
), valist
, f_args
, NULL_TREE
);
453 build3 (COMPONENT_REF
, TREE_TYPE (f_skip
), valist
, f_skip
, NULL_TREE
);
455 addr
= create_tmp_var (ptr_type_node
, "va_arg");
457 /* if an object is dynamically sized, a pointer to it is passed
458 instead of the object itself. */
459 pass_by_reference_p
= pass_by_reference (NULL
, TYPE_MODE (type
), type
,
462 if (pass_by_reference_p
)
463 type
= build_pointer_type (type
);
465 size
= int_size_in_bytes (type
);
466 rsize
= ((size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
) * UNITS_PER_WORD
;
468 /* If the alignment of the type is greater than the default for a
469 parameter, align to STACK_BOUNDARY. */
470 if (TYPE_ALIGN (type
) > PARM_BOUNDARY
)
472 /* Assert the only case we generate code for: when
473 stack boundary = 2 * parm boundary. */
474 gcc_assert (STACK_BOUNDARY
== PARM_BOUNDARY
* 2);
476 tmp
= build2 (BIT_AND_EXPR
, sizetype
,
477 fold_convert (sizetype
, unshare_expr (args
)),
478 size_int (PARM_BOUNDARY
/ 8));
479 tmp
= build2 (POINTER_PLUS_EXPR
, ptr_type_node
,
480 unshare_expr (args
), tmp
);
482 gimplify_assign (unshare_expr (args
), tmp
, pre_p
);
485 /* Build conditional expression to calculate addr. The expression
486 will be gimplified later. */
487 tmp
= fold_build_pointer_plus_hwi (unshare_expr (args
), rsize
);
488 tmp
= build2 (TRUTH_AND_EXPR
, boolean_type_node
,
489 build2 (GT_EXPR
, boolean_type_node
, tmp
, unshare_expr (skip
)),
490 build2 (LE_EXPR
, boolean_type_node
, unshare_expr (args
),
491 unshare_expr (skip
)));
493 tmp
= build3 (COND_EXPR
, ptr_type_node
, tmp
,
494 build2 (POINTER_PLUS_EXPR
, ptr_type_node
, unshare_expr (skip
),
495 size_int (STACK_POINTER_OFFSET
)),
496 unshare_expr (args
));
498 gimplify_assign (addr
, tmp
, pre_p
);
500 /* Update VALIST.__args. */
501 tmp
= fold_build_pointer_plus_hwi (addr
, rsize
);
502 gimplify_assign (unshare_expr (args
), tmp
, pre_p
);
504 addr
= fold_convert (build_pointer_type (type
), addr
);
506 if (pass_by_reference_p
)
507 addr
= build_va_arg_indirect_ref (addr
);
509 return build_va_arg_indirect_ref (addr
);
514 /* Implement TARGET_RTX_COSTS. */
516 tilepro_rtx_costs (rtx x
, int code
, int outer_code
, int opno
, int *total
,
522 /* If this is an 8-bit constant, return zero since it can be
523 used nearly anywhere with no cost. If it is a valid operand
524 for an ADD or AND, likewise return 0 if we know it will be
525 used in that context. Otherwise, return 2 since it might be
526 used there later. All other constants take at least two
528 if (satisfies_constraint_I (x
))
533 else if (outer_code
== PLUS
&& add_operand (x
, VOIDmode
))
535 /* Slightly penalize large constants even though we can add
536 them in one instruction, because it forces the use of
537 2-wide bundling mode. */
541 else if (move_operand (x
, SImode
))
543 /* We can materialize in one move. */
544 *total
= COSTS_N_INSNS (1);
549 /* We can materialize in two moves. */
550 *total
= COSTS_N_INSNS (2);
559 *total
= COSTS_N_INSNS (2);
563 *total
= COSTS_N_INSNS (4);
571 /* If outer-code was a sign or zero extension, a cost of
572 COSTS_N_INSNS (1) was already added in, so account for
574 if (outer_code
== ZERO_EXTEND
|| outer_code
== SIGN_EXTEND
)
575 *total
= COSTS_N_INSNS (1);
577 *total
= COSTS_N_INSNS (2);
581 /* Convey that s[123]a are efficient. */
582 if (GET_CODE (XEXP (x
, 0)) == MULT
583 && cint_248_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
585 *total
= (rtx_cost (XEXP (XEXP (x
, 0), 0),
586 (enum rtx_code
) outer_code
, opno
, speed
)
587 + rtx_cost (XEXP (x
, 1),
588 (enum rtx_code
) outer_code
, opno
, speed
)
589 + COSTS_N_INSNS (1));
595 *total
= COSTS_N_INSNS (2);
600 if (outer_code
== MULT
)
603 *total
= COSTS_N_INSNS (1);
610 /* These are handled by software and are very expensive. */
611 *total
= COSTS_N_INSNS (100);
615 case UNSPEC_VOLATILE
:
617 int num
= XINT (x
, 1);
619 if (num
<= TILEPRO_LAST_LATENCY_1_INSN
)
620 *total
= COSTS_N_INSNS (1);
621 else if (num
<= TILEPRO_LAST_LATENCY_2_INSN
)
622 *total
= COSTS_N_INSNS (2);
623 else if (num
> TILEPRO_LAST_LATENCY_INSN
)
625 if (outer_code
== PLUS
)
628 *total
= COSTS_N_INSNS (1);
634 case UNSPEC_BLOCKAGE
:
635 case UNSPEC_NETWORK_BARRIER
:
639 case UNSPEC_LNK_AND_LABEL
:
641 case UNSPEC_NETWORK_RECEIVE
:
642 case UNSPEC_NETWORK_SEND
:
643 case UNSPEC_TLS_GD_ADD
:
644 *total
= COSTS_N_INSNS (1);
647 case UNSPEC_TLS_IE_LOAD
:
648 *total
= COSTS_N_INSNS (2);
652 *total
= COSTS_N_INSNS (3);
656 *total
= COSTS_N_INSNS (4);
659 case UNSPEC_LATENCY_L2
:
660 *total
= COSTS_N_INSNS (8);
663 case UNSPEC_TLS_GD_CALL
:
664 *total
= COSTS_N_INSNS (30);
667 case UNSPEC_LATENCY_MISS
:
668 *total
= COSTS_N_INSNS (80);
672 *total
= COSTS_N_INSNS (1);
685 /* Returns an SImode integer rtx with value VAL. */
687 gen_int_si (HOST_WIDE_INT val
)
689 return gen_int_mode (val
, SImode
);
693 /* Create a temporary variable to hold a partial result, to enable
696 create_temp_reg_if_possible (machine_mode mode
, rtx default_reg
)
698 return can_create_pseudo_p ()? gen_reg_rtx (mode
) : default_reg
;
702 /* Functions to save and restore machine-specific function data. */
703 static struct machine_function
*
704 tilepro_init_machine_status (void)
706 return ggc_cleared_alloc
<machine_function
> ();
710 /* Do anything needed before RTL is emitted for each function. */
712 tilepro_init_expanders (void)
714 /* Arrange to initialize and mark the machine per-function
716 init_machine_status
= tilepro_init_machine_status
;
718 if (cfun
&& cfun
->machine
&& flag_pic
)
720 static int label_num
= 0;
722 char text_label_name
[32];
724 struct machine_function
*machine
= cfun
->machine
;
726 ASM_GENERATE_INTERNAL_LABEL (text_label_name
, "L_PICLNK", label_num
++);
728 machine
->text_label_symbol
=
729 gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup (text_label_name
));
731 machine
->text_label_rtx
=
732 gen_rtx_REG (Pmode
, TILEPRO_PIC_TEXT_LABEL_REGNUM
);
734 machine
->got_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
736 machine
->calls_tls_get_addr
= false;
741 /* Return true if X contains a thread-local symbol. */
743 tilepro_tls_referenced_p (rtx x
)
745 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
746 x
= XEXP (XEXP (x
, 0), 0);
748 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x
))
751 /* That's all we handle in tilepro_legitimize_tls_address for
757 /* Return true if X requires a scratch register. It is given that
758 flag_pic is on and that X satisfies CONSTANT_P. */
760 tilepro_pic_address_needs_scratch (rtx x
)
762 if (GET_CODE (x
) == CONST
763 && GET_CODE (XEXP (x
, 0)) == PLUS
764 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
765 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
766 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
773 /* Implement TARGET_LEGITIMATE_CONSTANT_P. This is all constants for
774 which we are willing to load the value into a register via a move
775 pattern. TLS cannot be treated as a constant because it can
776 include a function call. */
778 tilepro_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
780 switch (GET_CODE (x
))
784 return !tilepro_tls_referenced_p (x
);
792 /* Return true if the constant value X is a legitimate general operand
793 when generating PIC code. It is given that flag_pic is on and that
794 X satisfies CONSTANT_P. */
796 tilepro_legitimate_pic_operand_p (rtx x
)
798 if (tilepro_pic_address_needs_scratch (x
))
801 if (tilepro_tls_referenced_p (x
))
808 /* Return true if the rtx X can be used as an address operand. */
810 tilepro_legitimate_address_p (machine_mode
ARG_UNUSED (mode
), rtx x
,
813 if (GET_CODE (x
) == SUBREG
)
816 switch (GET_CODE (x
))
820 if (GET_MODE_SIZE (GET_MODE (x
)) > UNITS_PER_WORD
)
827 if (GET_MODE_SIZE (GET_MODE (x
)) > UNITS_PER_WORD
)
830 if (GET_CODE (XEXP (x
, 1)) != PLUS
)
833 if (!rtx_equal_p (XEXP (x
, 0), XEXP (XEXP (x
, 1), 0)))
836 if (!satisfies_constraint_I (XEXP (XEXP (x
, 1), 1)))
849 /* Check if x is a valid reg. */
854 return REGNO_OK_FOR_BASE_P (REGNO (x
));
860 /* Return the rtx containing SYMBOL_REF to the text label. */
862 tilepro_text_label_symbol (void)
864 return cfun
->machine
->text_label_symbol
;
868 /* Return the register storing the value of the text label. */
870 tilepro_text_label_rtx (void)
872 return cfun
->machine
->text_label_rtx
;
876 /* Return the register storing the value of the global offset
879 tilepro_got_rtx (void)
881 return cfun
->machine
->got_rtx
;
885 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_. */
887 tilepro_got_symbol (void)
889 if (g_got_symbol
== NULL
)
890 g_got_symbol
= gen_rtx_SYMBOL_REF (Pmode
, "_GLOBAL_OFFSET_TABLE_");
896 /* Return a reference to the got to be used by tls references. */
898 tilepro_tls_got (void)
903 crtl
->uses_pic_offset_table
= 1;
904 return tilepro_got_rtx ();
907 temp
= gen_reg_rtx (Pmode
);
908 emit_move_insn (temp
, tilepro_got_symbol ());
914 /* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
915 this (thread-local) address. */
917 tilepro_legitimize_tls_address (rtx addr
)
921 gcc_assert (can_create_pseudo_p ());
923 if (GET_CODE (addr
) == SYMBOL_REF
)
924 switch (SYMBOL_REF_TLS_MODEL (addr
))
926 case TLS_MODEL_GLOBAL_DYNAMIC
:
927 case TLS_MODEL_LOCAL_DYNAMIC
:
929 rtx r0
, temp1
, temp2
, temp3
, got
;
932 ret
= gen_reg_rtx (Pmode
);
933 r0
= gen_rtx_REG (Pmode
, 0);
934 temp1
= gen_reg_rtx (Pmode
);
935 temp2
= gen_reg_rtx (Pmode
);
936 temp3
= gen_reg_rtx (Pmode
);
938 got
= tilepro_tls_got ();
939 emit_insn (gen_tls_gd_addhi (temp1
, got
, addr
));
940 emit_insn (gen_tls_gd_addlo (temp2
, temp1
, addr
));
941 emit_move_insn (r0
, temp2
);
942 emit_insn (gen_tls_gd_call (addr
));
943 emit_move_insn (temp3
, r0
);
944 last
= emit_insn (gen_tls_gd_add (ret
, temp3
, addr
));
945 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
948 case TLS_MODEL_INITIAL_EXEC
:
950 rtx temp1
, temp2
, temp3
, got
;
953 ret
= gen_reg_rtx (Pmode
);
954 temp1
= gen_reg_rtx (Pmode
);
955 temp2
= gen_reg_rtx (Pmode
);
956 temp3
= gen_reg_rtx (Pmode
);
958 got
= tilepro_tls_got ();
959 emit_insn (gen_tls_ie_addhi (temp1
, got
, addr
));
960 emit_insn (gen_tls_ie_addlo (temp2
, temp1
, addr
));
961 emit_insn (gen_tls_ie_load (temp3
, temp2
, addr
));
966 THREAD_POINTER_REGNUM
),
968 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
971 case TLS_MODEL_LOCAL_EXEC
:
976 ret
= gen_reg_rtx (Pmode
);
977 temp1
= gen_reg_rtx (Pmode
);
979 emit_insn (gen_tls_le_addhi (temp1
,
981 THREAD_POINTER_REGNUM
),
983 last
= emit_insn (gen_tls_le_addlo (ret
, temp1
, addr
));
984 set_unique_reg_note (last
, REG_EQUAL
, copy_rtx (addr
));
990 else if (GET_CODE (addr
) == CONST
)
994 gcc_assert (GET_CODE (XEXP (addr
, 0)) == PLUS
);
996 base
= tilepro_legitimize_tls_address (XEXP (XEXP (addr
, 0), 0));
997 offset
= XEXP (XEXP (addr
, 0), 1);
999 base
= force_operand (base
, NULL_RTX
);
1000 ret
= force_reg (Pmode
, gen_rtx_PLUS (Pmode
, base
, offset
));
1009 /* Legitimize PIC addresses. If the address is already
1010 position-independent, we return ORIG. Newly generated
1011 position-independent addresses go into a reg. This is REG if
1012 nonzero, otherwise we allocate register(s) as necessary. */
1014 tilepro_legitimize_pic_address (rtx orig
,
1015 machine_mode mode ATTRIBUTE_UNUSED
,
1018 if (GET_CODE (orig
) == SYMBOL_REF
)
1020 rtx address
, pic_ref
;
1024 gcc_assert (can_create_pseudo_p ());
1025 reg
= gen_reg_rtx (Pmode
);
1028 if (SYMBOL_REF_LOCAL_P (orig
))
1030 /* If not during reload, allocate another temp reg here for
1031 loading in the address, so that these instructions can be
1032 optimized properly. */
1033 rtx temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
1034 rtx text_label_symbol
= tilepro_text_label_symbol ();
1035 rtx text_label_rtx
= tilepro_text_label_rtx ();
1037 emit_insn (gen_addli_pcrel (temp_reg
, text_label_rtx
, orig
,
1038 text_label_symbol
));
1039 emit_insn (gen_auli_pcrel (temp_reg
, temp_reg
, orig
,
1040 text_label_symbol
));
1042 /* Note: this is conservative. We use the text_label but we
1043 don't use the pic_offset_table. However, in some cases
1044 we may need the pic_offset_table (see
1045 tilepro_fixup_pcrel_references). */
1046 crtl
->uses_pic_offset_table
= 1;
1050 emit_move_insn (reg
, address
);
1055 /* If not during reload, allocate another temp reg here for
1056 loading in the address, so that these instructions can be
1057 optimized properly. */
1058 rtx temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
1060 gcc_assert (flag_pic
);
1063 emit_insn (gen_add_got16 (temp_reg
,
1064 tilepro_got_rtx (), orig
));
1068 rtx temp_reg2
= create_temp_reg_if_possible (Pmode
, reg
);
1069 emit_insn (gen_addhi_got32 (temp_reg2
,
1070 tilepro_got_rtx (), orig
));
1071 emit_insn (gen_addlo_got32 (temp_reg
, temp_reg2
, orig
));
1076 pic_ref
= gen_const_mem (Pmode
, address
);
1077 crtl
->uses_pic_offset_table
= 1;
1078 emit_move_insn (reg
, pic_ref
);
1079 /* The following put a REG_EQUAL note on this insn, so that
1080 it can be optimized by loop. But it causes the label to
1081 be optimized away. */
1082 /* set_unique_reg_note (insn, REG_EQUAL, orig); */
1086 else if (GET_CODE (orig
) == CONST
)
1090 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1091 && XEXP (XEXP (orig
, 0), 0) == tilepro_got_rtx ())
1096 gcc_assert (can_create_pseudo_p ());
1097 reg
= gen_reg_rtx (Pmode
);
1100 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1101 base
= tilepro_legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
,
1104 tilepro_legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1105 base
== reg
? 0 : reg
);
1107 if (CONST_INT_P (offset
))
1109 if (can_create_pseudo_p ())
1110 offset
= force_reg (Pmode
, offset
);
1112 /* If we reach here, then something is seriously
1117 if (can_create_pseudo_p ())
1118 return force_reg (Pmode
, gen_rtx_PLUS (Pmode
, base
, offset
));
1122 else if (GET_CODE (orig
) == LABEL_REF
)
1124 rtx address
, temp_reg
;
1125 rtx text_label_symbol
;
1130 gcc_assert (can_create_pseudo_p ());
1131 reg
= gen_reg_rtx (Pmode
);
1134 /* If not during reload, allocate another temp reg here for
1135 loading in the address, so that these instructions can be
1136 optimized properly. */
1137 temp_reg
= create_temp_reg_if_possible (Pmode
, reg
);
1138 text_label_symbol
= tilepro_text_label_symbol ();
1139 text_label_rtx
= tilepro_text_label_rtx ();
1141 emit_insn (gen_addli_pcrel (temp_reg
, text_label_rtx
, orig
,
1142 text_label_symbol
));
1143 emit_insn (gen_auli_pcrel (temp_reg
, temp_reg
, orig
,
1144 text_label_symbol
));
1146 /* Note: this is conservative. We use the text_label but we
1147 don't use the pic_offset_table. */
1148 crtl
->uses_pic_offset_table
= 1;
1152 emit_move_insn (reg
, address
);
1161 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1163 tilepro_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1166 if (GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
1167 && symbolic_operand (x
, Pmode
) && tilepro_tls_referenced_p (x
))
1169 return tilepro_legitimize_tls_address (x
);
1173 return tilepro_legitimize_pic_address (x
, mode
, 0);
1180 /* Implement TARGET_DELEGITIMIZE_ADDRESS. */
1182 tilepro_delegitimize_address (rtx x
)
1184 x
= delegitimize_mem_from_attrs (x
);
1186 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == UNSPEC
)
1188 switch (XINT (XEXP (x
, 0), 1))
1190 case UNSPEC_PCREL_SYM
:
1191 case UNSPEC_GOT16_SYM
:
1192 case UNSPEC_GOT32_SYM
:
1195 x
= XVECEXP (XEXP (x
, 0), 0, 0);
1204 /* Emit code to load the PIC register. */
1206 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED
)
1208 int orig_flag_pic
= flag_pic
;
1210 rtx got_symbol
= tilepro_got_symbol ();
1211 rtx text_label_symbol
= tilepro_text_label_symbol ();
1212 rtx text_label_rtx
= tilepro_text_label_rtx ();
1215 emit_insn (gen_insn_lnk_and_label (text_label_rtx
, text_label_symbol
));
1217 emit_insn (gen_addli_pcrel (tilepro_got_rtx (),
1218 text_label_rtx
, got_symbol
, text_label_symbol
));
1220 emit_insn (gen_auli_pcrel (tilepro_got_rtx (),
1222 got_symbol
, text_label_symbol
));
1224 flag_pic
= orig_flag_pic
;
1226 /* Need to emit this whether or not we obey regdecls, since
1227 setjmp/longjmp can cause life info to screw up. ??? In the case
1228 where we don't obey regdecls, this is not sufficient since we may
1229 not fall out the bottom. */
1230 emit_use (tilepro_got_rtx ());
1234 /* Return the simd variant of the constant NUM of mode MODE, by
1235 replicating it to fill an interger of mode SImode. NUM is first
1236 truncated to fit in MODE. */
1238 tilepro_simd_int (rtx num
, machine_mode mode
)
1240 HOST_WIDE_INT n
= 0;
1242 gcc_assert (CONST_INT_P (num
));
1249 n
= 0x01010101 * (n
& 0x000000FF);
1252 n
= 0x00010001 * (n
& 0x0000FFFF);
1262 return gen_int_si (n
);
1266 /* Split one or more DImode RTL references into pairs of SImode
1267 references. The RTL can be REG, offsettable MEM, integer constant,
1268 or CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL
1269 to split and "num" is its length. lo_half and hi_half are output
1270 arrays that parallel "operands". */
1272 split_di (rtx operands
[], int num
, rtx lo_half
[], rtx hi_half
[])
1276 rtx op
= operands
[num
];
1278 /* simplify_subreg refuse to split volatile memory addresses,
1279 but we still have to handle it. */
1282 lo_half
[num
] = adjust_address (op
, SImode
, 0);
1283 hi_half
[num
] = adjust_address (op
, SImode
, 4);
1287 lo_half
[num
] = simplify_gen_subreg (SImode
, op
,
1288 GET_MODE (op
) == VOIDmode
1289 ? DImode
: GET_MODE (op
), 0);
1290 hi_half
[num
] = simplify_gen_subreg (SImode
, op
,
1291 GET_MODE (op
) == VOIDmode
1292 ? DImode
: GET_MODE (op
), 4);
1298 /* Returns true iff val can be moved into a register in one
1299 instruction. And if it can, it emits the code to move the
1302 If three_wide_only is true, this insists on an instruction that
1303 works in a bundle containing three instructions. */
1305 expand_set_cint32_one_inst (rtx dest_reg
,
1306 HOST_WIDE_INT val
, bool three_wide_only
)
1308 val
= trunc_int_for_mode (val
, SImode
);
1310 if (val
== trunc_int_for_mode (val
, QImode
))
1313 emit_move_insn (dest_reg
, GEN_INT (val
));
1316 else if (!three_wide_only
)
1318 rtx imm_op
= GEN_INT (val
);
1320 if (satisfies_constraint_J (imm_op
)
1321 || satisfies_constraint_K (imm_op
)
1322 || satisfies_constraint_N (imm_op
)
1323 || satisfies_constraint_P (imm_op
))
1325 emit_move_insn (dest_reg
, imm_op
);
1334 /* Implement SImode rotatert. */
1335 static HOST_WIDE_INT
1336 rotate_right (HOST_WIDE_INT n
, int count
)
1338 unsigned HOST_WIDE_INT x
= n
& 0xFFFFFFFF;
1341 return ((x
>> count
) | (x
<< (32 - count
))) & 0xFFFFFFFF;
1345 /* Return true iff n contains exactly one contiguous sequence of 1
1346 bits, possibly wrapping around from high bits to low bits. */
1348 tilepro_bitfield_operand_p (HOST_WIDE_INT n
, int *first_bit
, int *last_bit
)
1355 for (i
= 0; i
< 32; i
++)
1357 unsigned HOST_WIDE_INT x
= rotate_right (n
, i
);
1361 /* See if x is a power of two minus one, i.e. only consecutive 1
1362 bits starting from bit 0. */
1363 if ((x
& (x
+ 1)) == 0)
1365 if (first_bit
!= NULL
)
1367 if (last_bit
!= NULL
)
1368 *last_bit
= (i
+ exact_log2 (x
^ (x
>> 1))) & 31;
1378 /* Create code to move the CONST_INT value in src_val to dest_reg. */
1380 expand_set_cint32 (rtx dest_reg
, rtx src_val
)
1383 int leading_zeroes
, trailing_zeroes
;
1385 int three_wide_only
;
1388 gcc_assert (CONST_INT_P (src_val
));
1389 val
= trunc_int_for_mode (INTVAL (src_val
), SImode
);
1391 /* See if we can generate the constant in one instruction. */
1392 if (expand_set_cint32_one_inst (dest_reg
, val
, false))
1395 /* Create a temporary variable to hold a partial result, to enable
1397 temp
= create_temp_reg_if_possible (SImode
, dest_reg
);
1399 leading_zeroes
= 31 - floor_log2 (val
& 0xFFFFFFFF);
1400 trailing_zeroes
= exact_log2 (val
& -val
);
1402 lower
= trunc_int_for_mode (val
, HImode
);
1403 upper
= trunc_int_for_mode ((val
- lower
) >> 16, HImode
);
1405 /* First try all three-wide instructions that generate a constant
1406 (i.e. movei) followed by various shifts and rotates. If none of
1407 those work, try various two-wide ways of generating a constant
1408 followed by various shifts and rotates. */
1409 for (three_wide_only
= 1; three_wide_only
>= 0; three_wide_only
--)
1413 if (expand_set_cint32_one_inst (temp
, val
>> trailing_zeroes
,
1416 /* 0xFFFFA500 becomes:
1417 movei temp, 0xFFFFFFA5
1418 shli dest, temp, 8 */
1419 emit_move_insn (dest_reg
,
1420 gen_rtx_ASHIFT (SImode
, temp
,
1421 GEN_INT (trailing_zeroes
)));
1425 if (expand_set_cint32_one_inst (temp
, val
<< leading_zeroes
,
1428 /* 0x7FFFFFFF becomes:
1430 shri dest, temp, 1 */
1431 emit_move_insn (dest_reg
,
1432 gen_rtx_LSHIFTRT (SImode
, temp
,
1433 GEN_INT (leading_zeroes
)));
1437 /* Try rotating a one-instruction immediate, since rotate is
1439 for (count
= 1; count
< 32; count
++)
1441 HOST_WIDE_INT r
= rotate_right (val
, count
);
1442 if (expand_set_cint32_one_inst (temp
, r
, three_wide_only
))
1444 /* 0xFFA5FFFF becomes:
1445 movei temp, 0xFFFFFFA5
1446 rli dest, temp, 16 */
1447 emit_move_insn (dest_reg
,
1448 gen_rtx_ROTATE (SImode
, temp
, GEN_INT (count
)));
1453 if (lower
== trunc_int_for_mode (lower
, QImode
))
1455 /* We failed to use two 3-wide instructions, but the low 16
1456 bits are a small number so just use a 2-wide + 3-wide
1457 auli + addi pair rather than anything more exotic.
1460 auli temp, zero, 0x1234
1461 addi dest, temp, 0x56 */
1466 /* Fallback case: use a auli + addli/addi pair. */
1467 emit_move_insn (temp
, GEN_INT (upper
<< 16));
1468 emit_move_insn (dest_reg
, (gen_rtx_PLUS (SImode
, temp
, GEN_INT (lower
))));
1472 /* Load OP1, a 32-bit constant, into OP0, a register. We know it
1473 can't be done in one insn when we get here, the move expander
1476 tilepro_expand_set_const32 (rtx op0
, rtx op1
)
1478 machine_mode mode
= GET_MODE (op0
);
1481 if (CONST_INT_P (op1
))
1483 /* TODO: I don't know if we want to split large constants now,
1484 or wait until later (with a define_split).
1486 Does splitting early help CSE? Does it harm other
1487 optimizations that might fold loads? */
1488 expand_set_cint32 (op0
, op1
);
1492 temp
= create_temp_reg_if_possible (mode
, op0
);
1494 /* A symbol, emit in the traditional way. */
1495 emit_move_insn (temp
, gen_rtx_HIGH (mode
, op1
));
1496 emit_move_insn (op0
, gen_rtx_LO_SUM (mode
, temp
, op1
));
1501 /* Expand a move instruction. Return true if all work is done. */
1503 tilepro_expand_mov (machine_mode mode
, rtx
*operands
)
1505 /* Handle sets of MEM first. */
1506 if (MEM_P (operands
[0]))
1508 if (can_create_pseudo_p ())
1509 operands
[0] = validize_mem (operands
[0]);
1511 if (reg_or_0_operand (operands
[1], mode
))
1514 if (!reload_in_progress
)
1515 operands
[1] = force_reg (mode
, operands
[1]);
1518 /* Fixup TLS cases. */
1519 if (CONSTANT_P (operands
[1]) && tilepro_tls_referenced_p (operands
[1]))
1521 operands
[1] = tilepro_legitimize_tls_address (operands
[1]);
1525 /* Fixup PIC cases. */
1526 if (flag_pic
&& CONSTANT_P (operands
[1]))
1528 if (tilepro_pic_address_needs_scratch (operands
[1]))
1529 operands
[1] = tilepro_legitimize_pic_address (operands
[1], mode
, 0);
1531 if (symbolic_operand (operands
[1], mode
))
1533 operands
[1] = tilepro_legitimize_pic_address (operands
[1],
1535 (reload_in_progress
?
1542 /* Fixup for UNSPEC addresses. */
1544 && GET_CODE (operands
[1]) == HIGH
1545 && GET_CODE (XEXP (operands
[1], 0)) == CONST
1546 && GET_CODE (XEXP (XEXP (operands
[1], 0), 0)) == UNSPEC
)
1548 rtx unspec
= XEXP (XEXP (operands
[1], 0), 0);
1549 int unspec_num
= XINT (unspec
, 1);
1550 if (unspec_num
== UNSPEC_PCREL_SYM
)
1552 emit_insn (gen_auli_pcrel (operands
[0], const0_rtx
,
1553 XVECEXP (unspec
, 0, 0),
1554 XVECEXP (unspec
, 0, 1)));
1557 else if (flag_pic
== 2 && unspec_num
== UNSPEC_GOT32_SYM
)
1559 emit_insn (gen_addhi_got32 (operands
[0], const0_rtx
,
1560 XVECEXP (unspec
, 0, 0)));
1563 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_GD
)
1565 emit_insn (gen_tls_gd_addhi (operands
[0], const0_rtx
,
1566 XVECEXP (unspec
, 0, 0)));
1569 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_IE
)
1571 emit_insn (gen_tls_ie_addhi (operands
[0], const0_rtx
,
1572 XVECEXP (unspec
, 0, 0)));
1575 else if (HAVE_AS_TLS
&& unspec_num
== UNSPEC_TLS_LE
)
1577 emit_insn (gen_tls_le_addhi (operands
[0], const0_rtx
,
1578 XVECEXP (unspec
, 0, 0)));
1583 /* Accept non-constants and valid constants unmodified. */
1584 if (!CONSTANT_P (operands
[1])
1585 || GET_CODE (operands
[1]) == HIGH
|| move_operand (operands
[1], mode
))
1588 /* Split large integers. */
1589 if (GET_MODE_SIZE (mode
) <= 4)
1591 tilepro_expand_set_const32 (operands
[0], operands
[1]);
1599 /* Expand the "insv" pattern. */
1601 tilepro_expand_insv (rtx operands
[4])
1603 rtx first_rtx
= operands
[2];
1604 HOST_WIDE_INT first
= INTVAL (first_rtx
);
1605 HOST_WIDE_INT width
= INTVAL (operands
[1]);
1606 rtx v
= operands
[3];
1608 /* Shift the inserted bits into position. */
1611 if (CONST_INT_P (v
))
1613 /* Shift the constant into mm position. */
1614 v
= gen_int_si (INTVAL (v
) << first
);
1618 /* Shift over the value to be inserted. */
1619 rtx tmp
= gen_reg_rtx (SImode
);
1620 emit_insn (gen_ashlsi3 (tmp
, v
, first_rtx
));
1625 /* Insert the shifted bits using an 'mm' insn. */
1626 emit_insn (gen_insn_mm (operands
[0], v
, operands
[0], first_rtx
,
1627 GEN_INT (first
+ width
- 1)));
1631 /* Expand unaligned loads. */
1633 tilepro_expand_unaligned_load (rtx dest_reg
, rtx mem
, HOST_WIDE_INT bitsize
,
1634 HOST_WIDE_INT bit_offset
, bool sign
)
1637 rtx addr_lo
, addr_hi
;
1638 rtx mem_lo
, mem_hi
, hi
;
1639 rtx mema
, wide_result
;
1640 int last_byte_offset
;
1641 HOST_WIDE_INT byte_offset
= bit_offset
/ BITS_PER_UNIT
;
1643 mode
= GET_MODE (dest_reg
);
1645 hi
= gen_reg_rtx (mode
);
1647 if (bitsize
== 2 * BITS_PER_UNIT
&& (bit_offset
% BITS_PER_UNIT
) == 0)
1651 /* When just loading a two byte value, we can load the two bytes
1652 individually and combine them efficiently. */
1654 mem_lo
= adjust_address (mem
, QImode
, byte_offset
);
1655 mem_hi
= adjust_address (mem
, QImode
, byte_offset
+ 1);
1657 lo
= gen_reg_rtx (mode
);
1658 emit_insn (gen_zero_extendqisi2 (lo
, mem_lo
));
1662 rtx tmp
= gen_reg_rtx (mode
);
1664 /* Do a signed load of the second byte then shift and OR it
1666 emit_insn (gen_extendqisi2 (gen_lowpart (SImode
, hi
), mem_hi
));
1667 emit_insn (gen_ashlsi3 (gen_lowpart (SImode
, tmp
),
1668 gen_lowpart (SImode
, hi
), GEN_INT (8)));
1669 emit_insn (gen_iorsi3 (gen_lowpart (SImode
, dest_reg
),
1670 gen_lowpart (SImode
, lo
),
1671 gen_lowpart (SImode
, tmp
)));
1675 /* Do two unsigned loads and use intlb to interleave
1677 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode
, hi
), mem_hi
));
1678 emit_insn (gen_insn_intlb (gen_lowpart (SImode
, dest_reg
),
1679 gen_lowpart (SImode
, hi
),
1680 gen_lowpart (SImode
, lo
)));
1686 mema
= XEXP (mem
, 0);
1688 /* AND addresses cannot be in any alias set, since they may
1689 implicitly alias surrounding code. Ideally we'd have some alias
1690 set that covered all types except those with alignment 8 or
1692 addr_lo
= force_reg (Pmode
, plus_constant (Pmode
, mema
, byte_offset
));
1693 mem_lo
= change_address (mem
, mode
,
1694 gen_rtx_AND (Pmode
, addr_lo
, GEN_INT (-4)));
1695 set_mem_alias_set (mem_lo
, 0);
1697 /* Load the high word at an address that will not fault if the low
1698 address is aligned and at the very end of a page. */
1699 last_byte_offset
= (bit_offset
+ bitsize
- 1) / BITS_PER_UNIT
;
1700 addr_hi
= force_reg (Pmode
, plus_constant (Pmode
, mema
, last_byte_offset
));
1701 mem_hi
= change_address (mem
, mode
,
1702 gen_rtx_AND (Pmode
, addr_hi
, GEN_INT (-4)));
1703 set_mem_alias_set (mem_hi
, 0);
1707 addr_lo
= make_safe_from (addr_lo
, dest_reg
);
1708 wide_result
= dest_reg
;
1712 wide_result
= gen_reg_rtx (mode
);
1715 /* Load hi first in case dest_reg is used in mema. */
1716 emit_move_insn (hi
, mem_hi
);
1717 emit_move_insn (wide_result
, mem_lo
);
1719 emit_insn (gen_insn_dword_align (gen_lowpart (SImode
, wide_result
),
1720 gen_lowpart (SImode
, wide_result
),
1721 gen_lowpart (SImode
, hi
), addr_lo
));
1726 extract_bit_field (gen_lowpart (SImode
, wide_result
),
1727 bitsize
, bit_offset
% BITS_PER_UNIT
,
1728 !sign
, gen_lowpart (SImode
, dest_reg
),
1731 if (extracted
!= dest_reg
)
1732 emit_move_insn (dest_reg
, gen_lowpart (SImode
, extracted
));
1737 /* Expand unaligned stores. */
1739 tilepro_expand_unaligned_store (rtx mem
, rtx src
, HOST_WIDE_INT bitsize
,
1740 HOST_WIDE_INT bit_offset
)
1742 HOST_WIDE_INT byte_offset
= bit_offset
/ BITS_PER_UNIT
;
1743 HOST_WIDE_INT bytesize
= bitsize
/ BITS_PER_UNIT
;
1744 HOST_WIDE_INT shift_amt
;
1749 for (i
= 0, shift_amt
= 0; i
< bytesize
; i
++, shift_amt
+= BITS_PER_UNIT
)
1751 mem_addr
= adjust_address (mem
, QImode
, byte_offset
+ i
);
1755 store_val
= expand_simple_binop (SImode
, LSHIFTRT
,
1756 gen_lowpart (SImode
, src
),
1757 GEN_INT (shift_amt
), NULL
, 1,
1759 store_val
= gen_lowpart (QImode
, store_val
);
1763 store_val
= gen_lowpart (QImode
, src
);
1766 emit_move_insn (mem_addr
, store_val
);
1771 /* Implement the movmisalign patterns. One of the operands is a
1772 memory that is not naturally aligned. Emit instructions to load
1775 tilepro_expand_movmisalign (machine_mode mode
, rtx
*operands
)
1777 if (MEM_P (operands
[1]))
1781 if (register_operand (operands
[0], mode
))
1784 tmp
= gen_reg_rtx (mode
);
1786 tilepro_expand_unaligned_load (tmp
, operands
[1],
1787 GET_MODE_BITSIZE (mode
), 0, true);
1789 if (tmp
!= operands
[0])
1790 emit_move_insn (operands
[0], tmp
);
1792 else if (MEM_P (operands
[0]))
1794 if (!reg_or_0_operand (operands
[1], mode
))
1795 operands
[1] = force_reg (mode
, operands
[1]);
1797 tilepro_expand_unaligned_store (operands
[0], operands
[1],
1798 GET_MODE_BITSIZE (mode
), 0);
1805 /* Implement the addsi3 pattern. */
1807 tilepro_expand_addsi (rtx op0
, rtx op1
, rtx op2
)
1813 /* Skip anything that only takes one instruction. */
1814 if (add_operand (op2
, SImode
))
1817 /* We can only optimize ints here (it should be impossible to get
1818 here with any other type, but it is harmless to check. */
1819 if (!CONST_INT_P (op2
))
1822 temp
= create_temp_reg_if_possible (SImode
, op0
);
1824 high
= (n
+ (n
& 0x8000)) & ~0xffff;
1826 emit_move_insn (temp
, gen_rtx_PLUS (SImode
, op1
, gen_int_si (high
)));
1827 emit_move_insn (op0
, gen_rtx_PLUS (SImode
, temp
, gen_int_si (n
- high
)));
1833 /* Implement the allocate_stack pattern (alloca). */
1835 tilepro_allocate_stack (rtx op0
, rtx op1
)
1837 /* Technically the correct way to initialize chain_loc is with
1838 * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
1839 * sets the alias_set to that of a frame reference. Some of our
1840 * tests rely on some unsafe assumption about when the chaining
1841 * update is done, we need to be conservative about reordering the
1842 * chaining instructions.
1844 rtx fp_addr
= gen_reg_rtx (Pmode
);
1845 rtx fp_value
= gen_reg_rtx (Pmode
);
1848 emit_move_insn (fp_addr
, gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
1849 GEN_INT (UNITS_PER_WORD
)));
1851 fp_loc
= gen_frame_mem (Pmode
, fp_addr
);
1853 emit_move_insn (fp_value
, fp_loc
);
1855 op1
= force_reg (Pmode
, op1
);
1857 emit_move_insn (stack_pointer_rtx
,
1858 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, op1
));
1860 emit_move_insn (fp_addr
, gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
1861 GEN_INT (UNITS_PER_WORD
)));
1863 fp_loc
= gen_frame_mem (Pmode
, fp_addr
);
1865 emit_move_insn (fp_loc
, fp_value
);
1867 emit_move_insn (op0
, virtual_stack_dynamic_rtx
);
1874 /* Returns the insn_code in ENTRY. */
1875 static enum insn_code
1876 tilepro_multiply_get_opcode (const struct tilepro_multiply_insn_seq_entry
1879 return tilepro_multiply_insn_seq_decode_opcode
[entry
->compressed_opcode
];
1883 /* Returns the length of the 'op' array. */
1885 tilepro_multiply_get_num_ops (const struct tilepro_multiply_insn_seq
*seq
)
1887 /* The array either uses all of its allocated slots or is terminated
1888 by a bogus opcode. Either way, the array size is the index of the
1889 last valid opcode plus one. */
1891 for (i
= tilepro_multiply_insn_seq_MAX_OPERATIONS
- 1; i
>= 0; i
--)
1892 if (tilepro_multiply_get_opcode (&seq
->op
[i
]) != CODE_FOR_nothing
)
1895 /* An empty array is not allowed. */
1900 /* We precompute a number of expression trees for multiplying by
1901 constants. This generates code for such an expression tree by
1902 walking through the nodes in the tree (which are conveniently
1903 pre-linearized) and emitting an instruction for each one. */
1905 tilepro_expand_constant_multiply_given_sequence (rtx result
, rtx src
,
1907 tilepro_multiply_insn_seq
1913 /* Keep track of the subexpressions computed so far, so later
1914 instructions can refer to them. We seed the array with zero and
1915 the value being multiplied. */
1916 int num_subexprs
= 2;
1917 rtx subexprs
[tilepro_multiply_insn_seq_MAX_OPERATIONS
+ 2];
1918 subexprs
[0] = const0_rtx
;
1921 /* Determine how many instructions we are going to generate. */
1922 num_ops
= tilepro_multiply_get_num_ops (seq
);
1923 gcc_assert (num_ops
> 0
1924 && num_ops
<= tilepro_multiply_insn_seq_MAX_OPERATIONS
);
1926 for (i
= 0; i
< num_ops
; i
++)
1928 const struct tilepro_multiply_insn_seq_entry
*entry
= &seq
->op
[i
];
1930 /* Figure out where to store the output of this instruction. */
1931 const bool is_last_op
= (i
+ 1 == num_ops
);
1932 rtx out
= is_last_op
? result
: gen_reg_rtx (SImode
);
1934 enum insn_code opcode
= tilepro_multiply_get_opcode (entry
);
1935 if (opcode
== CODE_FOR_ashlsi3
)
1937 /* Handle shift by immediate. This is a special case because
1938 the meaning of the second operand is a constant shift
1939 count rather than an operand index. */
1941 /* Make sure the shift count is in range. Zero should not
1943 const int shift_count
= entry
->rhs
;
1944 gcc_assert (shift_count
> 0 && shift_count
< 32);
1946 /* Emit the actual instruction. */
1947 emit_insn (GEN_FCN (opcode
)
1948 (out
, subexprs
[entry
->lhs
],
1949 gen_rtx_CONST_INT (SImode
, shift_count
)));
1953 /* Handle a normal two-operand instruction, such as add or
1956 /* Make sure we are referring to a previously computed
1958 gcc_assert (entry
->rhs
< num_subexprs
);
1960 /* Emit the actual instruction. */
1961 emit_insn (GEN_FCN (opcode
)
1962 (out
, subexprs
[entry
->lhs
], subexprs
[entry
->rhs
]));
1965 /* Record this subexpression for use by later expressions. */
1966 subexprs
[num_subexprs
++] = out
;
1971 /* bsearch helper function. */
1973 tilepro_compare_multipliers (const void *key
, const void *t
)
1975 return *(const int *) key
-
1976 ((const struct tilepro_multiply_insn_seq
*) t
)->multiplier
;
1980 /* Returns the tilepro_multiply_insn_seq for multiplier, or NULL if
1982 static const struct tilepro_multiply_insn_seq
*
1983 tilepro_find_multiply_insn_seq_for_constant (int multiplier
)
1985 return ((const struct tilepro_multiply_insn_seq
*)
1986 bsearch (&multiplier
, tilepro_multiply_insn_seq_table
,
1987 tilepro_multiply_insn_seq_table_size
,
1988 sizeof tilepro_multiply_insn_seq_table
[0],
1989 tilepro_compare_multipliers
));
1993 /* Try to a expand constant multiply in SImode by looking it up in a
1994 precompiled table. OP0 is the result operand, OP1 is the source
1995 operand, and MULTIPLIER is the value of the constant. Return true
1998 tilepro_expand_const_mulsi (rtx op0
, rtx op1
, int multiplier
)
2000 /* See if we have precomputed an efficient way to multiply by this
2002 const struct tilepro_multiply_insn_seq
*seq
=
2003 tilepro_find_multiply_insn_seq_for_constant (multiplier
);
2006 tilepro_expand_constant_multiply_given_sequence (op0
, op1
, seq
);
2014 /* Expand the mulsi pattern. */
2016 tilepro_expand_mulsi (rtx op0
, rtx op1
, rtx op2
)
2018 if (CONST_INT_P (op2
))
2020 HOST_WIDE_INT n
= trunc_int_for_mode (INTVAL (op2
), SImode
);
2021 return tilepro_expand_const_mulsi (op0
, op1
, n
);
2027 /* Expand a high multiply pattern in SImode. RESULT, OP1, OP2 are the
2028 operands, and SIGN is true if it's a signed multiply, and false if
2029 it's an unsigned multiply. */
2031 tilepro_expand_high_multiply (rtx result
, rtx op1
, rtx op2
, bool sign
)
2033 rtx tmp0
= gen_reg_rtx (SImode
);
2034 rtx tmp1
= gen_reg_rtx (SImode
);
2035 rtx tmp2
= gen_reg_rtx (SImode
);
2036 rtx tmp3
= gen_reg_rtx (SImode
);
2037 rtx tmp4
= gen_reg_rtx (SImode
);
2038 rtx tmp5
= gen_reg_rtx (SImode
);
2039 rtx tmp6
= gen_reg_rtx (SImode
);
2040 rtx tmp7
= gen_reg_rtx (SImode
);
2041 rtx tmp8
= gen_reg_rtx (SImode
);
2042 rtx tmp9
= gen_reg_rtx (SImode
);
2043 rtx tmp10
= gen_reg_rtx (SImode
);
2044 rtx tmp11
= gen_reg_rtx (SImode
);
2045 rtx tmp12
= gen_reg_rtx (SImode
);
2046 rtx tmp13
= gen_reg_rtx (SImode
);
2047 rtx result_lo
= gen_reg_rtx (SImode
);
2051 emit_insn (gen_insn_mulhl_su (tmp0
, op1
, op2
));
2052 emit_insn (gen_insn_mulhl_su (tmp1
, op2
, op1
));
2053 emit_insn (gen_insn_mulll_uu (tmp2
, op1
, op2
));
2054 emit_insn (gen_insn_mulhh_ss (tmp3
, op1
, op2
));
2058 emit_insn (gen_insn_mulhl_uu (tmp0
, op1
, op2
));
2059 emit_insn (gen_insn_mulhl_uu (tmp1
, op2
, op1
));
2060 emit_insn (gen_insn_mulll_uu (tmp2
, op1
, op2
));
2061 emit_insn (gen_insn_mulhh_uu (tmp3
, op1
, op2
));
2064 emit_move_insn (tmp4
, (gen_rtx_ASHIFT (SImode
, tmp0
, GEN_INT (16))));
2066 emit_move_insn (tmp5
, (gen_rtx_ASHIFT (SImode
, tmp1
, GEN_INT (16))));
2068 emit_move_insn (tmp6
, (gen_rtx_PLUS (SImode
, tmp4
, tmp5
)));
2069 emit_move_insn (result_lo
, (gen_rtx_PLUS (SImode
, tmp2
, tmp6
)));
2071 emit_move_insn (tmp7
, gen_rtx_LTU (SImode
, tmp6
, tmp4
));
2072 emit_move_insn (tmp8
, gen_rtx_LTU (SImode
, result_lo
, tmp2
));
2076 emit_move_insn (tmp9
, (gen_rtx_ASHIFTRT (SImode
, tmp0
, GEN_INT (16))));
2077 emit_move_insn (tmp10
, (gen_rtx_ASHIFTRT (SImode
, tmp1
, GEN_INT (16))));
2081 emit_move_insn (tmp9
, (gen_rtx_LSHIFTRT (SImode
, tmp0
, GEN_INT (16))));
2082 emit_move_insn (tmp10
, (gen_rtx_LSHIFTRT (SImode
, tmp1
, GEN_INT (16))));
2085 emit_move_insn (tmp11
, (gen_rtx_PLUS (SImode
, tmp3
, tmp7
)));
2086 emit_move_insn (tmp12
, (gen_rtx_PLUS (SImode
, tmp8
, tmp9
)));
2087 emit_move_insn (tmp13
, (gen_rtx_PLUS (SImode
, tmp11
, tmp12
)));
2088 emit_move_insn (result
, (gen_rtx_PLUS (SImode
, tmp13
, tmp10
)));
2092 /* Implement smulsi3_highpart. */
2094 tilepro_expand_smulsi3_highpart (rtx op0
, rtx op1
, rtx op2
)
2096 tilepro_expand_high_multiply (op0
, op1
, op2
, true);
2100 /* Implement umulsi3_highpart. */
2102 tilepro_expand_umulsi3_highpart (rtx op0
, rtx op1
, rtx op2
)
2104 tilepro_expand_high_multiply (op0
, op1
, op2
, false);
2109 /* Compare and branches */
2111 /* Helper function to handle DImode for tilepro_emit_setcc_internal. */
2113 tilepro_emit_setcc_internal_di (rtx res
, enum rtx_code code
, rtx op0
, rtx op1
)
2115 rtx operands
[2], lo_half
[2], hi_half
[2];
2116 rtx tmp
, tmp0
, tmp1
, tmp2
;
2119 /* Reduce the number of cases we need to handle by reversing the
2129 /* We handle these compares directly. */
2136 /* Reverse the operands. */
2141 /* We should not have called this with any other code. */
2147 code
= swap_condition (code
);
2148 tmp
= op0
, op0
= op1
, op1
= tmp
;
2154 split_di (operands
, 2, lo_half
, hi_half
);
2156 if (!reg_or_0_operand (lo_half
[0], SImode
))
2157 lo_half
[0] = force_reg (SImode
, lo_half
[0]);
2159 if (!reg_or_0_operand (hi_half
[0], SImode
))
2160 hi_half
[0] = force_reg (SImode
, hi_half
[0]);
2162 if (!CONST_INT_P (lo_half
[1]) && !register_operand (lo_half
[1], SImode
))
2163 lo_half
[1] = force_reg (SImode
, lo_half
[1]);
2165 if (!CONST_INT_P (hi_half
[1]) && !register_operand (hi_half
[1], SImode
))
2166 hi_half
[1] = force_reg (SImode
, hi_half
[1]);
2168 tmp0
= gen_reg_rtx (SImode
);
2169 tmp1
= gen_reg_rtx (SImode
);
2170 tmp2
= gen_reg_rtx (SImode
);
2175 emit_insn (gen_insn_seq (tmp0
, lo_half
[0], lo_half
[1]));
2176 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2177 emit_insn (gen_andsi3 (res
, tmp0
, tmp1
));
2181 emit_insn (gen_insn_sne (tmp0
, lo_half
[0], lo_half
[1]));
2182 emit_insn (gen_insn_sne (tmp1
, hi_half
[0], hi_half
[1]));
2183 emit_insn (gen_iorsi3 (res
, tmp0
, tmp1
));
2187 emit_insn (gen_insn_slte (tmp0
, hi_half
[0], hi_half
[1]));
2188 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2189 emit_insn (gen_insn_slte_u (tmp2
, lo_half
[0], lo_half
[1]));
2190 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2193 if (operands
[1] == const0_rtx
)
2195 emit_insn (gen_lshrsi3 (res
, hi_half
[0], GEN_INT (31)));
2200 emit_insn (gen_insn_slt (tmp0
, hi_half
[0], hi_half
[1]));
2201 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2202 emit_insn (gen_insn_slt_u (tmp2
, lo_half
[0], lo_half
[1]));
2203 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2207 emit_insn (gen_insn_slte_u (tmp0
, hi_half
[0], hi_half
[1]));
2208 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2209 emit_insn (gen_insn_slte_u (tmp2
, lo_half
[0], lo_half
[1]));
2210 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2213 emit_insn (gen_insn_slt_u (tmp0
, hi_half
[0], hi_half
[1]));
2214 emit_insn (gen_insn_seq (tmp1
, hi_half
[0], hi_half
[1]));
2215 emit_insn (gen_insn_slt_u (tmp2
, lo_half
[0], lo_half
[1]));
2216 emit_insn (gen_insn_mvnz (res
, tmp0
, tmp1
, tmp2
));
2226 /* Certain simplifications can be done to make invalid setcc
2227 operations valid. Return the final comparison, or NULL if we can't
2230 tilepro_emit_setcc_internal (rtx res
, enum rtx_code code
, rtx op0
, rtx op1
,
2231 machine_mode cmp_mode
)
2236 if (cmp_mode
== DImode
)
2238 return tilepro_emit_setcc_internal_di (res
, code
, op0
, op1
);
2241 /* The general case: fold the comparison code to the types of
2242 compares that we have, choosing the branch as necessary. */
2252 /* We have these compares. */
2259 /* We do not have these compares, so we reverse the
2265 /* We should not have called this with any other code. */
2271 code
= swap_condition (code
);
2272 tmp
= op0
, op0
= op1
, op1
= tmp
;
2275 if (!reg_or_0_operand (op0
, SImode
))
2276 op0
= force_reg (SImode
, op0
);
2278 if (!CONST_INT_P (op1
) && !register_operand (op1
, SImode
))
2279 op1
= force_reg (SImode
, op1
);
2281 /* Return the setcc comparison. */
2282 emit_insn (gen_rtx_SET (VOIDmode
, res
,
2283 gen_rtx_fmt_ee (code
, SImode
, op0
, op1
)));
2289 /* Implement cstore patterns. */
2291 tilepro_emit_setcc (rtx operands
[], machine_mode cmp_mode
)
2294 tilepro_emit_setcc_internal (operands
[0], GET_CODE (operands
[1]),
2295 operands
[2], operands
[3], cmp_mode
);
2299 /* Return whether CODE is a signed comparison. */
2301 signed_compare_p (enum rtx_code code
)
2303 return (code
== EQ
|| code
== NE
|| code
== LT
|| code
== LE
2304 || code
== GT
|| code
== GE
);
2308 /* Generate the comparison for an SImode conditional branch. */
2310 tilepro_emit_cc_test (enum rtx_code code
, rtx op0
, rtx op1
,
2311 machine_mode cmp_mode
, bool eq_ne_only
)
2313 enum rtx_code branch_code
;
2316 /* Check for a compare against zero using a comparison we can do
2318 if (cmp_mode
!= DImode
2319 && op1
== const0_rtx
2320 && (code
== EQ
|| code
== NE
2321 || (!eq_ne_only
&& signed_compare_p (code
))))
2323 op0
= force_reg (SImode
, op0
);
2324 return gen_rtx_fmt_ee (code
, VOIDmode
, op0
, const0_rtx
);
2327 /* The general case: fold the comparison code to the types of
2328 compares that we have, choosing the branch as necessary. */
2336 /* We have these compares. */
2345 /* These must be reversed (except NE, but let's
2347 code
= reverse_condition (code
);
2355 if (cmp_mode
!= DImode
2356 && CONST_INT_P (op1
) && (!satisfies_constraint_I (op1
) || code
== LEU
))
2358 HOST_WIDE_INT n
= trunc_int_for_mode (INTVAL (op1
), SImode
);
2363 /* Subtract off the value we want to compare against and see
2364 if we get zero. This is cheaper than creating a constant
2365 in a register. Except that subtracting -128 is more
2366 expensive than seqi to -128, so we leave that alone. */
2367 /* ??? Don't do this when comparing against symbols,
2368 otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
2369 0), which will be declared false out of hand (at least
2371 if (!(symbolic_operand (op0
, VOIDmode
)
2372 || (REG_P (op0
) && REG_POINTER (op0
))))
2374 /* To compare against MIN_INT, we add MIN_INT and check
2377 if (n
!= -2147483647 - 1)
2382 op0
= force_reg (SImode
, op0
);
2383 temp
= gen_reg_rtx (SImode
);
2384 emit_insn (gen_addsi3 (temp
, op0
, gen_int_si (add
)));
2385 return gen_rtx_fmt_ee (reverse_condition (branch_code
),
2386 VOIDmode
, temp
, const0_rtx
);
2396 /* Change ((unsigned)x < 0x1000) into !((unsigned)x >> 12),
2399 int first
= exact_log2 (code
== LTU
? n
: n
+ 1);
2402 op0
= force_reg (SImode
, op0
);
2403 temp
= gen_reg_rtx (SImode
);
2404 emit_move_insn (temp
,
2405 gen_rtx_LSHIFTRT (SImode
, op0
,
2406 gen_int_si (first
)));
2407 return gen_rtx_fmt_ee (reverse_condition (branch_code
),
2408 VOIDmode
, temp
, const0_rtx
);
2418 /* Compute a flag saying whether we should branch. */
2419 temp
= gen_reg_rtx (SImode
);
2420 tilepro_emit_setcc_internal (temp
, code
, op0
, op1
, cmp_mode
);
2422 /* Return the branch comparison. */
2423 return gen_rtx_fmt_ee (branch_code
, VOIDmode
, temp
, const0_rtx
);
2427 /* Generate the comparison for a conditional branch. */
2429 tilepro_emit_conditional_branch (rtx operands
[], machine_mode cmp_mode
)
2432 tilepro_emit_cc_test (GET_CODE (operands
[0]), operands
[1], operands
[2],
2434 rtx branch_rtx
= gen_rtx_SET (VOIDmode
, pc_rtx
,
2435 gen_rtx_IF_THEN_ELSE (VOIDmode
, cmp_rtx
,
2440 emit_jump_insn (branch_rtx
);
2444 /* Implement the movsicc pattern. */
2446 tilepro_emit_conditional_move (rtx cmp
)
2449 tilepro_emit_cc_test (GET_CODE (cmp
), XEXP (cmp
, 0), XEXP (cmp
, 1),
2450 GET_MODE (XEXP (cmp
, 0)), true);
2454 /* Return true if INSN is annotated with a REG_BR_PROB note that
2455 indicates it's a branch that's predicted taken. */
2457 cbranch_predicted_p (rtx_insn
*insn
)
2459 rtx x
= find_reg_note (insn
, REG_BR_PROB
, 0);
2463 int pred_val
= XINT (x
, 0);
2465 return pred_val
>= REG_BR_PROB_BASE
/ 2;
2472 /* Output assembly code for a specific branch instruction, appending
2473 the branch prediction flag to the opcode if appropriate. */
2475 tilepro_output_simple_cbranch_with_opcode (rtx_insn
*insn
, const char *opcode
,
2476 int regop
, bool netreg_p
,
2477 bool reverse_predicted
)
2479 static char buf
[64];
2480 sprintf (buf
, "%s%s\t%%%c%d, %%l0", opcode
,
2481 (cbranch_predicted_p (insn
) ^ reverse_predicted
) ? "t" : "",
2482 netreg_p
? 'N' : 'r', regop
);
2487 /* Output assembly code for a specific branch instruction, appending
2488 the branch prediction flag to the opcode if appropriate. */
2490 tilepro_output_cbranch_with_opcode (rtx_insn
*insn
, rtx
*operands
,
2492 const char *rev_opcode
,
2493 int regop
, bool netreg_p
)
2495 const char *branch_if_false
;
2496 rtx taken
, not_taken
;
2497 bool is_simple_branch
;
2499 gcc_assert (LABEL_P (operands
[0]));
2501 is_simple_branch
= true;
2502 if (INSN_ADDRESSES_SET_P ())
2504 int from_addr
= INSN_ADDRESSES (INSN_UID (insn
));
2505 int to_addr
= INSN_ADDRESSES (INSN_UID (operands
[0]));
2506 int delta
= to_addr
- from_addr
;
2507 is_simple_branch
= IN_RANGE (delta
, -524288, 524280);
2510 if (is_simple_branch
)
2512 /* Just a simple conditional branch. */
2514 tilepro_output_simple_cbranch_with_opcode (insn
, opcode
, regop
,
2518 /* Generate a reversed branch around a direct jump. This fallback
2519 does not use branch-likely instructions. */
2520 not_taken
= gen_label_rtx ();
2521 taken
= operands
[0];
2523 /* Generate the reversed branch to NOT_TAKEN. */
2524 operands
[0] = not_taken
;
2526 tilepro_output_simple_cbranch_with_opcode (insn
, rev_opcode
, regop
,
2528 output_asm_insn (branch_if_false
, operands
);
2530 output_asm_insn ("j\t%l0", &taken
);
2532 /* Output NOT_TAKEN. */
2533 targetm
.asm_out
.internal_label (asm_out_file
, "L",
2534 CODE_LABEL_NUMBER (not_taken
));
2539 /* Output assembly code for a conditional branch instruction. */
2541 tilepro_output_cbranch (rtx_insn
*insn
, rtx
*operands
, bool reversed
)
2543 enum rtx_code code
= GET_CODE (operands
[1]);
2545 const char *rev_opcode
;
2548 code
= reverse_condition (code
);
2566 rev_opcode
= "blez";
2574 rev_opcode
= "bgez";
2581 tilepro_output_cbranch_with_opcode (insn
, operands
, opcode
, rev_opcode
,
2586 /* Implement the tablejump pattern. */
2588 tilepro_expand_tablejump (rtx op0
, rtx op1
)
2592 rtx table
= gen_rtx_LABEL_REF (Pmode
, op1
);
2593 rtx temp
= gen_reg_rtx (Pmode
);
2594 rtx text_label_symbol
= tilepro_text_label_symbol ();
2595 rtx text_label_rtx
= tilepro_text_label_rtx ();
2597 emit_insn (gen_addli_pcrel (temp
, text_label_rtx
,
2598 table
, text_label_symbol
));
2599 emit_insn (gen_auli_pcrel (temp
, temp
, table
, text_label_symbol
));
2600 emit_move_insn (temp
,
2601 gen_rtx_PLUS (Pmode
,
2602 convert_to_mode (Pmode
, op0
, false),
2607 emit_jump_insn (gen_tablejump_aux (op0
, op1
));
2611 /* Expand a builtin vector binary op, by calling gen function GEN with
2612 operands in the proper modes. DEST is converted to DEST_MODE, and
2613 src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE. */
2615 tilepro_expand_builtin_vector_binop (rtx (*gen
) (rtx
, rtx
, rtx
),
2616 machine_mode dest_mode
,
2618 machine_mode src_mode
,
2619 rtx src0
, rtx src1
, bool do_src1
)
2621 dest
= gen_lowpart (dest_mode
, dest
);
2623 if (src0
== const0_rtx
)
2624 src0
= CONST0_RTX (src_mode
);
2626 src0
= gen_lowpart (src_mode
, src0
);
2630 if (src1
== const0_rtx
)
2631 src1
= CONST0_RTX (src_mode
);
2633 src1
= gen_lowpart (src_mode
, src1
);
2636 emit_insn ((*gen
) (dest
, src0
, src1
));
2643 struct tile_builtin_info
2645 enum insn_code icode
;
2649 static struct tile_builtin_info tilepro_builtin_info
[TILEPRO_BUILTIN_max
] = {
2650 { CODE_FOR_addsi3
, NULL
}, /* add */
2651 { CODE_FOR_insn_addb
, NULL
}, /* addb */
2652 { CODE_FOR_insn_addbs_u
, NULL
}, /* addbs_u */
2653 { CODE_FOR_insn_addh
, NULL
}, /* addh */
2654 { CODE_FOR_insn_addhs
, NULL
}, /* addhs */
2655 { CODE_FOR_insn_addib
, NULL
}, /* addib */
2656 { CODE_FOR_insn_addih
, NULL
}, /* addih */
2657 { CODE_FOR_insn_addlis
, NULL
}, /* addlis */
2658 { CODE_FOR_ssaddsi3
, NULL
}, /* adds */
2659 { CODE_FOR_insn_adiffb_u
, NULL
}, /* adiffb_u */
2660 { CODE_FOR_insn_adiffh
, NULL
}, /* adiffh */
2661 { CODE_FOR_andsi3
, NULL
}, /* and */
2662 { CODE_FOR_insn_auli
, NULL
}, /* auli */
2663 { CODE_FOR_insn_avgb_u
, NULL
}, /* avgb_u */
2664 { CODE_FOR_insn_avgh
, NULL
}, /* avgh */
2665 { CODE_FOR_insn_bitx
, NULL
}, /* bitx */
2666 { CODE_FOR_bswapsi2
, NULL
}, /* bytex */
2667 { CODE_FOR_clzsi2
, NULL
}, /* clz */
2668 { CODE_FOR_insn_crc32_32
, NULL
}, /* crc32_32 */
2669 { CODE_FOR_insn_crc32_8
, NULL
}, /* crc32_8 */
2670 { CODE_FOR_ctzsi2
, NULL
}, /* ctz */
2671 { CODE_FOR_insn_drain
, NULL
}, /* drain */
2672 { CODE_FOR_insn_dtlbpr
, NULL
}, /* dtlbpr */
2673 { CODE_FOR_insn_dword_align
, NULL
}, /* dword_align */
2674 { CODE_FOR_insn_finv
, NULL
}, /* finv */
2675 { CODE_FOR_insn_flush
, NULL
}, /* flush */
2676 { CODE_FOR_insn_fnop
, NULL
}, /* fnop */
2677 { CODE_FOR_insn_icoh
, NULL
}, /* icoh */
2678 { CODE_FOR_insn_ill
, NULL
}, /* ill */
2679 { CODE_FOR_insn_info
, NULL
}, /* info */
2680 { CODE_FOR_insn_infol
, NULL
}, /* infol */
2681 { CODE_FOR_insn_inthb
, NULL
}, /* inthb */
2682 { CODE_FOR_insn_inthh
, NULL
}, /* inthh */
2683 { CODE_FOR_insn_intlb
, NULL
}, /* intlb */
2684 { CODE_FOR_insn_intlh
, NULL
}, /* intlh */
2685 { CODE_FOR_insn_inv
, NULL
}, /* inv */
2686 { CODE_FOR_insn_lb
, NULL
}, /* lb */
2687 { CODE_FOR_insn_lb_u
, NULL
}, /* lb_u */
2688 { CODE_FOR_insn_lh
, NULL
}, /* lh */
2689 { CODE_FOR_insn_lh_u
, NULL
}, /* lh_u */
2690 { CODE_FOR_insn_lnk
, NULL
}, /* lnk */
2691 { CODE_FOR_insn_lw
, NULL
}, /* lw */
2692 { CODE_FOR_insn_lw_na
, NULL
}, /* lw_na */
2693 { CODE_FOR_insn_lb_L2
, NULL
}, /* lb_L2 */
2694 { CODE_FOR_insn_lb_u_L2
, NULL
}, /* lb_u_L2 */
2695 { CODE_FOR_insn_lh_L2
, NULL
}, /* lh_L2 */
2696 { CODE_FOR_insn_lh_u_L2
, NULL
}, /* lh_u_L2 */
2697 { CODE_FOR_insn_lw_L2
, NULL
}, /* lw_L2 */
2698 { CODE_FOR_insn_lw_na_L2
, NULL
}, /* lw_na_L2 */
2699 { CODE_FOR_insn_lb_miss
, NULL
}, /* lb_miss */
2700 { CODE_FOR_insn_lb_u_miss
, NULL
}, /* lb_u_miss */
2701 { CODE_FOR_insn_lh_miss
, NULL
}, /* lh_miss */
2702 { CODE_FOR_insn_lh_u_miss
, NULL
}, /* lh_u_miss */
2703 { CODE_FOR_insn_lw_miss
, NULL
}, /* lw_miss */
2704 { CODE_FOR_insn_lw_na_miss
, NULL
}, /* lw_na_miss */
2705 { CODE_FOR_insn_maxb_u
, NULL
}, /* maxb_u */
2706 { CODE_FOR_insn_maxh
, NULL
}, /* maxh */
2707 { CODE_FOR_insn_maxib_u
, NULL
}, /* maxib_u */
2708 { CODE_FOR_insn_maxih
, NULL
}, /* maxih */
2709 { CODE_FOR_memory_barrier
, NULL
}, /* mf */
2710 { CODE_FOR_insn_mfspr
, NULL
}, /* mfspr */
2711 { CODE_FOR_insn_minb_u
, NULL
}, /* minb_u */
2712 { CODE_FOR_insn_minh
, NULL
}, /* minh */
2713 { CODE_FOR_insn_minib_u
, NULL
}, /* minib_u */
2714 { CODE_FOR_insn_minih
, NULL
}, /* minih */
2715 { CODE_FOR_insn_mm
, NULL
}, /* mm */
2716 { CODE_FOR_insn_mnz
, NULL
}, /* mnz */
2717 { CODE_FOR_insn_mnzb
, NULL
}, /* mnzb */
2718 { CODE_FOR_insn_mnzh
, NULL
}, /* mnzh */
2719 { CODE_FOR_movsi
, NULL
}, /* move */
2720 { CODE_FOR_insn_movelis
, NULL
}, /* movelis */
2721 { CODE_FOR_insn_mtspr
, NULL
}, /* mtspr */
2722 { CODE_FOR_insn_mulhh_ss
, NULL
}, /* mulhh_ss */
2723 { CODE_FOR_insn_mulhh_su
, NULL
}, /* mulhh_su */
2724 { CODE_FOR_insn_mulhh_uu
, NULL
}, /* mulhh_uu */
2725 { CODE_FOR_insn_mulhha_ss
, NULL
}, /* mulhha_ss */
2726 { CODE_FOR_insn_mulhha_su
, NULL
}, /* mulhha_su */
2727 { CODE_FOR_insn_mulhha_uu
, NULL
}, /* mulhha_uu */
2728 { CODE_FOR_insn_mulhhsa_uu
, NULL
}, /* mulhhsa_uu */
2729 { CODE_FOR_insn_mulhl_ss
, NULL
}, /* mulhl_ss */
2730 { CODE_FOR_insn_mulhl_su
, NULL
}, /* mulhl_su */
2731 { CODE_FOR_insn_mulhl_us
, NULL
}, /* mulhl_us */
2732 { CODE_FOR_insn_mulhl_uu
, NULL
}, /* mulhl_uu */
2733 { CODE_FOR_insn_mulhla_ss
, NULL
}, /* mulhla_ss */
2734 { CODE_FOR_insn_mulhla_su
, NULL
}, /* mulhla_su */
2735 { CODE_FOR_insn_mulhla_us
, NULL
}, /* mulhla_us */
2736 { CODE_FOR_insn_mulhla_uu
, NULL
}, /* mulhla_uu */
2737 { CODE_FOR_insn_mulhlsa_uu
, NULL
}, /* mulhlsa_uu */
2738 { CODE_FOR_insn_mulll_ss
, NULL
}, /* mulll_ss */
2739 { CODE_FOR_insn_mulll_su
, NULL
}, /* mulll_su */
2740 { CODE_FOR_insn_mulll_uu
, NULL
}, /* mulll_uu */
2741 { CODE_FOR_insn_mullla_ss
, NULL
}, /* mullla_ss */
2742 { CODE_FOR_insn_mullla_su
, NULL
}, /* mullla_su */
2743 { CODE_FOR_insn_mullla_uu
, NULL
}, /* mullla_uu */
2744 { CODE_FOR_insn_mulllsa_uu
, NULL
}, /* mulllsa_uu */
2745 { CODE_FOR_insn_mvnz
, NULL
}, /* mvnz */
2746 { CODE_FOR_insn_mvz
, NULL
}, /* mvz */
2747 { CODE_FOR_insn_mz
, NULL
}, /* mz */
2748 { CODE_FOR_insn_mzb
, NULL
}, /* mzb */
2749 { CODE_FOR_insn_mzh
, NULL
}, /* mzh */
2750 { CODE_FOR_insn_nap
, NULL
}, /* nap */
2751 { CODE_FOR_nop
, NULL
}, /* nop */
2752 { CODE_FOR_insn_nor
, NULL
}, /* nor */
2753 { CODE_FOR_iorsi3
, NULL
}, /* or */
2754 { CODE_FOR_insn_packbs_u
, NULL
}, /* packbs_u */
2755 { CODE_FOR_insn_packhb
, NULL
}, /* packhb */
2756 { CODE_FOR_insn_packhs
, NULL
}, /* packhs */
2757 { CODE_FOR_insn_packlb
, NULL
}, /* packlb */
2758 { CODE_FOR_popcountsi2
, NULL
}, /* pcnt */
2759 { CODE_FOR_insn_prefetch
, NULL
}, /* prefetch */
2760 { CODE_FOR_insn_prefetch_L1
, NULL
}, /* prefetch_L1 */
2761 { CODE_FOR_rotlsi3
, NULL
}, /* rl */
2762 { CODE_FOR_insn_s1a
, NULL
}, /* s1a */
2763 { CODE_FOR_insn_s2a
, NULL
}, /* s2a */
2764 { CODE_FOR_insn_s3a
, NULL
}, /* s3a */
2765 { CODE_FOR_insn_sadab_u
, NULL
}, /* sadab_u */
2766 { CODE_FOR_insn_sadah
, NULL
}, /* sadah */
2767 { CODE_FOR_insn_sadah_u
, NULL
}, /* sadah_u */
2768 { CODE_FOR_insn_sadb_u
, NULL
}, /* sadb_u */
2769 { CODE_FOR_insn_sadh
, NULL
}, /* sadh */
2770 { CODE_FOR_insn_sadh_u
, NULL
}, /* sadh_u */
2771 { CODE_FOR_insn_sb
, NULL
}, /* sb */
2772 { CODE_FOR_insn_seq
, NULL
}, /* seq */
2773 { CODE_FOR_insn_seqb
, NULL
}, /* seqb */
2774 { CODE_FOR_insn_seqh
, NULL
}, /* seqh */
2775 { CODE_FOR_insn_seqib
, NULL
}, /* seqib */
2776 { CODE_FOR_insn_seqih
, NULL
}, /* seqih */
2777 { CODE_FOR_insn_sh
, NULL
}, /* sh */
2778 { CODE_FOR_ashlsi3
, NULL
}, /* shl */
2779 { CODE_FOR_insn_shlb
, NULL
}, /* shlb */
2780 { CODE_FOR_insn_shlh
, NULL
}, /* shlh */
2781 { CODE_FOR_insn_shlb
, NULL
}, /* shlib */
2782 { CODE_FOR_insn_shlh
, NULL
}, /* shlih */
2783 { CODE_FOR_lshrsi3
, NULL
}, /* shr */
2784 { CODE_FOR_insn_shrb
, NULL
}, /* shrb */
2785 { CODE_FOR_insn_shrh
, NULL
}, /* shrh */
2786 { CODE_FOR_insn_shrb
, NULL
}, /* shrib */
2787 { CODE_FOR_insn_shrh
, NULL
}, /* shrih */
2788 { CODE_FOR_insn_slt
, NULL
}, /* slt */
2789 { CODE_FOR_insn_slt_u
, NULL
}, /* slt_u */
2790 { CODE_FOR_insn_sltb
, NULL
}, /* sltb */
2791 { CODE_FOR_insn_sltb_u
, NULL
}, /* sltb_u */
2792 { CODE_FOR_insn_slte
, NULL
}, /* slte */
2793 { CODE_FOR_insn_slte_u
, NULL
}, /* slte_u */
2794 { CODE_FOR_insn_slteb
, NULL
}, /* slteb */
2795 { CODE_FOR_insn_slteb_u
, NULL
}, /* slteb_u */
2796 { CODE_FOR_insn_slteh
, NULL
}, /* slteh */
2797 { CODE_FOR_insn_slteh_u
, NULL
}, /* slteh_u */
2798 { CODE_FOR_insn_slth
, NULL
}, /* slth */
2799 { CODE_FOR_insn_slth_u
, NULL
}, /* slth_u */
2800 { CODE_FOR_insn_sltib
, NULL
}, /* sltib */
2801 { CODE_FOR_insn_sltib_u
, NULL
}, /* sltib_u */
2802 { CODE_FOR_insn_sltih
, NULL
}, /* sltih */
2803 { CODE_FOR_insn_sltih_u
, NULL
}, /* sltih_u */
2804 { CODE_FOR_insn_sne
, NULL
}, /* sne */
2805 { CODE_FOR_insn_sneb
, NULL
}, /* sneb */
2806 { CODE_FOR_insn_sneh
, NULL
}, /* sneh */
2807 { CODE_FOR_ashrsi3
, NULL
}, /* sra */
2808 { CODE_FOR_insn_srab
, NULL
}, /* srab */
2809 { CODE_FOR_insn_srah
, NULL
}, /* srah */
2810 { CODE_FOR_insn_srab
, NULL
}, /* sraib */
2811 { CODE_FOR_insn_srah
, NULL
}, /* sraih */
2812 { CODE_FOR_subsi3
, NULL
}, /* sub */
2813 { CODE_FOR_insn_subb
, NULL
}, /* subb */
2814 { CODE_FOR_insn_subbs_u
, NULL
}, /* subbs_u */
2815 { CODE_FOR_insn_subh
, NULL
}, /* subh */
2816 { CODE_FOR_insn_subhs
, NULL
}, /* subhs */
2817 { CODE_FOR_sssubsi3
, NULL
}, /* subs */
2818 { CODE_FOR_insn_sw
, NULL
}, /* sw */
2819 { CODE_FOR_insn_tblidxb0
, NULL
}, /* tblidxb0 */
2820 { CODE_FOR_insn_tblidxb1
, NULL
}, /* tblidxb1 */
2821 { CODE_FOR_insn_tblidxb2
, NULL
}, /* tblidxb2 */
2822 { CODE_FOR_insn_tblidxb3
, NULL
}, /* tblidxb3 */
2823 { CODE_FOR_insn_tns
, NULL
}, /* tns */
2824 { CODE_FOR_insn_wh64
, NULL
}, /* wh64 */
2825 { CODE_FOR_xorsi3
, NULL
}, /* xor */
2826 { CODE_FOR_tilepro_network_barrier
, NULL
}, /* network_barrier */
2827 { CODE_FOR_tilepro_idn0_receive
, NULL
}, /* idn0_receive */
2828 { CODE_FOR_tilepro_idn1_receive
, NULL
}, /* idn1_receive */
2829 { CODE_FOR_tilepro_idn_send
, NULL
}, /* idn_send */
2830 { CODE_FOR_tilepro_sn_receive
, NULL
}, /* sn_receive */
2831 { CODE_FOR_tilepro_sn_send
, NULL
}, /* sn_send */
2832 { CODE_FOR_tilepro_udn0_receive
, NULL
}, /* udn0_receive */
2833 { CODE_FOR_tilepro_udn1_receive
, NULL
}, /* udn1_receive */
2834 { CODE_FOR_tilepro_udn2_receive
, NULL
}, /* udn2_receive */
2835 { CODE_FOR_tilepro_udn3_receive
, NULL
}, /* udn3_receive */
2836 { CODE_FOR_tilepro_udn_send
, NULL
}, /* udn_send */
2840 struct tilepro_builtin_def
2843 enum tilepro_builtin code
;
2845 /* The first character is the return type. Subsequent characters
2846 are the argument types. See char_to_type. */
2851 static const struct tilepro_builtin_def tilepro_builtins
[] = {
2852 { "__insn_add", TILEPRO_INSN_ADD
, true, "lll" },
2853 { "__insn_addb", TILEPRO_INSN_ADDB
, true, "lll" },
2854 { "__insn_addbs_u", TILEPRO_INSN_ADDBS_U
, false, "lll" },
2855 { "__insn_addh", TILEPRO_INSN_ADDH
, true, "lll" },
2856 { "__insn_addhs", TILEPRO_INSN_ADDHS
, false, "lll" },
2857 { "__insn_addi", TILEPRO_INSN_ADD
, true, "lll" },
2858 { "__insn_addib", TILEPRO_INSN_ADDIB
, true, "lll" },
2859 { "__insn_addih", TILEPRO_INSN_ADDIH
, true, "lll" },
2860 { "__insn_addli", TILEPRO_INSN_ADD
, true, "lll" },
2861 { "__insn_addlis", TILEPRO_INSN_ADDLIS
, false, "lll" },
2862 { "__insn_adds", TILEPRO_INSN_ADDS
, false, "lll" },
2863 { "__insn_adiffb_u", TILEPRO_INSN_ADIFFB_U
, true, "lll" },
2864 { "__insn_adiffh", TILEPRO_INSN_ADIFFH
, true, "lll" },
2865 { "__insn_and", TILEPRO_INSN_AND
, true, "lll" },
2866 { "__insn_andi", TILEPRO_INSN_AND
, true, "lll" },
2867 { "__insn_auli", TILEPRO_INSN_AULI
, true, "lll" },
2868 { "__insn_avgb_u", TILEPRO_INSN_AVGB_U
, true, "lll" },
2869 { "__insn_avgh", TILEPRO_INSN_AVGH
, true, "lll" },
2870 { "__insn_bitx", TILEPRO_INSN_BITX
, true, "ll" },
2871 { "__insn_bytex", TILEPRO_INSN_BYTEX
, true, "ll" },
2872 { "__insn_clz", TILEPRO_INSN_CLZ
, true, "ll" },
2873 { "__insn_crc32_32", TILEPRO_INSN_CRC32_32
, true, "lll" },
2874 { "__insn_crc32_8", TILEPRO_INSN_CRC32_8
, true, "lll" },
2875 { "__insn_ctz", TILEPRO_INSN_CTZ
, true, "ll" },
2876 { "__insn_drain", TILEPRO_INSN_DRAIN
, false, "v" },
2877 { "__insn_dtlbpr", TILEPRO_INSN_DTLBPR
, false, "vl" },
2878 { "__insn_dword_align", TILEPRO_INSN_DWORD_ALIGN
, true, "lllk" },
2879 { "__insn_finv", TILEPRO_INSN_FINV
, false, "vk" },
2880 { "__insn_flush", TILEPRO_INSN_FLUSH
, false, "vk" },
2881 { "__insn_fnop", TILEPRO_INSN_FNOP
, false, "v" },
2882 { "__insn_icoh", TILEPRO_INSN_ICOH
, false, "vk" },
2883 { "__insn_ill", TILEPRO_INSN_ILL
, false, "v" },
2884 { "__insn_info", TILEPRO_INSN_INFO
, false, "vl" },
2885 { "__insn_infol", TILEPRO_INSN_INFOL
, false, "vl" },
2886 { "__insn_inthb", TILEPRO_INSN_INTHB
, true, "lll" },
2887 { "__insn_inthh", TILEPRO_INSN_INTHH
, true, "lll" },
2888 { "__insn_intlb", TILEPRO_INSN_INTLB
, true, "lll" },
2889 { "__insn_intlh", TILEPRO_INSN_INTLH
, true, "lll" },
2890 { "__insn_inv", TILEPRO_INSN_INV
, false, "vp" },
2891 { "__insn_lb", TILEPRO_INSN_LB
, false, "lk" },
2892 { "__insn_lb_u", TILEPRO_INSN_LB_U
, false, "lk" },
2893 { "__insn_lh", TILEPRO_INSN_LH
, false, "lk" },
2894 { "__insn_lh_u", TILEPRO_INSN_LH_U
, false, "lk" },
2895 { "__insn_lnk", TILEPRO_INSN_LNK
, true, "l" },
2896 { "__insn_lw", TILEPRO_INSN_LW
, false, "lk" },
2897 { "__insn_lw_na", TILEPRO_INSN_LW_NA
, false, "lk" },
2898 { "__insn_lb_L2", TILEPRO_INSN_LB_L2
, false, "lk" },
2899 { "__insn_lb_u_L2", TILEPRO_INSN_LB_U_L2
, false, "lk" },
2900 { "__insn_lh_L2", TILEPRO_INSN_LH_L2
, false, "lk" },
2901 { "__insn_lh_u_L2", TILEPRO_INSN_LH_U_L2
, false, "lk" },
2902 { "__insn_lw_L2", TILEPRO_INSN_LW_L2
, false, "lk" },
2903 { "__insn_lw_na_L2", TILEPRO_INSN_LW_NA_L2
, false, "lk" },
2904 { "__insn_lb_miss", TILEPRO_INSN_LB_MISS
, false, "lk" },
2905 { "__insn_lb_u_miss", TILEPRO_INSN_LB_U_MISS
, false, "lk" },
2906 { "__insn_lh_miss", TILEPRO_INSN_LH_MISS
, false, "lk" },
2907 { "__insn_lh_u_miss", TILEPRO_INSN_LH_U_MISS
, false, "lk" },
2908 { "__insn_lw_miss", TILEPRO_INSN_LW_MISS
, false, "lk" },
2909 { "__insn_lw_na_miss", TILEPRO_INSN_LW_NA_MISS
, false, "lk" },
2910 { "__insn_maxb_u", TILEPRO_INSN_MAXB_U
, true, "lll" },
2911 { "__insn_maxh", TILEPRO_INSN_MAXH
, true, "lll" },
2912 { "__insn_maxib_u", TILEPRO_INSN_MAXIB_U
, true, "lll" },
2913 { "__insn_maxih", TILEPRO_INSN_MAXIH
, true, "lll" },
2914 { "__insn_mf", TILEPRO_INSN_MF
, false, "v" },
2915 { "__insn_mfspr", TILEPRO_INSN_MFSPR
, false, "ll" },
2916 { "__insn_minb_u", TILEPRO_INSN_MINB_U
, true, "lll" },
2917 { "__insn_minh", TILEPRO_INSN_MINH
, true, "lll" },
2918 { "__insn_minib_u", TILEPRO_INSN_MINIB_U
, true, "lll" },
2919 { "__insn_minih", TILEPRO_INSN_MINIH
, true, "lll" },
2920 { "__insn_mm", TILEPRO_INSN_MM
, true, "lllll" },
2921 { "__insn_mnz", TILEPRO_INSN_MNZ
, true, "lll" },
2922 { "__insn_mnzb", TILEPRO_INSN_MNZB
, true, "lll" },
2923 { "__insn_mnzh", TILEPRO_INSN_MNZH
, true, "lll" },
2924 { "__insn_move", TILEPRO_INSN_MOVE
, true, "ll" },
2925 { "__insn_movei", TILEPRO_INSN_MOVE
, true, "ll" },
2926 { "__insn_moveli", TILEPRO_INSN_MOVE
, true, "ll" },
2927 { "__insn_movelis", TILEPRO_INSN_MOVELIS
, false, "ll" },
2928 { "__insn_mtspr", TILEPRO_INSN_MTSPR
, false, "vll" },
2929 { "__insn_mulhh_ss", TILEPRO_INSN_MULHH_SS
, true, "lll" },
2930 { "__insn_mulhh_su", TILEPRO_INSN_MULHH_SU
, true, "lll" },
2931 { "__insn_mulhh_uu", TILEPRO_INSN_MULHH_UU
, true, "lll" },
2932 { "__insn_mulhha_ss", TILEPRO_INSN_MULHHA_SS
, true, "llll" },
2933 { "__insn_mulhha_su", TILEPRO_INSN_MULHHA_SU
, true, "llll" },
2934 { "__insn_mulhha_uu", TILEPRO_INSN_MULHHA_UU
, true, "llll" },
2935 { "__insn_mulhhsa_uu", TILEPRO_INSN_MULHHSA_UU
, true, "llll" },
2936 { "__insn_mulhl_ss", TILEPRO_INSN_MULHL_SS
, true, "lll" },
2937 { "__insn_mulhl_su", TILEPRO_INSN_MULHL_SU
, true, "lll" },
2938 { "__insn_mulhl_us", TILEPRO_INSN_MULHL_US
, true, "lll" },
2939 { "__insn_mulhl_uu", TILEPRO_INSN_MULHL_UU
, true, "lll" },
2940 { "__insn_mulhla_ss", TILEPRO_INSN_MULHLA_SS
, true, "llll" },
2941 { "__insn_mulhla_su", TILEPRO_INSN_MULHLA_SU
, true, "llll" },
2942 { "__insn_mulhla_us", TILEPRO_INSN_MULHLA_US
, true, "llll" },
2943 { "__insn_mulhla_uu", TILEPRO_INSN_MULHLA_UU
, true, "llll" },
2944 { "__insn_mulhlsa_uu", TILEPRO_INSN_MULHLSA_UU
, true, "llll" },
2945 { "__insn_mulll_ss", TILEPRO_INSN_MULLL_SS
, true, "lll" },
2946 { "__insn_mulll_su", TILEPRO_INSN_MULLL_SU
, true, "lll" },
2947 { "__insn_mulll_uu", TILEPRO_INSN_MULLL_UU
, true, "lll" },
2948 { "__insn_mullla_ss", TILEPRO_INSN_MULLLA_SS
, true, "llll" },
2949 { "__insn_mullla_su", TILEPRO_INSN_MULLLA_SU
, true, "llll" },
2950 { "__insn_mullla_uu", TILEPRO_INSN_MULLLA_UU
, true, "llll" },
2951 { "__insn_mulllsa_uu", TILEPRO_INSN_MULLLSA_UU
, true, "llll" },
2952 { "__insn_mvnz", TILEPRO_INSN_MVNZ
, true, "llll" },
2953 { "__insn_mvz", TILEPRO_INSN_MVZ
, true, "llll" },
2954 { "__insn_mz", TILEPRO_INSN_MZ
, true, "lll" },
2955 { "__insn_mzb", TILEPRO_INSN_MZB
, true, "lll" },
2956 { "__insn_mzh", TILEPRO_INSN_MZH
, true, "lll" },
2957 { "__insn_nap", TILEPRO_INSN_NAP
, false, "v" },
2958 { "__insn_nop", TILEPRO_INSN_NOP
, true, "v" },
2959 { "__insn_nor", TILEPRO_INSN_NOR
, true, "lll" },
2960 { "__insn_or", TILEPRO_INSN_OR
, true, "lll" },
2961 { "__insn_ori", TILEPRO_INSN_OR
, true, "lll" },
2962 { "__insn_packbs_u", TILEPRO_INSN_PACKBS_U
, false, "lll" },
2963 { "__insn_packhb", TILEPRO_INSN_PACKHB
, true, "lll" },
2964 { "__insn_packhs", TILEPRO_INSN_PACKHS
, false, "lll" },
2965 { "__insn_packlb", TILEPRO_INSN_PACKLB
, true, "lll" },
2966 { "__insn_pcnt", TILEPRO_INSN_PCNT
, true, "ll" },
2967 { "__insn_prefetch", TILEPRO_INSN_PREFETCH
, false, "vk" },
2968 { "__insn_prefetch_L1", TILEPRO_INSN_PREFETCH_L1
, false, "vk" },
2969 { "__insn_rl", TILEPRO_INSN_RL
, true, "lll" },
2970 { "__insn_rli", TILEPRO_INSN_RL
, true, "lll" },
2971 { "__insn_s1a", TILEPRO_INSN_S1A
, true, "lll" },
2972 { "__insn_s2a", TILEPRO_INSN_S2A
, true, "lll" },
2973 { "__insn_s3a", TILEPRO_INSN_S3A
, true, "lll" },
2974 { "__insn_sadab_u", TILEPRO_INSN_SADAB_U
, true, "llll" },
2975 { "__insn_sadah", TILEPRO_INSN_SADAH
, true, "llll" },
2976 { "__insn_sadah_u", TILEPRO_INSN_SADAH_U
, true, "llll" },
2977 { "__insn_sadb_u", TILEPRO_INSN_SADB_U
, true, "lll" },
2978 { "__insn_sadh", TILEPRO_INSN_SADH
, true, "lll" },
2979 { "__insn_sadh_u", TILEPRO_INSN_SADH_U
, true, "lll" },
2980 { "__insn_sb", TILEPRO_INSN_SB
, false, "vpl" },
2981 { "__insn_seq", TILEPRO_INSN_SEQ
, true, "lll" },
2982 { "__insn_seqb", TILEPRO_INSN_SEQB
, true, "lll" },
2983 { "__insn_seqh", TILEPRO_INSN_SEQH
, true, "lll" },
2984 { "__insn_seqi", TILEPRO_INSN_SEQ
, true, "lll" },
2985 { "__insn_seqib", TILEPRO_INSN_SEQIB
, true, "lll" },
2986 { "__insn_seqih", TILEPRO_INSN_SEQIH
, true, "lll" },
2987 { "__insn_sh", TILEPRO_INSN_SH
, false, "vpl" },
2988 { "__insn_shl", TILEPRO_INSN_SHL
, true, "lll" },
2989 { "__insn_shlb", TILEPRO_INSN_SHLB
, true, "lll" },
2990 { "__insn_shlh", TILEPRO_INSN_SHLH
, true, "lll" },
2991 { "__insn_shli", TILEPRO_INSN_SHL
, true, "lll" },
2992 { "__insn_shlib", TILEPRO_INSN_SHLIB
, true, "lll" },
2993 { "__insn_shlih", TILEPRO_INSN_SHLIH
, true, "lll" },
2994 { "__insn_shr", TILEPRO_INSN_SHR
, true, "lll" },
2995 { "__insn_shrb", TILEPRO_INSN_SHRB
, true, "lll" },
2996 { "__insn_shrh", TILEPRO_INSN_SHRH
, true, "lll" },
2997 { "__insn_shri", TILEPRO_INSN_SHR
, true, "lll" },
2998 { "__insn_shrib", TILEPRO_INSN_SHRIB
, true, "lll" },
2999 { "__insn_shrih", TILEPRO_INSN_SHRIH
, true, "lll" },
3000 { "__insn_slt", TILEPRO_INSN_SLT
, true, "lll" },
3001 { "__insn_slt_u", TILEPRO_INSN_SLT_U
, true, "lll" },
3002 { "__insn_sltb", TILEPRO_INSN_SLTB
, true, "lll" },
3003 { "__insn_sltb_u", TILEPRO_INSN_SLTB_U
, true, "lll" },
3004 { "__insn_slte", TILEPRO_INSN_SLTE
, true, "lll" },
3005 { "__insn_slte_u", TILEPRO_INSN_SLTE_U
, true, "lll" },
3006 { "__insn_slteb", TILEPRO_INSN_SLTEB
, true, "lll" },
3007 { "__insn_slteb_u", TILEPRO_INSN_SLTEB_U
, true, "lll" },
3008 { "__insn_slteh", TILEPRO_INSN_SLTEH
, true, "lll" },
3009 { "__insn_slteh_u", TILEPRO_INSN_SLTEH_U
, true, "lll" },
3010 { "__insn_slth", TILEPRO_INSN_SLTH
, true, "lll" },
3011 { "__insn_slth_u", TILEPRO_INSN_SLTH_U
, true, "lll" },
3012 { "__insn_slti", TILEPRO_INSN_SLT
, true, "lll" },
3013 { "__insn_slti_u", TILEPRO_INSN_SLT_U
, true, "lll" },
3014 { "__insn_sltib", TILEPRO_INSN_SLTIB
, true, "lll" },
3015 { "__insn_sltib_u", TILEPRO_INSN_SLTIB_U
, true, "lll" },
3016 { "__insn_sltih", TILEPRO_INSN_SLTIH
, true, "lll" },
3017 { "__insn_sltih_u", TILEPRO_INSN_SLTIH_U
, true, "lll" },
3018 { "__insn_sne", TILEPRO_INSN_SNE
, true, "lll" },
3019 { "__insn_sneb", TILEPRO_INSN_SNEB
, true, "lll" },
3020 { "__insn_sneh", TILEPRO_INSN_SNEH
, true, "lll" },
3021 { "__insn_sra", TILEPRO_INSN_SRA
, true, "lll" },
3022 { "__insn_srab", TILEPRO_INSN_SRAB
, true, "lll" },
3023 { "__insn_srah", TILEPRO_INSN_SRAH
, true, "lll" },
3024 { "__insn_srai", TILEPRO_INSN_SRA
, true, "lll" },
3025 { "__insn_sraib", TILEPRO_INSN_SRAIB
, true, "lll" },
3026 { "__insn_sraih", TILEPRO_INSN_SRAIH
, true, "lll" },
3027 { "__insn_sub", TILEPRO_INSN_SUB
, true, "lll" },
3028 { "__insn_subb", TILEPRO_INSN_SUBB
, true, "lll" },
3029 { "__insn_subbs_u", TILEPRO_INSN_SUBBS_U
, false, "lll" },
3030 { "__insn_subh", TILEPRO_INSN_SUBH
, true, "lll" },
3031 { "__insn_subhs", TILEPRO_INSN_SUBHS
, false, "lll" },
3032 { "__insn_subs", TILEPRO_INSN_SUBS
, false, "lll" },
3033 { "__insn_sw", TILEPRO_INSN_SW
, false, "vpl" },
3034 { "__insn_tblidxb0", TILEPRO_INSN_TBLIDXB0
, true, "lll" },
3035 { "__insn_tblidxb1", TILEPRO_INSN_TBLIDXB1
, true, "lll" },
3036 { "__insn_tblidxb2", TILEPRO_INSN_TBLIDXB2
, true, "lll" },
3037 { "__insn_tblidxb3", TILEPRO_INSN_TBLIDXB3
, true, "lll" },
3038 { "__insn_tns", TILEPRO_INSN_TNS
, false, "lp" },
3039 { "__insn_wh64", TILEPRO_INSN_WH64
, false, "vp" },
3040 { "__insn_xor", TILEPRO_INSN_XOR
, true, "lll" },
3041 { "__insn_xori", TILEPRO_INSN_XOR
, true, "lll" },
3042 { "__tile_network_barrier", TILEPRO_NETWORK_BARRIER
, false, "v" },
3043 { "__tile_idn0_receive", TILEPRO_IDN0_RECEIVE
, false, "l" },
3044 { "__tile_idn1_receive", TILEPRO_IDN1_RECEIVE
, false, "l" },
3045 { "__tile_idn_send", TILEPRO_IDN_SEND
, false, "vl" },
3046 { "__tile_sn_receive", TILEPRO_SN_RECEIVE
, false, "l" },
3047 { "__tile_sn_send", TILEPRO_SN_SEND
, false, "vl" },
3048 { "__tile_udn0_receive", TILEPRO_UDN0_RECEIVE
, false, "l" },
3049 { "__tile_udn1_receive", TILEPRO_UDN1_RECEIVE
, false, "l" },
3050 { "__tile_udn2_receive", TILEPRO_UDN2_RECEIVE
, false, "l" },
3051 { "__tile_udn3_receive", TILEPRO_UDN3_RECEIVE
, false, "l" },
3052 { "__tile_udn_send", TILEPRO_UDN_SEND
, false, "vl" },
3056 /* Convert a character in a builtin type string to a tree type. */
3058 char_to_type (char c
)
3060 static tree volatile_ptr_type_node
= NULL
;
3061 static tree volatile_const_ptr_type_node
= NULL
;
3063 if (volatile_ptr_type_node
== NULL
)
3065 volatile_ptr_type_node
=
3066 build_pointer_type (build_qualified_type (void_type_node
,
3067 TYPE_QUAL_VOLATILE
));
3068 volatile_const_ptr_type_node
=
3069 build_pointer_type (build_qualified_type (void_type_node
,
3071 | TYPE_QUAL_VOLATILE
));
3077 return void_type_node
;
3079 return long_unsigned_type_node
;
3081 return volatile_ptr_type_node
;
3083 return volatile_const_ptr_type_node
;
3090 /* Implement TARGET_INIT_BUILTINS. */
3092 tilepro_init_builtins (void)
3096 for (i
= 0; i
< ARRAY_SIZE (tilepro_builtins
); i
++)
3098 const struct tilepro_builtin_def
*p
= &tilepro_builtins
[i
];
3099 tree ftype
, ret_type
, arg_type_list
= void_list_node
;
3103 for (j
= strlen (p
->type
) - 1; j
> 0; j
--)
3106 tree_cons (NULL_TREE
, char_to_type (p
->type
[j
]), arg_type_list
);
3109 ret_type
= char_to_type (p
->type
[0]);
3111 ftype
= build_function_type (ret_type
, arg_type_list
);
3113 decl
= add_builtin_function (p
->name
, ftype
, p
->code
, BUILT_IN_MD
,
3117 TREE_READONLY (decl
) = 1;
3118 TREE_NOTHROW (decl
) = 1;
3120 if (tilepro_builtin_info
[p
->code
].fndecl
== NULL
)
3121 tilepro_builtin_info
[p
->code
].fndecl
= decl
;
3126 /* Implement TARGET_EXPAND_BUILTIN. */
3128 tilepro_expand_builtin (tree exp
,
3130 rtx subtarget ATTRIBUTE_UNUSED
,
3131 machine_mode mode ATTRIBUTE_UNUSED
,
3132 int ignore ATTRIBUTE_UNUSED
)
3134 #define MAX_BUILTIN_ARGS 4
3136 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
3137 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
3139 call_expr_arg_iterator iter
;
3140 enum insn_code icode
;
3141 rtx op
[MAX_BUILTIN_ARGS
+ 1], pat
;
3146 if (fcode
>= TILEPRO_BUILTIN_max
)
3147 internal_error ("bad builtin fcode");
3148 icode
= tilepro_builtin_info
[fcode
].icode
;
3150 internal_error ("bad builtin icode");
3152 nonvoid
= TREE_TYPE (TREE_TYPE (fndecl
)) != void_type_node
;
3155 FOR_EACH_CALL_EXPR_ARG (arg
, iter
, exp
)
3157 const struct insn_operand_data
*insn_op
;
3159 if (arg
== error_mark_node
)
3161 if (opnum
> MAX_BUILTIN_ARGS
)
3164 insn_op
= &insn_data
[icode
].operand
[opnum
];
3166 op
[opnum
] = expand_expr (arg
, NULL_RTX
, insn_op
->mode
, EXPAND_NORMAL
);
3168 if (!(*insn_op
->predicate
) (op
[opnum
], insn_op
->mode
))
3169 op
[opnum
] = copy_to_mode_reg (insn_op
->mode
, op
[opnum
]);
3171 if (!(*insn_op
->predicate
) (op
[opnum
], insn_op
->mode
))
3173 /* We still failed to meet the predicate even after moving
3174 into a register. Assume we needed an immediate. */
3175 error_at (EXPR_LOCATION (exp
),
3176 "operand must be an immediate of the right size");
3185 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
3187 || GET_MODE (target
) != tmode
3188 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
3189 target
= gen_reg_rtx (tmode
);
3193 fn
= GEN_FCN (icode
);
3197 pat
= fn (NULL_RTX
);
3203 pat
= fn (op
[0], op
[1]);
3206 pat
= fn (op
[0], op
[1], op
[2]);
3209 pat
= fn (op
[0], op
[1], op
[2], op
[3]);
3212 pat
= fn (op
[0], op
[1], op
[2], op
[3], op
[4]);
3220 /* If we are generating a prefetch, tell the scheduler not to move
3222 if (GET_CODE (pat
) == PREFETCH
)
3223 PREFETCH_SCHEDULE_BARRIER_P (pat
) = true;
3234 /* Implement TARGET_BUILTIN_DECL. */
3236 tilepro_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
3238 if (code
>= TILEPRO_BUILTIN_max
)
3239 return error_mark_node
;
3241 return tilepro_builtin_info
[code
].fndecl
;
3248 /* Return whether REGNO needs to be saved in the stack frame. */
3250 need_to_save_reg (unsigned int regno
)
3252 if (!fixed_regs
[regno
] && !call_used_regs
[regno
]
3253 && df_regs_ever_live_p (regno
))
3257 && (regno
== PIC_OFFSET_TABLE_REGNUM
3258 || regno
== TILEPRO_PIC_TEXT_LABEL_REGNUM
)
3259 && (crtl
->uses_pic_offset_table
|| crtl
->saves_all_registers
))
3262 if (crtl
->calls_eh_return
)
3265 for (i
= 0; EH_RETURN_DATA_REGNO (i
) != INVALID_REGNUM
; i
++)
3267 if (regno
== EH_RETURN_DATA_REGNO (i
))
3276 /* Return the size of the register savev area. This function is only
3277 correct starting with local register allocation */
3279 tilepro_saved_regs_size (void)
3281 int reg_save_size
= 0;
3283 int offset_to_frame
;
3286 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
3287 if (need_to_save_reg (regno
))
3288 reg_save_size
+= UNITS_PER_WORD
;
3290 /* Pad out the register save area if necessary to make
3291 frame_pointer_rtx be as aligned as the stack pointer. */
3292 offset_to_frame
= crtl
->args
.pretend_args_size
+ reg_save_size
;
3293 align_mask
= (STACK_BOUNDARY
/ BITS_PER_UNIT
) - 1;
3294 reg_save_size
+= (-offset_to_frame
) & align_mask
;
3296 return reg_save_size
;
3300 /* Round up frame size SIZE. */
3302 round_frame_size (int size
)
3304 return ((size
+ STACK_BOUNDARY
/ BITS_PER_UNIT
- 1)
3305 & -STACK_BOUNDARY
/ BITS_PER_UNIT
);
3309 /* Emit a store in the stack frame to save REGNO at address ADDR, and
3310 emit the corresponding REG_CFA_OFFSET note described by CFA and
3311 CFA_OFFSET. Return the emitted insn. */
3313 frame_emit_store (int regno
, int regno_note
, rtx addr
, rtx cfa
,
3316 rtx reg
= gen_rtx_REG (Pmode
, regno
);
3317 rtx mem
= gen_frame_mem (Pmode
, addr
);
3318 rtx mov
= gen_movsi (mem
, reg
);
3320 /* Describe what just happened in a way that dwarf understands. We
3321 use temporary registers to hold the address to make scheduling
3322 easier, and use the REG_CFA_OFFSET to describe the address as an
3323 offset from the CFA. */
3324 rtx reg_note
= gen_rtx_REG (Pmode
, regno_note
);
3325 rtx cfa_relative_addr
= gen_rtx_PLUS (Pmode
, cfa
, gen_int_si (cfa_offset
));
3326 rtx cfa_relative_mem
= gen_frame_mem (Pmode
, cfa_relative_addr
);
3327 rtx real
= gen_rtx_SET (VOIDmode
, cfa_relative_mem
, reg_note
);
3328 add_reg_note (mov
, REG_CFA_OFFSET
, real
);
3330 return emit_insn (mov
);
3334 /* Emit a load in the stack frame to load REGNO from address ADDR.
3335 Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
3336 non-null. Return the emitted insn. */
3338 frame_emit_load (int regno
, rtx addr
, rtx
*cfa_restores
)
3340 rtx reg
= gen_rtx_REG (Pmode
, regno
);
3341 rtx mem
= gen_frame_mem (Pmode
, addr
);
3343 *cfa_restores
= alloc_reg_note (REG_CFA_RESTORE
, reg
, *cfa_restores
);
3344 return emit_insn (gen_movsi (reg
, mem
));
3348 /* Helper function to set RTX_FRAME_RELATED_P on instructions,
3349 including sequences. */
3351 set_frame_related_p (void)
3353 rtx_insn
*seq
= get_insns ();
3364 while (insn
!= NULL_RTX
)
3366 RTX_FRAME_RELATED_P (insn
) = 1;
3367 insn
= NEXT_INSN (insn
);
3369 seq
= emit_insn (seq
);
3373 seq
= emit_insn (seq
);
3374 RTX_FRAME_RELATED_P (seq
) = 1;
3380 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
3382 /* This emits code for 'sp += offset'.
3384 The ABI only allows us to modify 'sp' in a single 'addi' or
3385 'addli', so the backtracer understands it. Larger amounts cannot
3386 use those instructions, so are added by placing the offset into a
3387 large register and using 'add'.
3389 This happens after reload, so we need to expand it ourselves. */
3391 emit_sp_adjust (int offset
, int *next_scratch_regno
, bool frame_related
,
3395 rtx imm_rtx
= gen_int_si (offset
);
3398 if (satisfies_constraint_J (imm_rtx
))
3400 /* We can add this using a single addi or addli. */
3405 rtx tmp
= gen_rtx_REG (Pmode
, (*next_scratch_regno
)--);
3406 tilepro_expand_set_const32 (tmp
, imm_rtx
);
3410 /* Actually adjust the stack pointer. */
3411 insn
= emit_insn (gen_sp_adjust (stack_pointer_rtx
, stack_pointer_rtx
,
3413 REG_NOTES (insn
) = reg_notes
;
3415 /* Describe what just happened in a way that dwarf understands. */
3418 rtx real
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
3419 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3421 RTX_FRAME_RELATED_P (insn
) = 1;
3422 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, real
);
3429 /* Return whether the current function is leaf. This takes into
3430 account whether the function calls tls_get_addr. */
3432 tilepro_current_function_is_leaf (void)
3434 return crtl
->is_leaf
&& !cfun
->machine
->calls_tls_get_addr
;
3438 /* Return the frame size. */
3440 compute_total_frame_size (void)
3442 int total_size
= (get_frame_size () + tilepro_saved_regs_size ()
3443 + crtl
->outgoing_args_size
3444 + crtl
->args
.pretend_args_size
);
3446 if (!tilepro_current_function_is_leaf () || cfun
->calls_alloca
)
3448 /* Make room for save area in callee. */
3449 total_size
+= STACK_POINTER_OFFSET
;
3452 return round_frame_size (total_size
);
3456 /* Return nonzero if this function is known to have a null epilogue.
3457 This allows the optimizer to omit jumps to jumps if no stack was
3460 tilepro_can_use_return_insn_p (void)
3462 return (reload_completed
3463 && cfun
->static_chain_decl
== 0
3464 && compute_total_frame_size () == 0
3465 && tilepro_current_function_is_leaf ()
3466 && !crtl
->profile
&& !df_regs_ever_live_p (TILEPRO_LINK_REGNUM
));
3470 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'. If there
3471 is a frame pointer, it computes the value relative to
3472 that. Otherwise it uses the stack pointer. */
3474 compute_frame_addr (int offset_from_fp
, int *next_scratch_regno
)
3476 rtx base_reg_rtx
, tmp_reg_rtx
, offset_rtx
;
3477 int offset_from_base
;
3479 if (frame_pointer_needed
)
3481 base_reg_rtx
= hard_frame_pointer_rtx
;
3482 offset_from_base
= offset_from_fp
;
3486 int offset_from_sp
= compute_total_frame_size () + offset_from_fp
;
3487 base_reg_rtx
= stack_pointer_rtx
;
3488 offset_from_base
= offset_from_sp
;
3491 if (offset_from_base
== 0)
3492 return base_reg_rtx
;
3494 /* Compute the new value of the stack pointer. */
3495 tmp_reg_rtx
= gen_rtx_REG (Pmode
, (*next_scratch_regno
)--);
3496 offset_rtx
= gen_int_si (offset_from_base
);
3498 if (!tilepro_expand_addsi (tmp_reg_rtx
, base_reg_rtx
, offset_rtx
))
3500 emit_insn (gen_rtx_SET (VOIDmode
, tmp_reg_rtx
,
3501 gen_rtx_PLUS (Pmode
, base_reg_rtx
,
3509 /* The stack frame looks like this:
3514 AP -> +-------------+
3518 HFP -> +-------------+
3520 | reg save | crtl->args.pretend_args_size bytes
3523 | saved regs | tilepro_saved_regs_size() bytes
3524 FP -> +-------------+
3526 | vars | get_frame_size() bytes
3530 | stack args | crtl->outgoing_args_size bytes
3532 | HFP | 4 bytes (only here if nonleaf / alloca)
3534 | callee lr | 4 bytes (only here if nonleaf / alloca)
3536 SP -> +-------------+
3540 For functions with a frame larger than 32767 bytes, or which use
3541 alloca (), r52 is used as a frame pointer. Otherwise there is no
3544 FP is saved at SP+4 before calling a subroutine so the
3545 callee can chain. */
3547 tilepro_expand_prologue (void)
3549 #define ROUND_ROBIN_SIZE 4
3550 /* We round-robin through four scratch registers to hold temporary
3551 addresses for saving registers, to make instruction scheduling
3553 rtx reg_save_addr
[ROUND_ROBIN_SIZE
] = {
3554 NULL_RTX
, NULL_RTX
, NULL_RTX
, NULL_RTX
3557 unsigned int which_scratch
;
3558 int offset
, start_offset
, regno
;
3560 /* A register that holds a copy of the incoming fp. */
3561 int fp_copy_regno
= -1;
3563 /* A register that holds a copy of the incoming sp. */
3564 int sp_copy_regno
= -1;
3566 /* Next scratch register number to hand out (postdecrementing). */
3567 int next_scratch_regno
= 29;
3569 int total_size
= compute_total_frame_size ();
3571 if (flag_stack_usage_info
)
3572 current_function_static_stack_size
= total_size
;
3574 /* Save lr first in its special location because code after this
3575 might use the link register as a scratch register. */
3576 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM
) || crtl
->calls_eh_return
)
3577 FRP (frame_emit_store (TILEPRO_LINK_REGNUM
, TILEPRO_LINK_REGNUM
,
3578 stack_pointer_rtx
, stack_pointer_rtx
, 0));
3580 if (total_size
== 0)
3582 /* Load the PIC register if needed. */
3583 if (flag_pic
&& crtl
->uses_pic_offset_table
)
3584 load_pic_register (false);
3589 cfa
= stack_pointer_rtx
;
3591 if (frame_pointer_needed
)
3593 fp_copy_regno
= next_scratch_regno
--;
3595 /* Copy the old frame pointer aside so we can save it later. */
3596 insn
= FRP (emit_move_insn (gen_rtx_REG (word_mode
, fp_copy_regno
),
3597 hard_frame_pointer_rtx
));
3598 add_reg_note (insn
, REG_CFA_REGISTER
, NULL_RTX
);
3600 /* Set up the frame pointer. */
3601 insn
= FRP (emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
));
3602 add_reg_note (insn
, REG_CFA_DEF_CFA
, hard_frame_pointer_rtx
);
3603 cfa
= hard_frame_pointer_rtx
;
3604 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM
) = STACK_BOUNDARY
;
3606 /* fp holds a copy of the incoming sp, in case we need to store
3608 sp_copy_regno
= HARD_FRAME_POINTER_REGNUM
;
3610 else if (!tilepro_current_function_is_leaf ())
3612 /* Copy the old stack pointer aside so we can save it later. */
3613 sp_copy_regno
= next_scratch_regno
--;
3614 emit_move_insn (gen_rtx_REG (Pmode
, sp_copy_regno
),
3618 if (tilepro_current_function_is_leaf ())
3620 /* No need to store chain pointer to caller's frame. */
3621 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3622 !frame_pointer_needed
, NULL_RTX
);
3626 /* Save the frame pointer (incoming sp value) to support
3627 backtracing. First we need to create an rtx with the store
3629 rtx chain_addr
= gen_rtx_REG (Pmode
, next_scratch_regno
--);
3630 rtx size_rtx
= gen_int_si (-(total_size
- UNITS_PER_WORD
));
3632 if (add_operand (size_rtx
, Pmode
))
3634 /* Expose more parallelism by computing this value from the
3635 original stack pointer, not the one after we have pushed
3637 rtx p
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, size_rtx
);
3638 emit_insn (gen_rtx_SET (VOIDmode
, chain_addr
, p
));
3639 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3640 !frame_pointer_needed
, NULL_RTX
);
3644 /* The stack frame is large, so just store the incoming sp
3645 value at *(new_sp + UNITS_PER_WORD). */
3647 emit_sp_adjust (-total_size
, &next_scratch_regno
,
3648 !frame_pointer_needed
, NULL_RTX
);
3649 p
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
3650 GEN_INT (UNITS_PER_WORD
));
3651 emit_insn (gen_rtx_SET (VOIDmode
, chain_addr
, p
));
3654 /* Save our frame pointer for backtrace chaining. */
3655 emit_insn (gen_movsi (gen_frame_mem (SImode
, chain_addr
),
3656 gen_rtx_REG (SImode
, sp_copy_regno
)));
3659 /* Compute where to start storing registers we need to save. */
3660 start_offset
= -crtl
->args
.pretend_args_size
- UNITS_PER_WORD
;
3661 offset
= start_offset
;
3663 /* Store all registers that need saving. */
3665 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
>= 0; regno
--)
3666 if (need_to_save_reg (regno
))
3668 rtx r
= reg_save_addr
[which_scratch
];
3670 int cfa_offset
= frame_pointer_needed
? offset
: total_size
+ offset
;
3674 rtx p
= compute_frame_addr (offset
, &next_scratch_regno
);
3675 r
= gen_rtx_REG (word_mode
, next_scratch_regno
--);
3676 reg_save_addr
[which_scratch
] = r
;
3678 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3682 /* Advance to the next stack slot to store this register. */
3683 int stride
= ROUND_ROBIN_SIZE
* -UNITS_PER_WORD
;
3684 rtx p
= gen_rtx_PLUS (Pmode
, r
, GEN_INT (stride
));
3685 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3688 /* Save this register to the stack (but use the old fp value
3689 we copied aside if appropriate). */
3690 from_regno
= (fp_copy_regno
>= 0
3692 HARD_FRAME_POINTER_REGNUM
) ? fp_copy_regno
: regno
;
3693 FRP (frame_emit_store (from_regno
, regno
, r
, cfa
, cfa_offset
));
3695 offset
-= UNITS_PER_WORD
;
3696 which_scratch
= (which_scratch
+ 1) % ROUND_ROBIN_SIZE
;
3699 /* If profiling, force that to happen after the frame is set up. */
3701 emit_insn (gen_blockage ());
3703 /* Load the PIC register if needed. */
3704 if (flag_pic
&& crtl
->uses_pic_offset_table
)
3705 load_pic_register (false);
3709 /* Implement the epilogue and sibcall_epilogue patterns. SIBCALL_P is
3710 true for a sibcall_epilogue pattern, and false for an epilogue
3713 tilepro_expand_epilogue (bool sibcall_p
)
3715 /* We round-robin through four scratch registers to hold temporary
3716 addresses for saving registers, to make instruction scheduling
3718 rtx reg_save_addr
[ROUND_ROBIN_SIZE
] = {
3719 NULL_RTX
, NULL_RTX
, NULL_RTX
, NULL_RTX
3721 rtx_insn
*last_insn
, *insn
;
3722 unsigned int which_scratch
;
3723 int offset
, start_offset
, regno
;
3724 rtx cfa_restores
= NULL_RTX
;
3726 /* A register that holds a copy of the incoming fp. */
3727 int fp_copy_regno
= -1;
3729 /* Next scratch register number to hand out (postdecrementing). */
3730 int next_scratch_regno
= 29;
3732 int total_size
= compute_total_frame_size ();
3734 last_insn
= get_last_insn ();
3736 /* Load lr first since we are going to need it first. */
3738 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM
))
3740 insn
= frame_emit_load (TILEPRO_LINK_REGNUM
,
3741 compute_frame_addr (0, &next_scratch_regno
),
3745 if (total_size
== 0)
3749 RTX_FRAME_RELATED_P (insn
) = 1;
3750 REG_NOTES (insn
) = cfa_restores
;
3755 /* Compute where to start restoring registers. */
3756 start_offset
= -crtl
->args
.pretend_args_size
- UNITS_PER_WORD
;
3757 offset
= start_offset
;
3759 if (frame_pointer_needed
)
3760 fp_copy_regno
= next_scratch_regno
--;
3762 /* Restore all callee-saved registers. */
3764 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
>= 0; regno
--)
3765 if (need_to_save_reg (regno
))
3767 rtx r
= reg_save_addr
[which_scratch
];
3770 r
= compute_frame_addr (offset
, &next_scratch_regno
);
3771 reg_save_addr
[which_scratch
] = r
;
3775 /* Advance to the next stack slot to store this
3777 int stride
= ROUND_ROBIN_SIZE
* -UNITS_PER_WORD
;
3778 rtx p
= gen_rtx_PLUS (Pmode
, r
, GEN_INT (stride
));
3779 emit_insn (gen_rtx_SET (VOIDmode
, r
, p
));
3782 if (fp_copy_regno
>= 0 && regno
== HARD_FRAME_POINTER_REGNUM
)
3783 frame_emit_load (fp_copy_regno
, r
, NULL
);
3785 frame_emit_load (regno
, r
, &cfa_restores
);
3787 offset
-= UNITS_PER_WORD
;
3788 which_scratch
= (which_scratch
+ 1) % ROUND_ROBIN_SIZE
;
3791 if (!tilepro_current_function_is_leaf ())
3793 alloc_reg_note (REG_CFA_RESTORE
, stack_pointer_rtx
, cfa_restores
);
3795 emit_insn (gen_blockage ());
3797 if (frame_pointer_needed
)
3799 /* Restore the old stack pointer by copying from the frame
3801 insn
= emit_insn (gen_sp_restore (stack_pointer_rtx
,
3802 hard_frame_pointer_rtx
));
3803 RTX_FRAME_RELATED_P (insn
) = 1;
3804 REG_NOTES (insn
) = cfa_restores
;
3805 add_reg_note (insn
, REG_CFA_DEF_CFA
, stack_pointer_rtx
);
3809 insn
= emit_sp_adjust (total_size
, &next_scratch_regno
, true,
3813 if (crtl
->calls_eh_return
)
3814 emit_insn (gen_sp_adjust (stack_pointer_rtx
, stack_pointer_rtx
,
3815 EH_RETURN_STACKADJ_RTX
));
3817 /* Restore the old frame pointer. */
3818 if (frame_pointer_needed
)
3820 insn
= emit_move_insn (hard_frame_pointer_rtx
,
3821 gen_rtx_REG (Pmode
, fp_copy_regno
));
3822 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
3825 /* Mark the pic registers as live outside of the function. */
3828 emit_use (cfun
->machine
->text_label_rtx
);
3829 emit_use (cfun
->machine
->got_rtx
);
3835 /* Emit the actual 'return' instruction. */
3836 emit_jump_insn (gen__return ());
3840 emit_use (gen_rtx_REG (Pmode
, TILEPRO_LINK_REGNUM
));
3843 /* Mark all insns we just emitted as frame-related. */
3844 for (; last_insn
!= NULL_RTX
; last_insn
= next_insn (last_insn
))
3845 RTX_FRAME_RELATED_P (last_insn
) = 1;
3848 #undef ROUND_ROBIN_SIZE
3851 /* Implement INITIAL_ELIMINATION_OFFSET. */
3853 tilepro_initial_elimination_offset (int from
, int to
)
3855 int total_size
= compute_total_frame_size ();
3857 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3859 return (total_size
- crtl
->args
.pretend_args_size
3860 - tilepro_saved_regs_size ());
3862 else if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3864 return -(crtl
->args
.pretend_args_size
+ tilepro_saved_regs_size ());
3866 else if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3868 return STACK_POINTER_OFFSET
+ total_size
;
3870 else if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
3872 return STACK_POINTER_OFFSET
;
3879 /* Return an RTX indicating where the return address to the
3880 calling function can be found. */
3882 tilepro_return_addr (int count
, rtx frame ATTRIBUTE_UNUSED
)
3887 return get_hard_reg_initial_val (Pmode
, TILEPRO_LINK_REGNUM
);
3891 /* Implement EH_RETURN_HANDLER_RTX. */
3893 tilepro_eh_return_handler_rtx (void)
3895 /* The MEM needs to be volatile to prevent it from being
3897 rtx tmp
= gen_frame_mem (Pmode
, hard_frame_pointer_rtx
);
3898 MEM_VOLATILE_P (tmp
) = true;
3906 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE. */
3908 tilepro_conditional_register_usage (void)
3910 global_regs
[TILEPRO_NETORDER_REGNUM
] = 1;
3911 /* TILEPRO_PIC_TEXT_LABEL_REGNUM is conditionally used. It is a
3912 member of fixed_regs, and therefore must be member of
3913 call_used_regs, but it is not a member of call_really_used_regs[]
3914 because it is not clobbered by a call. */
3915 if (TILEPRO_PIC_TEXT_LABEL_REGNUM
!= INVALID_REGNUM
)
3917 fixed_regs
[TILEPRO_PIC_TEXT_LABEL_REGNUM
] = 1;
3918 call_used_regs
[TILEPRO_PIC_TEXT_LABEL_REGNUM
] = 1;
3920 if (PIC_OFFSET_TABLE_REGNUM
!= INVALID_REGNUM
)
3922 fixed_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
3923 call_used_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
3928 /* Implement TARGET_FRAME_POINTER_REQUIRED. */
3930 tilepro_frame_pointer_required (void)
3932 return crtl
->calls_eh_return
|| cfun
->calls_alloca
;
3937 /* Scheduling and reorg */
3939 /* Return the length of INSN. LENGTH is the initial length computed
3940 by attributes in the machine-description file. This is where we
3941 account for bundles. */
3943 tilepro_adjust_insn_length (rtx_insn
*insn
, int length
)
3945 machine_mode mode
= GET_MODE (insn
);
3947 /* A non-termininating instruction in a bundle has length 0. */
3951 /* By default, there is not length adjustment. */
3956 /* Implement TARGET_SCHED_ISSUE_RATE. */
3958 tilepro_issue_rate (void)
3964 /* Return the rtx for the jump target. */
3966 get_jump_target (rtx branch
)
3968 if (CALL_P (branch
))
3971 call
= PATTERN (branch
);
3973 if (GET_CODE (call
) == PARALLEL
)
3974 call
= XVECEXP (call
, 0, 0);
3976 if (GET_CODE (call
) == SET
)
3977 call
= SET_SRC (call
);
3979 if (GET_CODE (call
) == CALL
)
3980 return XEXP (XEXP (call
, 0), 0);
3985 /* Implement TARGET_SCHED_ADJUST_COST. */
3987 tilepro_sched_adjust_cost (rtx_insn
*insn
, rtx link
, rtx_insn
*dep_insn
,
3990 /* If we have a true dependence, INSN is a call, and DEP_INSN
3991 defines a register that is needed by the call (argument or stack
3992 pointer), set its latency to 0 so that it can be bundled with
3993 the call. Explicitly check for and exclude the case when
3994 DEP_INSN defines the target of the jump. */
3995 if (CALL_P (insn
) && REG_NOTE_KIND (link
) == REG_DEP_TRUE
)
3997 rtx target
= get_jump_target (insn
);
3998 if (!REG_P (target
) || !set_of (target
, dep_insn
))
4006 /* Skip over irrelevant NOTEs and such and look for the next insn we
4007 would consider bundling. */
4009 next_insn_to_bundle (rtx_insn
*r
, rtx_insn
*end
)
4011 for (; r
!= end
; r
= NEXT_INSN (r
))
4013 if (NONDEBUG_INSN_P (r
)
4014 && GET_CODE (PATTERN (r
)) != USE
4015 && GET_CODE (PATTERN (r
)) != CLOBBER
)
4023 /* Go through all insns, and use the information generated during
4024 scheduling to generate SEQUENCEs to represent bundles of
4025 instructions issued simultaneously. */
4027 tilepro_gen_bundles (void)
4030 FOR_EACH_BB_FN (bb
, cfun
)
4032 rtx_insn
*insn
, *next
;
4033 rtx_insn
*end
= NEXT_INSN (BB_END (bb
));
4035 for (insn
= next_insn_to_bundle (BB_HEAD (bb
), end
); insn
; insn
= next
)
4037 next
= next_insn_to_bundle (NEXT_INSN (insn
), end
);
4039 /* Never wrap {} around inline asm. */
4040 if (GET_CODE (PATTERN (insn
)) != ASM_INPUT
)
4042 if (next
== NULL_RTX
|| GET_MODE (next
) == TImode
4043 /* NOTE: The scheduler incorrectly believes a call
4044 insn can execute in the same cycle as the insn
4045 after the call. This is of course impossible.
4046 Really we need to fix the scheduler somehow, so
4047 the code after the call gets scheduled
4051 /* Mark current insn as the end of a bundle. */
4052 PUT_MODE (insn
, QImode
);
4056 /* Mark it as part of a bundle. */
4057 PUT_MODE (insn
, SImode
);
4065 /* Helper function for tilepro_fixup_pcrel_references. */
4067 replace_pc_relative_symbol_ref (rtx_insn
*insn
, rtx opnds
[4], bool first_insn_p
)
4069 rtx_insn
*new_insns
;
4077 emit_insn (gen_add_got16 (opnds
[0], tilepro_got_rtx (),
4079 emit_insn (gen_insn_lw (opnds
[0], opnds
[0]));
4086 emit_insn (gen_addhi_got32 (opnds
[0], tilepro_got_rtx (),
4091 emit_insn (gen_addlo_got32 (opnds
[0], opnds
[1], opnds
[2]));
4092 emit_insn (gen_insn_lw (opnds
[0], opnds
[0]));
4096 new_insns
= get_insns ();
4100 emit_insn_before (new_insns
, insn
);
4106 /* Returns whether INSN is a pc-relative addli insn. */
4108 match_addli_pcrel (rtx_insn
*insn
)
4110 rtx pattern
= PATTERN (insn
);
4113 if (GET_CODE (pattern
) != SET
)
4116 if (GET_CODE (SET_SRC (pattern
)) != LO_SUM
)
4119 if (GET_CODE (XEXP (SET_SRC (pattern
), 1)) != CONST
)
4122 unspec
= XEXP (XEXP (SET_SRC (pattern
), 1), 0);
4124 return (GET_CODE (unspec
) == UNSPEC
4125 && XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4129 /* Helper function for tilepro_fixup_pcrel_references. */
4131 replace_addli_pcrel (rtx_insn
*insn
)
4133 rtx pattern
= PATTERN (insn
);
4139 gcc_assert (GET_CODE (pattern
) == SET
);
4140 opnds
[0] = SET_DEST (pattern
);
4142 set_src
= SET_SRC (pattern
);
4143 gcc_assert (GET_CODE (set_src
) == LO_SUM
);
4144 gcc_assert (GET_CODE (XEXP (set_src
, 1)) == CONST
);
4145 opnds
[1] = XEXP (set_src
, 0);
4147 unspec
= XEXP (XEXP (set_src
, 1), 0);
4148 gcc_assert (GET_CODE (unspec
) == UNSPEC
);
4149 gcc_assert (XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4150 opnds
[2] = XVECEXP (unspec
, 0, 0);
4151 opnds
[3] = XVECEXP (unspec
, 0, 1);
4153 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */
4154 if (GET_CODE (opnds
[2]) != SYMBOL_REF
)
4157 first_insn_p
= (opnds
[1] == tilepro_text_label_rtx ());
4159 replace_pc_relative_symbol_ref (insn
, opnds
, first_insn_p
);
4163 /* Returns whether INSN is a pc-relative auli insn. */
4165 match_auli_pcrel (rtx_insn
*insn
)
4167 rtx pattern
= PATTERN (insn
);
4171 if (GET_CODE (pattern
) != SET
)
4174 if (GET_CODE (SET_SRC (pattern
)) != PLUS
)
4177 high
= XEXP (SET_SRC (pattern
), 1);
4179 if (GET_CODE (high
) != HIGH
4180 || GET_CODE (XEXP (high
, 0)) != CONST
)
4183 unspec
= XEXP (XEXP (high
, 0), 0);
4185 return (GET_CODE (unspec
) == UNSPEC
4186 && XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4190 /* Helper function for tilepro_fixup_pcrel_references. */
4192 replace_auli_pcrel (rtx_insn
*insn
)
4194 rtx pattern
= PATTERN (insn
);
4201 gcc_assert (GET_CODE (pattern
) == SET
);
4202 opnds
[0] = SET_DEST (pattern
);
4204 set_src
= SET_SRC (pattern
);
4205 gcc_assert (GET_CODE (set_src
) == PLUS
);
4206 opnds
[1] = XEXP (set_src
, 0);
4208 high
= XEXP (set_src
, 1);
4209 gcc_assert (GET_CODE (high
) == HIGH
);
4210 gcc_assert (GET_CODE (XEXP (high
, 0)) == CONST
);
4212 unspec
= XEXP (XEXP (high
, 0), 0);
4213 gcc_assert (GET_CODE (unspec
) == UNSPEC
);
4214 gcc_assert (XINT (unspec
, 1) == UNSPEC_PCREL_SYM
);
4215 opnds
[2] = XVECEXP (unspec
, 0, 0);
4216 opnds
[3] = XVECEXP (unspec
, 0, 1);
4218 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */
4219 if (GET_CODE (opnds
[2]) != SYMBOL_REF
)
4222 first_insn_p
= (opnds
[1] == tilepro_text_label_rtx ());
4224 replace_pc_relative_symbol_ref (insn
, opnds
, first_insn_p
);
4228 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid
4229 going through the GOT when the symbol is local to the compilation
4230 unit. But such a symbol requires that the common text_label that
4231 we generate at the beginning of the function be in the same section
4232 as the reference to the SYMBOL_REF. This may not be true if we
4233 generate hot/cold sections. This function looks for such cases and
4234 replaces such references with the longer sequence going through the
4237 We expect one of the following two instruction sequences:
4238 addli tmp1, txt_label_reg, lo16(sym - txt_label)
4239 auli tmp2, tmp1, ha16(sym - txt_label)
4241 auli tmp1, txt_label_reg, ha16(sym - txt_label)
4242 addli tmp2, tmp1, lo16(sym - txt_label)
4244 If we're compiling -fpic, we replace the first instruction with
4245 nothing, and the second instruction with:
4247 addli tmp2, got_rtx, got(sym)
4250 If we're compiling -fPIC, we replace the first instruction with:
4252 auli tmp1, got_rtx, got_ha16(sym)
4254 and the second instruction with:
4256 addli tmp2, tmp1, got_lo16(sym)
4259 Note that we're careful to disturb the instruction sequence as
4260 little as possible, since it's very late in the compilation
4264 tilepro_fixup_pcrel_references (void)
4266 rtx_insn
*insn
, *next_insn
;
4267 bool same_section_as_entry
= true;
4269 for (insn
= get_insns (); insn
; insn
= next_insn
)
4271 next_insn
= NEXT_INSN (insn
);
4273 if (NOTE_P (insn
) && NOTE_KIND (insn
) == NOTE_INSN_SWITCH_TEXT_SECTIONS
)
4275 same_section_as_entry
= !same_section_as_entry
;
4279 if (same_section_as_entry
)
4283 && GET_CODE (PATTERN (insn
)) != USE
4284 && GET_CODE (PATTERN (insn
)) != CLOBBER
))
4287 if (match_addli_pcrel (insn
))
4288 replace_addli_pcrel (insn
);
4289 else if (match_auli_pcrel (insn
))
4290 replace_auli_pcrel (insn
);
4295 /* Ensure that no var tracking notes are emitted in the middle of a
4296 three-instruction bundle. */
4298 reorder_var_tracking_notes (void)
4301 FOR_EACH_BB_FN (bb
, cfun
)
4303 rtx_insn
*insn
, *next
;
4304 rtx_insn
*queue
= NULL
;
4305 bool in_bundle
= false;
4307 for (insn
= BB_HEAD (bb
); insn
!= BB_END (bb
); insn
= next
)
4309 next
= NEXT_INSN (insn
);
4313 /* Emit queued up notes at the last instruction of a bundle. */
4314 if (GET_MODE (insn
) == QImode
)
4318 rtx_insn
*next_queue
= PREV_INSN (queue
);
4319 SET_PREV_INSN (NEXT_INSN (insn
)) = queue
;
4320 SET_NEXT_INSN (queue
) = NEXT_INSN (insn
);
4321 SET_NEXT_INSN (insn
) = queue
;
4322 SET_PREV_INSN (queue
) = insn
;
4327 else if (GET_MODE (insn
) == SImode
)
4330 else if (NOTE_P (insn
) && NOTE_KIND (insn
) == NOTE_INSN_VAR_LOCATION
)
4334 rtx_insn
*prev
= PREV_INSN (insn
);
4335 SET_PREV_INSN (next
) = prev
;
4336 SET_NEXT_INSN (prev
) = next
;
4338 SET_PREV_INSN (insn
) = queue
;
4347 /* Perform machine dependent operations on the rtl chain INSNS. */
4349 tilepro_reorg (void)
4351 /* We are freeing block_for_insn in the toplev to keep compatibility
4352 with old MDEP_REORGS that are not CFG based. Recompute it
4354 compute_bb_for_insn ();
4356 if (flag_reorder_blocks_and_partition
)
4358 tilepro_fixup_pcrel_references ();
4361 if (flag_schedule_insns_after_reload
)
4365 timevar_push (TV_SCHED2
);
4367 timevar_pop (TV_SCHED2
);
4369 /* Examine the schedule to group into bundles. */
4370 tilepro_gen_bundles ();
4375 if (flag_var_tracking
)
4377 timevar_push (TV_VAR_TRACKING
);
4378 variable_tracking_main ();
4379 reorder_var_tracking_notes ();
4380 timevar_pop (TV_VAR_TRACKING
);
4383 df_finish_pass (false);
4390 /* Select a format to encode pointers in exception handling data.
4391 CODE is 0 for data, 1 for code labels, 2 for function pointers.
4392 GLOBAL is true if the symbol may be affected by dynamic
4395 tilepro_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED
, int global
)
4397 return (global
? DW_EH_PE_indirect
: 0) | DW_EH_PE_pcrel
| DW_EH_PE_sdata4
;
4401 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
4403 tilepro_asm_output_mi_thunk (FILE *file
, tree thunk_fndecl ATTRIBUTE_UNUSED
,
4404 HOST_WIDE_INT delta
, HOST_WIDE_INT vcall_offset
,
4407 rtx this_rtx
, funexp
;
4410 /* Pretend to be a post-reload pass while generating rtl. */
4411 reload_completed
= 1;
4413 /* Mark the end of the (empty) prologue. */
4414 emit_note (NOTE_INSN_PROLOGUE_END
);
4416 /* Find the "this" pointer. If the function returns a structure,
4417 the structure return pointer is in $1. */
4418 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
))
4419 this_rtx
= gen_rtx_REG (Pmode
, 1);
4421 this_rtx
= gen_rtx_REG (Pmode
, 0);
4423 /* Add DELTA to THIS_RTX. */
4424 emit_insn (gen_addsi3 (this_rtx
, this_rtx
, GEN_INT (delta
)));
4426 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
4431 tmp
= gen_rtx_REG (Pmode
, 29);
4432 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, this_rtx
));
4434 emit_insn (gen_addsi3 (tmp
, tmp
, GEN_INT (vcall_offset
)));
4436 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, tmp
));
4438 emit_insn (gen_addsi3 (this_rtx
, this_rtx
, tmp
));
4441 /* Generate a tail call to the target function. */
4442 if (!TREE_USED (function
))
4444 assemble_external (function
);
4445 TREE_USED (function
) = 1;
4447 funexp
= XEXP (DECL_RTL (function
), 0);
4448 funexp
= gen_rtx_MEM (FUNCTION_MODE
, funexp
);
4449 insn
= emit_call_insn (gen_sibcall (funexp
, const0_rtx
));
4450 SIBLING_CALL_P (insn
) = 1;
4452 /* Run just enough of rest_of_compilation to get the insns emitted.
4453 There's not really enough bulk here to make other passes such as
4454 instruction scheduling worth while. Note that use_thunk calls
4455 assemble_start_function and assemble_end_function.
4457 We don't currently bundle, but the instruciton sequence is all
4458 serial except for the tail call, so we're only wasting one cycle.
4460 insn
= get_insns ();
4461 shorten_branches (insn
);
4462 final_start_function (insn
, file
, 1);
4463 final (insn
, file
, 1);
4464 final_end_function ();
4466 /* Stop pretending to be a post-reload pass. */
4467 reload_completed
= 0;
4471 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */
4473 tilepro_asm_trampoline_template (FILE *file
)
4475 fprintf (file
, "\tlnk r10\n");
4476 fprintf (file
, "\taddi r10, r10, 32\n");
4477 fprintf (file
, "\tlwadd r11, r10, %d\n", GET_MODE_SIZE (ptr_mode
));
4478 fprintf (file
, "\tlw r10, r10\n");
4479 fprintf (file
, "\tjr r11\n");
4480 fprintf (file
, "\t.word 0 # <function address>\n");
4481 fprintf (file
, "\t.word 0 # <static chain value>\n");
4485 /* Implement TARGET_TRAMPOLINE_INIT. */
4487 tilepro_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
4491 rtx begin_addr
, end_addr
;
4492 int ptr_mode_size
= GET_MODE_SIZE (ptr_mode
);
4494 fnaddr
= copy_to_reg (XEXP (DECL_RTL (fndecl
), 0));
4495 chaddr
= copy_to_reg (static_chain
);
4497 emit_block_move (m_tramp
, assemble_trampoline_template (),
4498 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
4500 mem
= adjust_address (m_tramp
, ptr_mode
,
4501 TRAMPOLINE_SIZE
- 2 * ptr_mode_size
);
4502 emit_move_insn (mem
, fnaddr
);
4503 mem
= adjust_address (m_tramp
, ptr_mode
,
4504 TRAMPOLINE_SIZE
- ptr_mode_size
);
4505 emit_move_insn (mem
, chaddr
);
4507 /* Get pointers to the beginning and end of the code block. */
4508 begin_addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
4509 end_addr
= force_reg (Pmode
, plus_constant (Pmode
, XEXP (m_tramp
, 0),
4512 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__clear_cache"),
4513 LCT_NORMAL
, VOIDmode
, 2, begin_addr
, Pmode
,
4518 /* Implement TARGET_PRINT_OPERAND. */
4520 tilepro_print_operand (FILE *file
, rtx x
, int code
)
4525 /* Print the compare operator opcode for conditional moves. */
4526 switch (GET_CODE (x
))
4535 output_operand_lossage ("invalid %%c operand");
4540 /* Print the compare operator opcode for conditional moves. */
4541 switch (GET_CODE (x
))
4550 output_operand_lossage ("invalid %%C operand");
4556 /* Print the high 16 bits of a 32-bit constant. */
4558 if (CONST_INT_P (x
))
4560 else if (GET_CODE (x
) == CONST_DOUBLE
)
4561 i
= CONST_DOUBLE_LOW (x
);
4564 output_operand_lossage ("invalid %%h operand");
4567 i
= trunc_int_for_mode (i
>> 16, HImode
);
4568 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4575 const char *opstr
= NULL
;
4577 if (GET_CODE (x
) == CONST
4578 && GET_CODE (XEXP (x
, 0)) == UNSPEC
)
4580 addr
= XVECEXP (XEXP (x
, 0), 0, 0);
4581 switch (XINT (XEXP (x
, 0), 1))
4583 case UNSPEC_GOT32_SYM
:
4586 case UNSPEC_PCREL_SYM
:
4591 opstr
= "tls_gd_ha16";
4594 opstr
= "tls_ie_ha16";
4597 opstr
= "tls_le_ha16";
4600 output_operand_lossage ("invalid %%H operand");
4609 fputs (opstr
, file
);
4611 output_addr_const (file
, addr
);
4615 rtx addr2
= XVECEXP (XEXP (x
, 0), 0, 1);
4616 fputs (" - " , file
);
4617 output_addr_const (file
, addr2
);
4625 /* Print an auto-inc memory operand. */
4628 output_operand_lossage ("invalid %%I operand");
4632 output_memory_reference_mode
= GET_MODE (x
);
4633 output_memory_autoinc_first
= true;
4634 output_address (XEXP (x
, 0));
4635 output_memory_reference_mode
= VOIDmode
;
4639 /* Print an auto-inc memory operand. */
4642 output_operand_lossage ("invalid %%i operand");
4646 output_memory_reference_mode
= GET_MODE (x
);
4647 output_memory_autoinc_first
= false;
4648 output_address (XEXP (x
, 0));
4649 output_memory_reference_mode
= VOIDmode
;
4654 /* Print the low 8 bits of a constant. */
4656 if (CONST_INT_P (x
))
4658 else if (GET_CODE (x
) == CONST_DOUBLE
)
4659 i
= CONST_DOUBLE_LOW (x
);
4660 else if (GET_CODE (x
) == CONST_VECTOR
4661 && CONST_INT_P (CONST_VECTOR_ELT (x
, 0)))
4662 i
= INTVAL (CONST_VECTOR_ELT (x
, 0));
4665 output_operand_lossage ("invalid %%j operand");
4668 i
= trunc_int_for_mode (i
, QImode
);
4669 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4676 const char *opstr
= NULL
;
4678 if (GET_CODE (x
) == CONST
4679 && GET_CODE (XEXP (x
, 0)) == UNSPEC
)
4681 addr
= XVECEXP (XEXP (x
, 0), 0, 0);
4682 switch (XINT (XEXP (x
, 0), 1))
4684 case UNSPEC_GOT16_SYM
:
4687 case UNSPEC_GOT32_SYM
:
4690 case UNSPEC_PCREL_SYM
:
4695 opstr
= "tls_gd_lo16";
4698 opstr
= "tls_ie_lo16";
4701 opstr
= "tls_le_lo16";
4704 output_operand_lossage ("invalid %%L operand");
4713 fputs (opstr
, file
);
4715 output_addr_const (file
, addr
);
4719 rtx addr2
= XVECEXP (XEXP (x
, 0), 0, 1);
4720 fputs (" - " , file
);
4721 output_addr_const (file
, addr2
);
4729 if (GET_CODE (x
) == SYMBOL_REF
)
4731 if (flag_pic
&& !SYMBOL_REF_LOCAL_P (x
))
4732 fprintf (file
, "plt(");
4733 output_addr_const (file
, x
);
4734 if (flag_pic
&& !SYMBOL_REF_LOCAL_P (x
))
4735 fprintf (file
, ")");
4738 output_addr_const (file
, x
);
4743 /* Print a 32-bit constant plus one. */
4745 if (!CONST_INT_P (x
))
4747 output_operand_lossage ("invalid %%P operand");
4750 i
= trunc_int_for_mode (INTVAL (x
) + 1, SImode
);
4751 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4757 /* Print an mm-style bit range. */
4758 int first_bit
, last_bit
;
4760 if (!CONST_INT_P (x
)
4761 || !tilepro_bitfield_operand_p (INTVAL (x
), &first_bit
,
4764 output_operand_lossage ("invalid %%M operand");
4768 fprintf (file
, "%d, %d", first_bit
, last_bit
);
4774 const char *reg
= NULL
;
4776 /* Print a network register. */
4777 if (!CONST_INT_P (x
))
4779 output_operand_lossage ("invalid %%N operand");
4785 case TILEPRO_NETREG_IDN0
: reg
= "idn0"; break;
4786 case TILEPRO_NETREG_IDN1
: reg
= "idn1"; break;
4787 case TILEPRO_NETREG_SN
: reg
= "sn"; break;
4788 case TILEPRO_NETREG_UDN0
: reg
= "udn0"; break;
4789 case TILEPRO_NETREG_UDN1
: reg
= "udn1"; break;
4790 case TILEPRO_NETREG_UDN2
: reg
= "udn2"; break;
4791 case TILEPRO_NETREG_UDN3
: reg
= "udn3"; break;
4792 default: gcc_unreachable ();
4795 fprintf (file
, reg
);
4801 /* Log base 2 of a power of two. */
4805 if (!CONST_INT_P (x
))
4807 output_operand_lossage ("invalid %%t operand");
4810 n
= trunc_int_for_mode (INTVAL (x
), SImode
);
4814 output_operand_lossage ("invalid %%t operand '"
4815 HOST_WIDE_INT_PRINT_DEC
"'", n
);
4819 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, i
);
4825 /* In this case we need a register. Use 'zero' if the
4826 operand is const0_rtx. */
4828 || (GET_MODE (x
) != VOIDmode
&& x
== CONST0_RTX (GET_MODE (x
))))
4830 fputs ("zero", file
);
4833 else if (!REG_P (x
))
4835 output_operand_lossage ("invalid %%r operand");
4843 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
4848 output_memory_reference_mode
= VOIDmode
;
4849 output_address (XEXP (x
, 0));
4854 output_addr_const (file
, x
);
4861 output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
4866 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
4868 tilepro_print_operand_address (FILE *file
, rtx addr
)
4870 if (GET_CODE (addr
) == POST_DEC
4871 || GET_CODE (addr
) == POST_INC
)
4873 int offset
= GET_MODE_SIZE (output_memory_reference_mode
);
4875 gcc_assert (output_memory_reference_mode
!= VOIDmode
);
4877 if (output_memory_autoinc_first
)
4878 fprintf (file
, "%s", reg_names
[REGNO (XEXP (addr
, 0))]);
4880 fprintf (file
, "%d",
4881 GET_CODE (addr
) == POST_DEC
? -offset
: offset
);
4883 else if (GET_CODE (addr
) == POST_MODIFY
)
4885 gcc_assert (output_memory_reference_mode
!= VOIDmode
);
4887 gcc_assert (GET_CODE (XEXP (addr
, 1)) == PLUS
);
4889 if (output_memory_autoinc_first
)
4890 fprintf (file
, "%s", reg_names
[REGNO (XEXP (addr
, 0))]);
4892 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
,
4893 INTVAL (XEXP (XEXP (addr
, 1), 1)));
4896 tilepro_print_operand (file
, addr
, 'r');
4900 /* Machine mode of current insn, for determining curly brace
4902 static machine_mode insn_mode
;
4905 /* Implement FINAL_PRESCAN_INSN. This is used to emit bundles. */
4907 tilepro_final_prescan_insn (rtx_insn
*insn
)
4909 /* Record this for tilepro_asm_output_opcode to examine. */
4910 insn_mode
= GET_MODE (insn
);
4914 /* While emitting asm, are we currently inside '{' for a bundle? */
4915 static bool tilepro_in_bundle
= false;
4917 /* Implement ASM_OUTPUT_OPCODE. Prepend/append curly braces as
4918 appropriate given the bundling information recorded by
4919 tilepro_gen_bundles. */
4921 tilepro_asm_output_opcode (FILE *stream
, const char *code
)
4923 bool pseudo
= !strcmp (code
, "pseudo");
4925 if (!tilepro_in_bundle
&& insn_mode
== SImode
)
4927 /* Start a new bundle. */
4928 fprintf (stream
, "{\n\t");
4929 tilepro_in_bundle
= true;
4932 if (tilepro_in_bundle
&& insn_mode
== QImode
)
4934 /* Close an existing bundle. */
4935 static char buf
[100];
4937 gcc_assert (strlen (code
) + 3 + 1 < sizeof (buf
));
4939 strcpy (buf
, pseudo
? "" : code
);
4940 strcat (buf
, "\n\t}");
4941 tilepro_in_bundle
= false;
4947 return pseudo
? "" : code
;
4952 /* Output assembler code to FILE to increment profiler label # LABELNO
4953 for profiling a function entry. */
4955 tilepro_function_profiler (FILE *file
, int labelno ATTRIBUTE_UNUSED
)
4957 if (tilepro_in_bundle
)
4959 fprintf (file
, "\t}\n");
4968 "\t}\n", MCOUNT_NAME
);
4976 "\t}\n", MCOUNT_NAME
);
4979 tilepro_in_bundle
= false;
4983 /* Implement TARGET_ASM_FILE_END. */
4985 tilepro_file_end (void)
4987 if (NEED_INDICATE_EXEC_STACK
)
4988 file_end_indicate_exec_stack ();
4992 #undef TARGET_HAVE_TLS
4993 #define TARGET_HAVE_TLS HAVE_AS_TLS
4995 #undef TARGET_OPTION_OVERRIDE
4996 #define TARGET_OPTION_OVERRIDE tilepro_option_override
4998 #undef TARGET_SCALAR_MODE_SUPPORTED_P
4999 #define TARGET_SCALAR_MODE_SUPPORTED_P tilepro_scalar_mode_supported_p
5001 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5002 #define TARGET_VECTOR_MODE_SUPPORTED_P tile_vector_mode_supported_p
5004 #undef TARGET_CANNOT_FORCE_CONST_MEM
5005 #define TARGET_CANNOT_FORCE_CONST_MEM tilepro_cannot_force_const_mem
5007 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5008 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilepro_function_ok_for_sibcall
5010 #undef TARGET_PASS_BY_REFERENCE
5011 #define TARGET_PASS_BY_REFERENCE tilepro_pass_by_reference
5013 #undef TARGET_RETURN_IN_MEMORY
5014 #define TARGET_RETURN_IN_MEMORY tilepro_return_in_memory
5016 #undef TARGET_FUNCTION_ARG_BOUNDARY
5017 #define TARGET_FUNCTION_ARG_BOUNDARY tilepro_function_arg_boundary
5019 #undef TARGET_FUNCTION_ARG
5020 #define TARGET_FUNCTION_ARG tilepro_function_arg
5022 #undef TARGET_FUNCTION_ARG_ADVANCE
5023 #define TARGET_FUNCTION_ARG_ADVANCE tilepro_function_arg_advance
5025 #undef TARGET_FUNCTION_VALUE
5026 #define TARGET_FUNCTION_VALUE tilepro_function_value
5028 #undef TARGET_LIBCALL_VALUE
5029 #define TARGET_LIBCALL_VALUE tilepro_libcall_value
5031 #undef TARGET_FUNCTION_VALUE_REGNO_P
5032 #define TARGET_FUNCTION_VALUE_REGNO_P tilepro_function_value_regno_p
5034 #undef TARGET_PROMOTE_FUNCTION_MODE
5035 #define TARGET_PROMOTE_FUNCTION_MODE \
5036 default_promote_function_mode_always_promote
5038 #undef TARGET_PROMOTE_PROTOTYPES
5039 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
5041 #undef TARGET_BUILD_BUILTIN_VA_LIST
5042 #define TARGET_BUILD_BUILTIN_VA_LIST tilepro_build_builtin_va_list
5044 #undef TARGET_EXPAND_BUILTIN_VA_START
5045 #define TARGET_EXPAND_BUILTIN_VA_START tilepro_va_start
5047 #undef TARGET_SETUP_INCOMING_VARARGS
5048 #define TARGET_SETUP_INCOMING_VARARGS tilepro_setup_incoming_varargs
5050 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
5051 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilepro_gimplify_va_arg_expr
5053 #undef TARGET_RTX_COSTS
5054 #define TARGET_RTX_COSTS tilepro_rtx_costs
5056 /* Limit to what we can reach in one addli. */
5057 #undef TARGET_MIN_ANCHOR_OFFSET
5058 #define TARGET_MIN_ANCHOR_OFFSET -32768
5059 #undef TARGET_MAX_ANCHOR_OFFSET
5060 #define TARGET_MAX_ANCHOR_OFFSET 32767
5062 #undef TARGET_LEGITIMATE_CONSTANT_P
5063 #define TARGET_LEGITIMATE_CONSTANT_P tilepro_legitimate_constant_p
5065 #undef TARGET_LEGITIMATE_ADDRESS_P
5066 #define TARGET_LEGITIMATE_ADDRESS_P tilepro_legitimate_address_p
5068 #undef TARGET_LEGITIMIZE_ADDRESS
5069 #define TARGET_LEGITIMIZE_ADDRESS tilepro_legitimize_address
5071 #undef TARGET_DELEGITIMIZE_ADDRESS
5072 #define TARGET_DELEGITIMIZE_ADDRESS tilepro_delegitimize_address
5074 #undef TARGET_INIT_BUILTINS
5075 #define TARGET_INIT_BUILTINS tilepro_init_builtins
5077 #undef TARGET_BUILTIN_DECL
5078 #define TARGET_BUILTIN_DECL tilepro_builtin_decl
5080 #undef TARGET_EXPAND_BUILTIN
5081 #define TARGET_EXPAND_BUILTIN tilepro_expand_builtin
5083 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5084 #define TARGET_CONDITIONAL_REGISTER_USAGE tilepro_conditional_register_usage
5086 #undef TARGET_FRAME_POINTER_REQUIRED
5087 #define TARGET_FRAME_POINTER_REQUIRED tilepro_frame_pointer_required
5089 #undef TARGET_DELAY_SCHED2
5090 #define TARGET_DELAY_SCHED2 true
5092 #undef TARGET_DELAY_VARTRACK
5093 #define TARGET_DELAY_VARTRACK true
5095 #undef TARGET_SCHED_ISSUE_RATE
5096 #define TARGET_SCHED_ISSUE_RATE tilepro_issue_rate
5098 #undef TARGET_SCHED_ADJUST_COST
5099 #define TARGET_SCHED_ADJUST_COST tilepro_sched_adjust_cost
5101 #undef TARGET_MACHINE_DEPENDENT_REORG
5102 #define TARGET_MACHINE_DEPENDENT_REORG tilepro_reorg
5104 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5105 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5106 hook_bool_const_tree_hwi_hwi_const_tree_true
5108 #undef TARGET_ASM_OUTPUT_MI_THUNK
5109 #define TARGET_ASM_OUTPUT_MI_THUNK tilepro_asm_output_mi_thunk
5111 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5112 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilepro_asm_trampoline_template
5114 #undef TARGET_TRAMPOLINE_INIT
5115 #define TARGET_TRAMPOLINE_INIT tilepro_trampoline_init
5117 #undef TARGET_PRINT_OPERAND
5118 #define TARGET_PRINT_OPERAND tilepro_print_operand
5120 #undef TARGET_PRINT_OPERAND_ADDRESS
5121 #define TARGET_PRINT_OPERAND_ADDRESS tilepro_print_operand_address
5123 #undef TARGET_ASM_FILE_END
5124 #define TARGET_ASM_FILE_END tilepro_file_end
5126 #undef TARGET_CAN_USE_DOLOOP_P
5127 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
5129 struct gcc_target targetm
= TARGET_INITIALIZER
;
5131 #include "gt-tilepro.h"