/* Subroutines for insn-output.c for NEC V850 series
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <ctype.h>
#include "config.h"
+#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
#include "recog.h"
#include "expr.h"
-#include "obstack.h"
+#include "function.h"
#include "toplev.h"
+#include "cpplib.h"
+#include "c-lex.h"
+#include "ggc.h"
+#include "integrate.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
#ifndef streq
#define streq(a,b) (strcmp (a, b) == 0)
#endif
-/* Function prototypes that cannot exist in v850.h due to dependency
- compilcations. */
-extern rtx function_arg
- PROTO ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
-extern int function_arg_partial_nregs
- PROTO ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
-extern void asm_file_start PROTO ((FILE *));
-extern void print_operand PROTO ((FILE *, rtx, int ));
-extern void print_operand_address PROTO ((FILE *, rtx));
-extern void v850_output_aligned_bss
- PROTO ((FILE *, tree, char *, int, int));
-extern void v850_output_common
- PROTO ((FILE *, tree, char *, int, int));
-extern void v850_output_local
- PROTO ((FILE *, tree, char *, int, int));
-extern int const_costs PROTO ((rtx, enum rtx_code));
-extern char * output_move_double PROTO ((rtx *));
-extern char * output_move_single PROTO ((rtx *));
-extern int ep_memory_operand
- PROTO ((rtx, enum machine_mode, int));
-extern int reg_or_0_operand PROTO ((rtx, enum machine_mode));
-extern int reg_or_int5_operand PROTO ((rtx, enum machine_mode));
-extern int call_address_operand PROTO ((rtx, enum machine_mode));
-extern int movsi_source_operand PROTO ((rtx, enum machine_mode));
-extern int power_of_two_operand PROTO ((rtx, enum machine_mode));
-extern int not_power_of_two_operand PROTO ((rtx, enum machine_mode));
-extern int special_symbolref_operand PROTO ((rtx, enum machine_mode));
-extern void v850_reorg PROTO ((rtx));
-extern void notice_update_cc PROTO ((rtx, rtx));
-extern int v850_valid_machine_decl_attribute
- PROTO ((tree, tree, tree));
-extern int v850_interrupt_function_p PROTO ((tree));
-extern int pattern_is_ok_for_prologue PROTO ((rtx, enum machine_mode));
-extern int pattern_is_ok_for_epilogue PROTO ((rtx, enum machine_mode));
-extern int register_is_ok_for_epilogue PROTO ((rtx, enum machine_mode));
-extern char * construct_save_jarl PROTO ((rtx));
-extern char * construct_restore_jr PROTO ((rtx));
-extern void v850_encode_data_area PROTO ((tree));
-extern void v850_set_default_decl_attr PROTO ((tree));
-
/* Function prototypes for stupid compilers: */
-static void const_double_split
- PROTO ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
-static int const_costs_int PROTO ((HOST_WIDE_INT, int));
-static void substitute_ep_register PROTO ((rtx, rtx, int, int, rtx *, rtx *));
-static int push_data_area PROTO ((v850_data_area));
-static int pop_data_area PROTO ((v850_data_area));
-static int parse_ghs_pragma_token PROTO ((char *));
-static int ep_memory_offset PROTO ((enum machine_mode, int));
-static int mark_current_function_as_interrupt PROTO ((void));
-static void v850_set_data_area PROTO ((tree, v850_data_area));
+static void const_double_split PARAMS ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
+static int const_costs_int PARAMS ((HOST_WIDE_INT, int));
+static void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
+static int ep_memory_offset PARAMS ((enum machine_mode, int));
+static void v850_set_data_area PARAMS ((tree, v850_data_area));
+const struct attribute_spec v850_attribute_table[];
+static tree v850_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree v850_handle_data_area_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static void v850_insert_attributes PARAMS ((tree, tree *));
+static void v850_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
+static void v850_encode_data_area PARAMS ((tree));
+static void v850_encode_section_info PARAMS ((tree, int));
+static const char *v850_strip_name_encoding PARAMS ((const char *));
/* True if the current function has anonymous arguments. */
int current_function_anonymous_args;
{ "zda", (char *)0, 0, 32768 },
};
+/* Names of the various data areas used on the v850. */
+tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
+tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
+
+/* Track the current data area set by the data area pragma (which
+ can be nested). Tested by check_default_data_area. */
+data_area_stack_element * data_area_stack = NULL;
+
/* True if we don't need to check any more if the current
- function is an interrupt handler */
+ function is an interrupt handler. */
static int v850_interrupt_cache_p = FALSE;
/* Whether current function is an interrupt handler. */
static int v850_interrupt_p = FALSE;
+\f
+/* Initialize the GCC target structure. */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE v850_attribute_table
+
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
+
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION v850_select_section
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING v850_strip_name_encoding
+
+struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Sometimes certain combinations of command options do not make
sense on a particular target machine. You can define a macro
override_options ()
{
int i;
- extern int atoi PROTO ((const char *));
+ extern int atoi PARAMS ((const char *));
/* Parse -m{s,t,z}da=nnn switches */
for (i = 0; i < (int)SMALL_MEMORY_max; i++)
{
if (small_memory[i].value)
{
- if (!isdigit (*small_memory[i].value))
- error ("%s=%s is not numeric.",
+ if (!ISDIGIT (*small_memory[i].value))
+ error ("%s=%s is not numeric",
small_memory[i].name,
small_memory[i].value);
else
{
small_memory[i].max = atoi (small_memory[i].value);
if (small_memory[i].max > small_memory[i].physical_max)
- error ("%s=%s is too large.",
+ error ("%s=%s is too large",
small_memory[i].name,
small_memory[i].value);
}
switch (cum->nbytes / UNITS_PER_WORD)
{
case 0:
- result = gen_rtx (REG, mode, 6);
+ result = gen_rtx_REG (mode, 6);
break;
case 1:
- result = gen_rtx (REG, mode, 7);
+ result = gen_rtx_REG (mode, 7);
break;
case 2:
- result = gen_rtx (REG, mode, 8);
+ result = gen_rtx_REG (mode, 8);
break;
case 3:
- result = gen_rtx (REG, mode, 9);
+ result = gen_rtx_REG (mode, 9);
break;
default:
result = 0;
case 'O':
if (special_symbolref_operand (x, VOIDmode))
{
- char* name;
+ const char *name;
if (GET_CODE (x) == SYMBOL_REF)
name = XSTR (x, 0);
case 'Q':
if (special_symbolref_operand (x, VOIDmode))
{
- char* name;
+ const char *name;
if (GET_CODE (x) == SYMBOL_REF)
name = XSTR (x, 0);
fprintf (file, reg_names[REGNO (x) + 1]);
break;
case MEM:
- print_operand_address (file,
- XEXP (adj_offsettable_operand (x, 4), 0));
+ x = XEXP (adjust_address (x, SImode, 4), 0);
+ print_operand_address (file, x);
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "[r0]");
break;
default:
{
case MEM:
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- output_address (gen_rtx (PLUS, SImode,
- gen_rtx (REG, SImode, 0),
- XEXP (x, 0)));
+ output_address (gen_rtx_PLUS (SImode, gen_rtx (REG, SImode, 0),
+ XEXP (x, 0)));
else
output_address (XEXP (x, 0));
break;
fputs (reg_names[REGNO (x)], file);
break;
case SUBREG:
- fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
+ fputs (reg_names[subreg_regno (x)], file);
break;
case CONST_INT:
case SYMBOL_REF:
case SYMBOL_REF:
if (ENCODED_NAME_P (XSTR (addr, 0)))
{
- char* name = XSTR (addr, 0);
- char* off_name;
- char* reg_name;
+ const char *name = XSTR (addr, 0);
+ const char *off_name;
+ const char *reg_name;
if (ZDA_NAME_P (name))
{
case CONST:
if (special_symbolref_operand (addr, VOIDmode))
{
- char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
- char* off_name;
- char* reg_name;
+ const char *name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
+ const char *off_name;
+ const char *reg_name;
if (ZDA_NAME_P (name))
{
/* Return appropriate code to load up a 1, 2, or 4 integer/floating
point value. */
-char *
+const char *
output_move_single (operands)
rtx *operands;
{
return "%S0st%W0 %.,%0";
}
- fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src));
+ fatal_insn ("output_move_single:", gen_rtx_SET (VOIDmode, dst, src));
return "";
}
/* Return appropriate code to load up an 8 byte integer or
floating point value */
-char *
+const char *
output_move_double (operands)
rtx *operands;
{
for (i = 0; i < 2; i++)
{
- xop[0] = gen_rtx (REG, SImode, REGNO (dst)+i);
+ xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i);
xop[1] = GEN_INT (high_low[i]);
output_asm_insn (output_move_single (xop), xop);
}
if (GET_CODE (inside) == REG)
ptrreg = REGNO (inside);
else if (GET_CODE (inside) == SUBREG)
- ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
+ ptrreg = subreg_regno (inside);
else if (GET_CODE (inside) == PLUS)
ptrreg = REGNO (XEXP (inside, 0));
else if (GET_CODE (inside) == LO_SUM)
op1 = XEXP (addr, 1);
if (GET_CODE (op1) == CONST_INT
&& INTVAL (op1) < max_offset
+ && INTVAL (op1) >= 0
&& (INTVAL (op1) & mask) == 0)
{
if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)
else if (mode == HImode)
mask = 0xffff;
else if (mode == SImode)
- mask = 0xffffffff;
+ mask = 0xffffffff;
else
return 0;
rtx *p_r1;
rtx *p_ep;
{
- rtx reg = gen_rtx (REG, Pmode, regno);
+ rtx reg = gen_rtx_REG (Pmode, regno);
rtx insn;
if (!*p_r1)
{
regs_ever_live[1] = 1;
- *p_r1 = gen_rtx (REG, Pmode, 1);
- *p_ep = gen_rtx (REG, Pmode, 30);
+ *p_r1 = gen_rtx_REG (Pmode, 1);
+ *p_ep = gen_rtx_REG (Pmode, 30);
}
if (TARGET_DEBUG)
{
rtx addr = XEXP (*p_mem, 0);
- if (GET_CODE (addr) == REG && REGNO (addr) == regno)
+ if (GET_CODE (addr) == REG && REGNO (addr) == (unsigned) regno)
*p_mem = change_address (*p_mem, VOIDmode, *p_ep);
else if (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 0)) == REG
- && REGNO (XEXP (addr, 0)) == regno
+ && REGNO (XEXP (addr, 0)) == (unsigned) regno
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& ((INTVAL (XEXP (addr, 1)))
< ep_memory_offset (GET_MODE (*p_mem),
- unsignedp)))
+ unsignedp))
+ && ((INTVAL (XEXP (addr, 1))) >= 0))
*p_mem = change_address (*p_mem, VOIDmode,
- gen_rtx (PLUS, Pmode,
- *p_ep, XEXP (addr, 1)));
+ gen_rtx_PLUS (Pmode,
+ *p_ep,
+ XEXP (addr, 1)));
}
}
}
&& SET_SRC (PATTERN (insn)) == *p_r1)
delete_insn (insn);
else
- emit_insn_before (gen_rtx (SET, Pmode, *p_r1, *p_ep), first_insn);
+ emit_insn_before (gen_rtx_SET (Pmode, *p_r1, *p_ep), first_insn);
- emit_insn_before (gen_rtx (SET, Pmode, *p_ep, reg), first_insn);
- emit_insn_before (gen_rtx (SET, Pmode, *p_ep, *p_r1), last_insn);
+ emit_insn_before (gen_rtx_SET (Pmode, *p_ep, reg), first_insn);
+ emit_insn_before (gen_rtx_SET (Pmode, *p_ep, *p_r1), last_insn);
}
\f
as a C statement to act on the code starting at INSN.
On the 850, we use it to implement the -mep mode to copy heavily used
- pointers to ep to use the implicit addressing */
+ pointers to ep to use the implicit addressing. */
void v850_reorg (start_insn)
rtx start_insn;
rtx insn;
rtx pattern;
- /* If not ep mode, just return now */
+ /* If not ep mode, just return now. */
if (!TARGET_EP)
return;
int unsignedp = FALSE;
/* We might have (SUBREG (MEM)) here, so just get rid of the
- subregs to make this code simpler. It is safe to call
- alter_subreg any time after reload. */
- if (GET_CODE (dest) == SUBREG)
- dest = alter_subreg (dest);
- if (GET_CODE (src) == SUBREG)
- src = alter_subreg (src);
+ subregs to make this code simpler. */
+ if (GET_CODE (dest) == SUBREG
+ && (GET_CODE (SUBREG_REG (dest)) == MEM
+ || GET_CODE (SUBREG_REG (dest)) == REG))
+ alter_subreg (&dest);
+ if (GET_CODE (src) == SUBREG
+ && (GET_CODE (SUBREG_REG (src)) == MEM
+ || GET_CODE (SUBREG_REG (src)) == REG))
+ alter_subreg (&src);
if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
mem = NULL_RTX;
&& GET_CODE (XEXP (addr, 0)) == REG
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& ((INTVAL (XEXP (addr, 1)))
- < ep_memory_offset (GET_MODE (mem), unsignedp)))
+ < ep_memory_offset (GET_MODE (mem), unsignedp))
+ && ((INTVAL (XEXP (addr, 1))) >= 0))
{
short_p = TRUE;
regno = REGNO (XEXP (addr, 0));
long reg_saved = 0;
/* Count the return pointer if we need to save it. */
- if (profile_flag && !call_p)
+ if (current_function_profile && !call_p)
regs_ever_live [LINK_POINTER_REGNUM] = call_p = 1;
/* Count space for the register saves. */
need to cover the possibility that such a helper function will
be used, despite the fact that there might be gaps in the list of
registers that need to be saved. To detect this we note that the
- helper functions always push at least register r29 if the link
- register is not used, and at least registers r27 - r31 if the
- link register is used (and provided that the function is not an
- interrupt handler). */
+ helper functions always push at least register r29 (provided
+ that the function is not an interrupt handler). */
if (TARGET_PROLOG_FUNCTION
- && (i == 2 || i >= 20)
- && regs_ever_live[LINK_POINTER_REGNUM] ? (i < 28) : (i < 30))
+ && (i == 2 || ((i >= 20) && (i < 30))))
{
if (i == 2)
{
int size;
long *p_reg_saved;
{
- extern int current_function_outgoing_args_size;
-
return (size
+ compute_register_save_size (p_reg_saved)
+ current_function_outgoing_args_size);
actual_fsize = compute_frame_size (size, ®_saved);
- /* Save/setup global registers for interrupt functions right now */
+ /* Save/setup global registers for interrupt functions right now. */
if (interrupt_handler)
{
- emit_insn (gen_save_interrupt ());
+ emit_insn (gen_save_interrupt ());
actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
offset = 0;
for (i = 6; i < 10; i++)
{
- emit_move_insn (gen_rtx (MEM, SImode,
- plus_constant (stack_pointer_rtx,
- offset)),
- gen_rtx (REG, SImode, i));
+ emit_move_insn (gen_rtx_MEM (SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ gen_rtx_REG (SImode, i));
offset += 4;
}
}
}
- /* Identify all of the saved registers */
+ /* Identify all of the saved registers. */
num_save = 0;
default_stack = 0;
for (i = 1; i < 31; i++)
{
if (((1L << i) & reg_saved) != 0)
- save_regs[num_save++] = gen_rtx (REG, Pmode, i);
+ save_regs[num_save++] = gen_rtx_REG (Pmode, i);
}
/* If the return pointer is saved, the helper functions also allocate
16 bytes of stack for arguments to be saved in. */
if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
{
- save_regs[num_save++] = gen_rtx (REG, Pmode, LINK_POINTER_REGNUM);
+ save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
default_stack = 16;
}
stack space is allocated. */
if (save_func_len < save_normal_len)
{
- save_all = gen_rtx (PARALLEL, VOIDmode,
- rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
- XVECEXP (save_all, 0, 0) = gen_rtx (SET, VOIDmode,
- stack_pointer_rtx,
- gen_rtx (PLUS, Pmode,
- stack_pointer_rtx,
- GEN_INT (-alloc_stack)));
+ save_all = gen_rtx_PARALLEL
+ (VOIDmode,
+ rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
+
+ XVECEXP (save_all, 0, 0)
+ = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx, -alloc_stack));
if (TARGET_V850)
{
- XVECEXP (save_all, 0, num_save + 1)
- = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 10));
+ XVECEXP (save_all, 0, num_save+1)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
}
offset = - default_stack;
for (i = 0; i < num_save; i++)
{
- XVECEXP (save_all, 0, i + 1)
- = gen_rtx (SET, VOIDmode,
- gen_rtx (MEM, Pmode,
- plus_constant (stack_pointer_rtx, offset)),
- save_regs[i]);
+ XVECEXP (save_all, 0, i+1)
+ = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ save_regs[i]);
offset -= 4;
}
- code = recog (save_all, NULL_RTX, NULL_PTR);
+ code = recog (save_all, NULL_RTX, NULL);
if (code >= 0)
{
rtx insn = emit_insn (save_all);
/* Save the return pointer first. */
if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)
{
- emit_move_insn (gen_rtx (MEM, SImode,
- plus_constant (stack_pointer_rtx,
- offset)),
+ emit_move_insn (gen_rtx_MEM (SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
save_regs[--num_save]);
offset -= 4;
}
for (i = 0; i < num_save; i++)
{
- emit_move_insn (gen_rtx (MEM, SImode,
- plus_constant (stack_pointer_rtx,
- offset)),
+ emit_move_insn (gen_rtx_MEM (SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
save_regs[i]);
offset -= 4;
}
GEN_INT (-diff)));
else
{
- rtx reg = gen_rtx (REG, Pmode, 12);
+ rtx reg = gen_rtx_REG (Pmode, 12);
emit_move_insn (reg, GEN_INT (-diff));
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
}
if (frame_pointer_needed)
emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
- /* Identify all of the saved registers */
+ /* Identify all of the saved registers. */
num_restore = 0;
default_stack = 0;
for (i = 1; i < 31; i++)
{
if (((1L << i) & reg_saved) != 0)
- restore_regs[num_restore++] = gen_rtx (REG, Pmode, i);
+ restore_regs[num_restore++] = gen_rtx_REG (Pmode, i);
}
/* If the return pointer is saved, the helper functions also allocate
16 bytes of stack for arguments to be saved in. */
if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
{
- restore_regs[num_restore++] = gen_rtx (REG, Pmode, LINK_POINTER_REGNUM);
+ restore_regs[num_restore++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
default_stack = 16;
}
/* See if we have an insn that restores the particular registers we
want to. */
restore_all = NULL_RTX;
- if (TARGET_PROLOG_FUNCTION && num_restore > 0
+
+ if (TARGET_PROLOG_FUNCTION
+ && num_restore > 0
&& actual_fsize >= default_stack
&& !interrupt_handler)
{
if (unalloc_stack)
restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
- /* see if we would have used ep to restore the registers */
+ /* See if we would have used ep to restore the registers. */
if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255)
restore_normal_len = (3 * 2) + (2 * num_restore);
else
/* Don't bother checking if we don't actually save any space. */
if (restore_func_len < restore_normal_len)
{
- restore_all = gen_rtx (PARALLEL, VOIDmode,
- rtvec_alloc (num_restore + 2));
- XVECEXP (restore_all, 0, 0) = gen_rtx (RETURN, VOIDmode);
+ restore_all = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (num_restore + 2));
+ XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
XVECEXP (restore_all, 0, 1)
- = gen_rtx (SET, VOIDmode, stack_pointer_rtx,
- gen_rtx (PLUS, Pmode,
- stack_pointer_rtx,
- GEN_INT (alloc_stack)));
+ = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (alloc_stack)));
offset = alloc_stack - 4;
for (i = 0; i < num_restore; i++)
{
XVECEXP (restore_all, 0, i+2)
- = gen_rtx (SET, VOIDmode,
- restore_regs[i],
- gen_rtx (MEM, Pmode,
- plus_constant
- (stack_pointer_rtx, offset)));
+ = gen_rtx_SET (VOIDmode,
+ restore_regs[i],
+ gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
offset -= 4;
}
- code = recog (restore_all, NULL_RTX, NULL_PTR);
+ code = recog (restore_all, NULL_RTX, NULL);
+
if (code >= 0)
{
rtx insn;
GEN_INT (actual_fsize)));
else
{
- rtx reg = gen_rtx (REG, Pmode, 12);
+ rtx reg = gen_rtx_REG (Pmode, 12);
emit_move_insn (reg, GEN_INT (actual_fsize));
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
}
/* If no epilog save function is available, restore the registers the
- old fashioned way (one by one). */
+ old fashioned way (one by one). */
if (!restore_all)
{
/* If the stack is large, we need to cut it down in 2 pieces. */
else
init_stack_free = actual_fsize;
- /* Deallocate the rest of the stack if it is > 32K or if extra stack
- was allocated for an interrupt handler that makes a call. */
- if (actual_fsize > init_stack_free
- || (interrupt_handler && actual_fsize))
+ /* Deallocate the rest of the stack if it is > 32K. */
+ if (actual_fsize > init_stack_free)
{
int diff;
diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);
-
+
if (CONST_OK_FOR_K (diff))
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (diff)));
else
{
- rtx reg = gen_rtx (REG, Pmode, 12);
+ rtx reg = gen_rtx_REG (Pmode, 12);
emit_move_insn (reg, GEN_INT (diff));
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
}
else
{
- /* Restore registers from the beginning of the stack frame */
+ /* Restore registers from the beginning of the stack frame. */
offset = init_stack_free - 4;
/* Restore the return pointer first. */
&& REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM)
{
emit_move_insn (restore_regs[--num_restore],
- gen_rtx (MEM, SImode,
- plus_constant (stack_pointer_rtx,
- offset)));
+ gen_rtx_MEM (SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
offset -= 4;
}
for (i = 0; i < num_restore; i++)
{
emit_move_insn (restore_regs[i],
- gen_rtx (MEM, SImode,
- plus_constant (stack_pointer_rtx,
- offset)));
+ gen_rtx_MEM (SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
+ emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i]));
offset -= 4;
}
case CC_NONE_0HIT:
/* Insn does not change CC, but the 0'th operand has been changed. */
if (cc_status.value1 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
+ && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
cc_status.value1 = 0;
break;
case CC_SET_ZN:
- /* Insn sets the Z,N flags of CC to recog_operand[0].
+ /* Insn sets the Z,N flags of CC to recog_data.operand[0].
V,C is in an unusable state. */
CC_STATUS_INIT;
cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
- cc_status.value1 = recog_operand[0];
+ cc_status.value1 = recog_data.operand[0];
break;
case CC_SET_ZNV:
- /* Insn sets the Z,N,V flags of CC to recog_operand[0].
+ /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
C is in an unusable state. */
CC_STATUS_INIT;
cc_status.flags |= CC_NO_CARRY;
- cc_status.value1 = recog_operand[0];
+ cc_status.value1 = recog_data.operand[0];
break;
case CC_COMPARE:
v850_get_data_area (decl)
tree decl;
{
- if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+ if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_SDA;
- if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+ if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_TDA;
- if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
+ if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_ZDA;
return DATA_AREA_NORMAL;
return;
}
- DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
- (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
+ DECL_ATTRIBUTES (decl) = tree_cons
+ (name, NULL, DECL_ATTRIBUTES (decl));
}
\f
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ARGS are the arguments supplied with ATTR. */
+const struct attribute_spec v850_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute },
+ { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute },
+ { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute },
+ { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute },
+ { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
-int
-v850_valid_machine_decl_attribute (decl, attr, args)
- tree decl;
- tree attr;
- tree args;
+/* Handle an "interrupt" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "sda", "tda" or "zda" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+v850_handle_data_area_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
v850_data_area data_area;
v850_data_area area;
-
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("interrupt_handler", attr)
- || is_attribute_p ("interrupt", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
+ tree decl = *node;
/* Implement data area attribute. */
- if (is_attribute_p ("sda", attr))
+ if (is_attribute_p ("sda", name))
data_area = DATA_AREA_SDA;
- else if (is_attribute_p ("tda", attr))
+ else if (is_attribute_p ("tda", name))
data_area = DATA_AREA_TDA;
- else if (is_attribute_p ("zda", attr))
+ else if (is_attribute_p ("zda", name))
data_area = DATA_AREA_ZDA;
else
- return 0;
+ abort ();
switch (TREE_CODE (decl))
{
case VAR_DECL:
if (current_function_decl != NULL_TREE)
- error_with_decl (decl, "\
+ {
+ error_with_decl (decl, "\
a data area attribute cannot be specified for local variables");
-
+ *no_add_attrs = true;
+ }
+
/* Drop through. */
case FUNCTION_DECL:
area = v850_get_data_area (decl);
if (area != DATA_AREA_NORMAL && data_area != area)
- error_with_decl (decl, "\
+ {
+ error_with_decl (decl, "\
data area of '%s' conflicts with previous declaration");
-
- return 1;
+ *no_add_attrs = true;
+ }
+ break;
default:
break;
}
-
- return 0;
+
+ return NULL_TREE;
}
\f
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
- a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
+ a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
if (a != NULL_TREE)
ret = 1;
else
{
- a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
+ a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
ret = a != NULL_TREE;
}
}
\f
-extern struct obstack * saveable_obstack;
-
-void
+static void
v850_encode_data_area (decl)
tree decl;
{
- char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
int len = strlen (str);
char * newstr;
{
if (DECL_SECTION_NAME (decl))
{
- char * name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
if (streq (name, ".zdata") || streq (name, ".zbss"))
v850_set_data_area (decl, DATA_AREA_ZDA);
return;
}
- newstr = obstack_alloc (saveable_obstack, len + 2);
+ newstr = alloca (len + 2);
strcpy (newstr + 1, str);
default: abort ();
}
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
+ XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 2);
+}
+
+static void
+v850_encode_section_info (decl, first)
+ tree decl;
+ int first;
+{
+ if (first && TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ v850_encode_data_area (decl);
+}
+
+static const char *
+v850_strip_name_encoding (str)
+ const char *str;
+{
+ return str + (ENCODED_NAME_P (str) || *str == '*');
}
/* Return true if the given RTX is a register which can be restored
if (count <= 2)
{
- error ("Bogus JR construction: %d\n", count);
+ error ("bogus JR construction: %d\n", count);
return NULL;
}
/* Make sure that the amount we are popping either 0 or 16 bytes. */
if (stack_bytes != 0 && stack_bytes != 16)
{
- error ("Bad amount of stack space removal: %d", stack_bytes);
+ error ("bad amount of stack space removal: %d", stack_bytes);
return NULL;
}
be popping more registers than is strictly necessary, but
it does save code space. */
- if (first == last)
- sprintf (buff, "jr __return_%s", reg_names [first]);
+ if (TARGET_LONG_CALLS)
+ {
+ char name[40];
+
+ if (first == last)
+ sprintf (name, "__return_%s", reg_names [first]);
+ else
+ sprintf (name, "__return_%s_%s", reg_names [first], reg_names [last]);
+
+ sprintf (buff, "movhi hi(%s), r0, r6\n\tmovea lo(%s), r6, r6\n\tjmp r6",
+ name, name);
+ }
else
- sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
-
+ {
+ if (first == last)
+ sprintf (buff, "jr __return_%s", reg_names [first]);
+ else
+ sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
+ }
+
return buff;
}
if (count <= 2)
{
- error ("Bogus JARL construction: %d\n", count);
+ error ("bogus JARL construction: %d\n", count);
return NULL;
}
/* Make sure that the amount we are popping either 0 or 16 bytes. */
if (stack_bytes != 0 && stack_bytes != -16)
{
- error ("Bad amount of stack space removal: %d", stack_bytes);
+ error ("bad amount of stack space removal: %d", stack_bytes);
return NULL;
}
be pushing more registers than is strictly necessary, but
it does save code space. */
- if (first == last)
- sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+ if (TARGET_LONG_CALLS)
+ {
+ char name[40];
+
+ if (first == last)
+ sprintf (name, "__save_%s", reg_names [first]);
+ else
+ sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);
+
+ sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
+ name, name);
+ }
else
- sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
- reg_names [last]);
+ {
+ if (first == last)
+ sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+ else
+ sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
+ reg_names [last]);
+ }
return buff;
}
v850_output_aligned_bss (file, decl, name, size, align)
FILE * file;
tree decl;
- char * name;
+ const char * name;
int size;
int align;
{
v850_output_common (file, decl, name, size, align)
FILE * file;
tree decl;
- char * name;
+ const char * name;
int size;
int align;
{
if (decl == NULL_TREE)
{
- fprintf (file, "\t%s\t", COMMON_ASM_OP);
+ fprintf (file, "%s", COMMON_ASM_OP);
}
else
{
switch (v850_get_data_area (decl))
{
case DATA_AREA_ZDA:
- fprintf (file, "\t%s\t", ZCOMMON_ASM_OP);
+ fprintf (file, "%s", ZCOMMON_ASM_OP);
break;
case DATA_AREA_SDA:
- fprintf (file, "\t%s\t", SCOMMON_ASM_OP);
+ fprintf (file, "%s", SCOMMON_ASM_OP);
break;
case DATA_AREA_TDA:
- fprintf (file, "\t%s\t", TCOMMON_ASM_OP);
+ fprintf (file, "%s", TCOMMON_ASM_OP);
break;
default:
- fprintf (file, "\t%s\t", COMMON_ASM_OP);
+ fprintf (file, "%s", COMMON_ASM_OP);
break;
}
}
v850_output_local (file, decl, name, size, align)
FILE * file;
tree decl;
- char * name;
+ const char * name;
int size;
int align;
{
- fprintf (file, "\t%s\t", LOCAL_ASM_OP);
+ fprintf (file, "%s", LOCAL_ASM_OP);
assemble_name (file, name);
fprintf (file, "\n");
ASM_OUTPUT_ALIGNED_DECL_COMMON (file, decl, name, size, align);
}
-/* The following code is for handling pragmas supported by the
- v850 compiler produced by Green Hills Software. This is at
- the specific request of a customer. */
-
-/* Track the current data area set by the data area pragma (which
- can be nested). Tested by check_default_data_area. */
-
-typedef struct data_area_stack_element
-{
- struct data_area_stack_element * prev;
- v850_data_area data_area; /* current default data area. */
-} data_area_stack_element;
-
-static data_area_stack_element * data_area_stack = NULL;
-
-/* Names of the various data areas used on the v850. */
-static tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
-static tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
-
-/* Push a data area onto the stack. */
-static int
-push_data_area (data_area)
- v850_data_area data_area;
-{
- data_area_stack_element * elem;
-
- elem = (data_area_stack_element *) xmalloc (sizeof (* elem));
-
- if (elem == NULL)
- return 0;
-
- elem->prev = data_area_stack;
- elem->data_area = data_area;
-
- data_area_stack = elem;
-
- return 1;
-}
-
-/* Remove a data area from the stack. */
-static int
-pop_data_area (data_area)
- v850_data_area data_area;
-{
- if (data_area_stack == NULL)
- warning ("#pragma GHS endXXXX found without previous startXXX");
- else if (data_area != data_area_stack->data_area)
- warning ("#pragma GHS endXXX does not match previous startXXX");
- else
- {
- data_area_stack_element * elem;
-
- elem = data_area_stack;
- data_area_stack = data_area_stack->prev;
-
- free (elem);
-
- return 1;
- }
-
- return 0;
-}
-
-/* Set the machine specific 'interrupt' attribute on the current function. */
-static int
-mark_current_function_as_interrupt ()
-{
- tree name;
-
- if (current_function_decl == NULL_TREE)
- {
- warning ("Cannot set interrupt attribute: no current function");
- return 0;
- }
-
- name = get_identifier ("interrupt");
-
- if (name == NULL_TREE || TREE_CODE (name) != IDENTIFIER_NODE)
- {
- warning ("Cannot set interrupt attribute: no such identifier");
- return 0;
- }
-
- return valid_machine_attribute
- (name, NULL_TREE, current_function_decl, NULL_TREE);
-}
-
-/* Parse STRING as part of a GHS pragma.
- Returns 0 if the pragma has been parsed and there was a problem,
- non-zero in all other cases. */
-static int
-parse_ghs_pragma_token (string)
- char * string;
-{
- static enum v850_pragma_state state = V850_PS_START;
- static enum v850_pragma_type type = V850_PT_UNKNOWN;
- static v850_data_area data_area = DATA_AREA_NORMAL;
- static char * data_area_name;
- static enum GHS_section_kind GHS_section_kind = GHS_SECTION_KIND_DEFAULT;
-
- /* If the string is NULL then we have reached the end of the
- #pragma construct. Make sure that we are in an end state, and
- then implement the pragma's directive. */
- if (string == NULL)
- {
- int ret_val = 1;
-
- if (state != V850_PS_SHOULD_BE_DONE
- && state != V850_PS_MAYBE_COMMA
- && state != V850_PS_MAYBE_SECTION_NAME)
- {
- if (state != V850_PS_BAD)
- warning ("Incomplete #pragma ghs");
-
- ret_val = 0;
- }
- else switch (type)
- {
- case V850_PT_UNKNOWN:
- warning ("Nothing follows #pragma ghs");
- ret_val = 0;
- break;
-
- case V850_PT_INTERRUPT:
- ret_val = mark_current_function_as_interrupt ();
- break;
-
- case V850_PT_SECTION:
- /* If a section kind has not been specified, then reset
- all section names back to their defaults. */
- if (GHS_section_kind == GHS_SECTION_KIND_DEFAULT)
- {
- int i;
-
- for (i = COUNT_OF_GHS_SECTION_KINDS; i--;)
- GHS_current_section_names [i] = NULL;
- }
- /* If a section has been specified, then this will be handled
- by check_default_section_name (). */
- break;
-
- case V850_PT_START_SECTION:
- ret_val = push_data_area (data_area);
- break;
-
- case V850_PT_END_SECTION:
- ret_val = pop_data_area (data_area);
- break;
- }
-
- state = V850_PS_START;
- type = V850_PT_UNKNOWN;
-
- return ret_val;
- }
-
- switch (state)
- {
- case V850_PS_START:
- data_area = DATA_AREA_NORMAL;
- data_area_name = NULL;
-
- if (streq (string, "interrupt"))
- {
- type = V850_PT_INTERRUPT;
- state = V850_PS_SHOULD_BE_DONE;
- }
- else if (streq (string, "section"))
- {
- type = V850_PT_SECTION;
- state = V850_PS_MAYBE_SECTION_NAME;
- GHS_section_kind = GHS_SECTION_KIND_DEFAULT;
- }
- else if (streq (string, "starttda"))
- {
- type = V850_PT_START_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_TDA;
- }
- else if (streq (string, "endtda"))
- {
- type = V850_PT_END_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_TDA;
- }
- else if (streq (string, "startsda"))
- {
- type = V850_PT_START_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_SDA;
- }
- else if (streq (string, "endsda"))
- {
- type = V850_PT_END_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_SDA;
- }
- else if (streq (string, "startzda"))
- {
- type = V850_PT_START_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_ZDA;
- }
- else if (streq (string, "endzda"))
- {
- type = V850_PT_END_SECTION;
- state = V850_PS_SHOULD_BE_DONE;
- data_area = DATA_AREA_ZDA;
- }
- else
- {
- warning ("Unrecognised GHS pragma: '%s'\n", string);
- state = V850_PS_BAD;
- }
- break;
-
- case V850_PS_SHOULD_BE_DONE:
- warning ("Extra text after valid #pragma: '%s'", string);
- state = V850_PS_BAD;
- break;
-
- case V850_PS_BAD:
- /* Ignore tokens in a pragma that has been diagnosed as being corrupt. */
- break;
-
- case V850_PS_MAYBE_SECTION_NAME:
- state = V850_PS_EXPECTING_EQUALS;
-
- if (streq (string, "data")) GHS_section_kind = GHS_SECTION_KIND_DATA;
- else if (streq (string, "text")) GHS_section_kind = GHS_SECTION_KIND_TEXT;
- else if (streq (string, "rodata")) GHS_section_kind = GHS_SECTION_KIND_RODATA;
- else if (streq (string, "const")) GHS_section_kind = GHS_SECTION_KIND_RODATA;
- else if (streq (string, "rosdata")) GHS_section_kind = GHS_SECTION_KIND_ROSDATA;
- else if (streq (string, "rozdata")) GHS_section_kind = GHS_SECTION_KIND_ROZDATA;
- else if (streq (string, "sdata")) GHS_section_kind = GHS_SECTION_KIND_SDATA;
- else if (streq (string, "tdata")) GHS_section_kind = GHS_SECTION_KIND_TDATA;
- else if (streq (string, "zdata")) GHS_section_kind = GHS_SECTION_KIND_ZDATA;
- /* According to GHS beta documentation, the following should not be allowed! */
- else if (streq (string, "bss")) GHS_section_kind = GHS_SECTION_KIND_BSS;
- else if (streq (string, "zbss")) GHS_section_kind = GHS_SECTION_KIND_ZDATA;
- else
- {
- warning ("Unrecognised section name '%s' in GHS section pragma",
- string);
- state = V850_PS_BAD;
- }
- break;
-
- case V850_PS_EXPECTING_EQUALS:
- if (streq (string, "="))
- state = V850_PS_EXPECTING_SECTION_ALIAS;
- else
- {
- warning ("Missing '=' in GHS section pragma");
- state = V850_PS_BAD;
- }
- break;
-
- case V850_PS_EXPECTING_SECTION_ALIAS:
- if (streq (string, "default"))
- GHS_current_section_names [GHS_section_kind] = NULL;
- else
- GHS_current_section_names [GHS_section_kind] =
- build_string (strlen (string) + 1, string);
-
- state = V850_PS_MAYBE_COMMA;
- break;
-
- case V850_PS_MAYBE_COMMA:
- if (streq (string, ","))
- state = V850_PS_MAYBE_SECTION_NAME;
- else
- {
- warning
- ("Malformed GHS section pragma: found '%s' instead of a comma",
- string);
- state = V850_PS_BAD;
- }
- break;
- }
-
- return 1;
-}
-
-/* Handle the parsing of an entire GHS pragma. */
-int
-v850_handle_pragma (p_getc, p_ungetc, name)
- int (* p_getc) PROTO ((void));
- void (* p_ungetc) PROTO ((int));
- char * name;
-{
- /* Parse characters in the input stream until:
-
- * end of line
- * end of file
- * a complete GHS pragma has been parsed
- * a corrupted GHS pragma has been parsed
- * an unknown pragma is encountered.
-
- If an unknown pragma is encountered, we must return with
- the input stream in the same state as upon entry to this function.
-
- The first token in the input stream has already been parsed
- for us, and is passed as 'name'. */
-
- if (! streq (name, "ghs"))
- return 0;
-
- /* We now know that we are parsing a GHS pragma, so we do
- not need to preserve the original input stream state. */
- for (;;)
- {
- static char buffer [128];
- int c;
- char * buff;
-
- /* Skip white space. */
- do
- c = p_getc ();
- while (c == ' ' || c == '\t');
-
- p_ungetc (c);
-
- if (c == '\n' || c == EOF || c == '\r')
- return parse_ghs_pragma_token (NULL);
-
- /* Read next word. We have to do the parsing ourselves, rather
- than calling yylex() because we can be built with front ends
- that do not provide such functions. */
- buff = buffer;
- * buff ++ = (c = p_getc ());
-
- switch (c)
- {
- case ',':
- case '=':
- * buff ++ = (c = p_getc ());
- break;
-
- case '"':
- /* Skip opening double parenthesis. */
- -- buff;
-
- /* Read string. */
- do
- * buff ++ = (c = p_getc ());
- while (c != EOF && isascii (c)
- && (isalnum (c) || c == '_' || c == '.' || c == ' ')
- && (buff < buffer + 126));
-
- if (c != '"')
- warning ("Missing trailing \" in #pragma ghs");
- else
- c = p_getc ();
- break;
-
- default:
- while (c != EOF && isascii (c)
- && (isalnum (c) || c == '_' || c == '.')
- && (buff < buffer + 126))
- * buff ++ = (c = p_getc ());
- break;
- }
-
- p_ungetc (c);
-
- /* If nothing was read then terminate the parsing. */
- if (buff == buffer + 1)
- return parse_ghs_pragma_token (NULL);
-
- /* Parse and continue. */
- * -- buff = 0;
-
- parse_ghs_pragma_token (buffer);
- }
-}
-
/* Add data area to the given declaration if a ghs data area pragma is
currently in effect (#pragma ghs startXXX/endXXX). */
-void
-v850_set_default_decl_attr (decl)
+static void
+v850_insert_attributes (decl, attr_ptr)
tree decl;
+ tree *attr_ptr ATTRIBUTE_UNUSED;
{
if (data_area_stack
&& data_area_stack->data_area
}
}
}
+\f
+/* Implement `va_arg'. */
+
+rtx
+v850_va_arg (valist, type)
+ tree valist, type;
+{
+ HOST_WIDE_INT size, rsize;
+ tree addr, incr;
+ rtx addr_rtx;
+ int indirect;
+
+ /* Round up sizeof(type) to a word. */
+ size = int_size_in_bytes (type);
+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+ indirect = 0;
+
+ if (size > 8)
+ {
+ size = rsize = UNITS_PER_WORD;
+ indirect = 1;
+ }
+
+ addr = save_expr (valist);
+ incr = fold (build (PLUS_EXPR, ptr_type_node, addr,
+ build_int_2 (rsize, 0)));
+
+ incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
+ TREE_SIDE_EFFECTS (incr) = 1;
+ expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
+
+ if (indirect)
+ {
+ addr_rtx = force_reg (Pmode, addr_rtx);
+ addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
+ set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
+ }
+
+ return addr_rtx;
+}
+\f
+/* Return an RTX indicating where the return address to the
+ calling function can be found. */
+
+rtx
+v850_return_addr (count)
+ int count;
+{
+ if (count != 0)
+ return const0_rtx;
+
+ return get_hard_reg_initial_val (Pmode, LINK_POINTER_REGNUM);
+}
+\f
+static void
+v850_select_section (exp, reloc, align)
+ tree exp;
+ int reloc;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (TREE_CODE (exp) == VAR_DECL)
+ {
+ int is_const;
+ if (!TREE_READONLY (exp)
+ || TREE_SIDE_EFFECTS (exp)
+ || !DECL_INITIAL (exp)
+ || (DECL_INITIAL (exp) != error_mark_node
+ && !TREE_CONSTANT (DECL_INITIAL (exp))))
+ is_const = FALSE;
+ else
+ is_const = TRUE;
+
+ switch (v850_get_data_area (exp))
+ {
+ case DATA_AREA_ZDA:
+ if (is_const)
+ rozdata_section ();
+ else
+ zdata_section ();
+ break;
+
+ case DATA_AREA_TDA:
+ tdata_section ();
+ break;
+
+ case DATA_AREA_SDA:
+ if (is_const)
+ rosdata_section ();
+ else
+ sdata_section ();
+ break;
+
+ default:
+ if (is_const)
+ readonly_data_section ();
+ else
+ data_section ();
+ break;
+ }
+ }
+ else if (TREE_CODE (exp) == STRING_CST)
+ {
+ if (! flag_writable_strings)
+ readonly_data_section ();
+ else
+ data_section ();
+ }
+ else
+ readonly_data_section ();
+}