#include "function.h"
#include "toplev.h"
#include "optabs.h"
+#include "output.h"
#include "libfuncs.h"
+#include "ggc.h"
#include "target.h"
#include "target-def.h"
+#include "langhooks.h"
/* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order
#define LARGEST_MOVE_RATIO 15
/* Define the structure for the machine field in struct function. */
-struct machine_function
+struct machine_function GTY(())
{
int accesses_prev_frame;
};
NO_REGS, NO_REGS, NO_REGS, NO_REGS,
};
+static int b4const_or_zero PARAMS ((int));
+static enum internal_test map_test_to_internal_test PARAMS ((enum rtx_code));
+static rtx gen_int_relational PARAMS ((enum rtx_code, rtx, rtx, int *));
+static rtx gen_float_relational PARAMS ((enum rtx_code, rtx, rtx));
+static rtx gen_conditional_move PARAMS ((rtx));
+static rtx fixup_subreg_mem PARAMS ((rtx x));
+static enum machine_mode xtensa_find_mode_for_size PARAMS ((unsigned));
+static struct machine_function * xtensa_init_machine_status PARAMS ((void));
+static void printx PARAMS ((FILE *, signed int));
+static void xtensa_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static void xtensa_encode_section_info PARAMS ((tree, int));
+
+static rtx frame_size_const;
+static int current_function_arg_words;
+static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
+ REG_ALLOC_ORDER;
+\f
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to allocate.
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-static int b4const_or_zero PARAMS ((int));
-static enum internal_test map_test_to_internal_test PARAMS ((enum rtx_code));
-static rtx gen_int_relational PARAMS ((enum rtx_code, rtx, rtx, int *));
-static rtx gen_float_relational PARAMS ((enum rtx_code, rtx, rtx));
-static rtx gen_conditional_move PARAMS ((rtx));
-static rtx fixup_subreg_mem PARAMS ((rtx x));
-static enum machine_mode xtensa_find_mode_for_size PARAMS ((unsigned));
-static void xtensa_init_machine_status PARAMS ((struct function *p));
-static void xtensa_free_machine_status PARAMS ((struct function *p));
-static void printx PARAMS ((FILE *, signed int));
-static rtx frame_size_const;
-static int current_function_arg_words;
-static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
- REG_ALLOC_ORDER;
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO xtensa_encode_section_info
+struct gcc_target targetm = TARGET_INITIALIZER;
+\f
/*
* Functions to test Xtensa immediate operand validity.
if (num_pieces >= move_ratio)
return 0;
- /* make sure the memory addresses are valid */
+ /* make sure the memory addresses are valid */
operands[0] = validize_mem (dest);
operands[1] = validize_mem (src);
}
-static void
-xtensa_init_machine_status (p)
- struct function *p;
-{
- p->machine = (struct machine_function *)
- xcalloc (1, sizeof (struct machine_function));
-}
-
-
-static void
-xtensa_free_machine_status (p)
- struct function *p;
+static struct machine_function *
+xtensa_init_machine_status ()
{
- free (p->machine);
- p->machine = NULL;
+ return ggc_alloc_cleared (sizeof (struct machine_function));
}
int callop;
rtx *operands;
{
- char *result = (char *) malloc (64);
+ static char result[64];
rtx tgt = operands[callop];
if (GET_CODE (tgt) == CONST_INT)
}
init_machine_status = xtensa_init_machine_status;
- free_machine_status = xtensa_free_machine_status;
/* Check PIC settings. There's no need for -fPIC on Xtensa and
some targets need to always use PIC. */
/* A C compound statement to output to stdio stream STREAM the
assembler syntax for an instruction operand that is a memory
- reference whose address is ADDR. ADDR is an RTL expression.
-
- On some machines, the syntax for a symbolic address depends on
- the section that the address refers to. On these machines,
- define the macro 'ENCODE_SECTION_INFO' to store the information
- into the 'symbol_ref', and then check for it here. */
+ reference whose address is ADDR. ADDR is an RTL expression. */
void
print_operand_address (file, addr)
tree
xtensa_build_va_list (void)
{
- tree f_stk, f_reg, f_ndx, record;
+ tree f_stk, f_reg, f_ndx, record, type_decl;
- record = make_node (RECORD_TYPE);
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
+ type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
ptr_type_node);
DECL_FIELD_CONTEXT (f_reg) = record;
DECL_FIELD_CONTEXT (f_ndx) = record;
+ TREE_CHAIN (record) = type_decl;
+ TYPE_NAME (record) = type_decl;
TYPE_FIELDS (record) = f_stk;
TREE_CHAIN (f_stk) = f_reg;
TREE_CHAIN (f_reg) = f_ndx;
/* allocate the general-purpose register space */
gp_regs = assign_stack_local
(BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
- MEM_IN_STRUCT_P (gp_regs) = 1;
- RTX_UNCHANGING_P (gp_regs) = 1;
- RTX_UNCHANGING_P (XEXP (gp_regs, 0)) = 1;
+ set_mem_alias_set (gp_regs, get_varargs_alias_set ());
/* Now store the incoming registers. */
dest = change_address (gp_regs, SImode,
/* Check if the argument is in registers:
- if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
+ if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4
+ && !MUST_PASS_IN_STACK (type))
__array = (AP).__va_reg;
*/
- lab_false = gen_label_rtx ();
- lab_over = gen_label_rtx ();
array = gen_reg_rtx (Pmode);
- emit_cmp_and_jump_insns (expand_expr (ndx, NULL_RTX, SImode, EXPAND_NORMAL),
- GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD),
- GT, const1_rtx, SImode, 0, lab_false);
+ lab_over = NULL_RTX;
+ if (!MUST_PASS_IN_STACK (VOIDmode, type))
+ {
+ lab_false = gen_label_rtx ();
+ lab_over = gen_label_rtx ();
- r = expand_expr (reg, array, Pmode, EXPAND_NORMAL);
- if (r != array)
- emit_move_insn (array, r);
+ emit_cmp_and_jump_insns (expand_expr (ndx, NULL_RTX, SImode,
+ EXPAND_NORMAL),
+ GEN_INT (MAX_ARGS_IN_REGISTERS
+ * UNITS_PER_WORD),
+ GT, const1_rtx, SImode, 0, lab_false);
- emit_jump_insn (gen_jump (lab_over));
- emit_barrier ();
- emit_label (lab_false);
+ r = expand_expr (reg, array, Pmode, EXPAND_NORMAL);
+ if (r != array)
+ emit_move_insn (array, r);
+ emit_jump_insn (gen_jump (lab_over));
+ emit_barrier ();
+ emit_label (lab_false);
+ }
/* ...otherwise, the argument is on the stack (never split between
registers and the stack -- change __va_ndx if necessary):
if (r != array)
emit_move_insn (array, r);
- emit_label (lab_over);
+ if (lab_over != NULL_RTX)
+ emit_label (lab_over);
/* Given the base array pointer (__array) and index to the subsequent
return 0;
}
+
+/* The literal pool stays with the function. */
+
+static void
+xtensa_select_rtx_section (mode, x, align)
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ rtx x ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ function_section (current_function_decl);
+}
+
+/* If we are referencing a function that is static, make the SYMBOL_REF
+ special so that we can generate direct calls to it even with -fpic. */
+
+static void
+xtensa_encode_section_info (decl, first)
+ tree decl;
+ int first ATTRIBUTE_UNUSED;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && ! TREE_PUBLIC (decl))
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+}
+
+#include "gt-xtensa.h"