Commit 3ce15347 by Nick Clifton Committed by Nick Clifton

Add support for v850 special data areas.

From-SVN: r22716
parent e6e86071
......@@ -13,6 +13,11 @@ Thu Oct 1 15:56:01 1998 Gavin Romig-Koch <gavin@cygnus.com>
Thu Oct 1 10:42:27 1998 Nick Clifton <nickc@cygnus.com>
* config/v850/v850.c: Add function prototypes.
Add support for v850 special data areas.
* config/v850/v850.h: Add support for v850 special data areas.
* c-pragma.c: Add support for HANDLE_PRAGMA_PACK and
HANDLE_PRAGMA_PACK_PUSH_POP.
(push_alignment): New function: Cache an alignment requested
......
/* Subroutines for insn-output.c for NEC V850 series
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
......@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <ctype.h>
#include "config.h"
#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
......@@ -34,8 +35,64 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "recog.h"
#include "expr.h"
#include "tree.h"
#include "obstack.h"
#include "toplev.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));
/* True if the current function has anonymous arguments. */
int current_function_anonymous_args;
......@@ -70,7 +127,7 @@ void
override_options ()
{
int i;
extern int atoi ();
extern int atoi PROTO ((const char *));
/* Parse -m{s,t,z}da=nnn switches */
for (i = 0; i < (int)SMALL_MEMORY_max; i++)
......@@ -235,6 +292,9 @@ const_double_split (x, p_high, p_low)
*p_high = CONST_DOUBLE_HIGH (x);
*p_low = CONST_DOUBLE_LOW (x);
return;
default:
break;
}
}
......@@ -437,13 +497,16 @@ print_operand (file, x, code)
case 'R': /* 2nd word of a double. */
switch (GET_CODE (x))
{
case REG:
fprintf (file, reg_names[REGNO (x) + 1]);
break;
case MEM:
print_operand_address (file,
XEXP (adj_offsettable_operand (x, 4), 0));
break;
case REG:
fprintf (file, reg_names[REGNO (x) + 1]);
break;
case MEM:
print_operand_address (file,
XEXP (adj_offsettable_operand (x, 4), 0));
break;
default:
break;
}
break;
case 'S':
......@@ -724,7 +787,8 @@ output_move_single (operands)
}
/* Return appropriate code to load up an 8 byte integer or floating point value */
/* Return appropriate code to load up an 8 byte integer or
floating point value */
char *
output_move_double (operands)
......@@ -805,10 +869,10 @@ output_move_double (operands)
/* Return maximum offset supported for a short EP memory reference of mode
MODE and signedness UNSIGNEDP. */
int
static int
ep_memory_offset (mode, unsignedp)
enum machine_mode mode;
int unsignedp;
int ATTRIBUTE_UNUSED unsignedp;
{
int max_offset = 0;
......@@ -826,6 +890,9 @@ ep_memory_offset (mode, unsignedp)
case SFmode:
max_offset = (1 << 8);
break;
default:
break;
}
return max_offset;
......@@ -920,7 +987,7 @@ reg_or_int5_operand (op, mode)
int
call_address_operand (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
/* Only registers are valid call operands if TARGET_LONG_CALLS. */
if (TARGET_LONG_CALLS)
......@@ -931,7 +998,7 @@ call_address_operand (op, mode)
int
special_symbolref_operand (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
if (GET_CODE (op) == SYMBOL_REF)
return ENCODED_NAME_P (XSTR (op, 0));
......@@ -968,7 +1035,7 @@ movsi_source_operand (op, mode)
int
power_of_two_operand (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
if (GET_CODE (op) != CONST_INT)
return 0;
......@@ -1017,7 +1084,6 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
{
rtx reg = gen_rtx (REG, Pmode, regno);
rtx insn;
int i;
if (!*p_r1)
{
......@@ -1027,7 +1093,8 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
}
if (TARGET_DEBUG)
fprintf (stderr, "Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
fprintf (stderr, "\
Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
2 * (uses - 3), uses, reg_names[regno],
IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
INSN_UID (first_insn), INSN_UID (last_insn));
......@@ -1073,7 +1140,7 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
&& GET_CODE (XEXP (addr, 0)) == REG
&& REGNO (XEXP (addr, 0)) == regno
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& (((unsigned)INTVAL (XEXP (addr, 1)))
&& ((INTVAL (XEXP (addr, 1)))
< ep_memory_offset (GET_MODE (*p_mem),
unsignedp)))
*p_mem = change_address (*p_mem, VOIDmode,
......@@ -1110,11 +1177,13 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
void v850_reorg (start_insn)
rtx start_insn;
{
struct {
struct
{
int uses;
rtx first_insn;
rtx last_insn;
} regs[FIRST_PSEUDO_REGISTER];
}
regs[FIRST_PSEUDO_REGISTER];
int i;
int use_ep = FALSE;
......@@ -1215,7 +1284,7 @@ void v850_reorg (start_insn)
else if (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 0)) == REG
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& (((unsigned)INTVAL (XEXP (addr, 1)))
&& ((INTVAL (XEXP (addr, 1)))
< ep_memory_offset (GET_MODE (mem), unsignedp)))
{
short_p = TRUE;
......@@ -1274,7 +1343,8 @@ void v850_reorg (start_insn)
{
substitute_ep_register (regs[max_regno].first_insn,
regs[max_regno].last_insn,
max_uses, max_regno, &r1, &ep);
max_uses, max_regno, &r1,
&ep);
/* Since we made a substitution, zap all remembered
registers. */
......@@ -1397,8 +1467,8 @@ expand_prologue ()
unsigned int init_stack_alloc = 0;
rtx save_regs[32];
rtx save_all;
int num_save;
int default_stack;
unsigned int num_save;
unsigned int default_stack;
int code;
int interrupt_handler = v850_interrupt_function_p (current_function_decl);
long reg_saved = 0;
......@@ -1476,7 +1546,8 @@ expand_prologue ()
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)));
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,
......@@ -1508,7 +1579,8 @@ expand_prologue ()
actual_fsize -= alloc_stack;
if (TARGET_DEBUG)
fprintf (stderr, "Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
fprintf (stderr, "\
Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
save_normal_len - save_func_len,
save_normal_len, save_func_len,
IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
......@@ -1518,8 +1590,8 @@ expand_prologue ()
}
}
/* If no prolog save function is available, store the registers the old fashioned
way (one by one). */
/* If no prolog save function is available, store the registers the old
fashioned way (one by one). */
if (!save_all)
{
/* Special case interrupt functions that save all registers for a call. */
......@@ -1600,8 +1672,8 @@ expand_epilogue ()
unsigned int init_stack_free = 0;
rtx restore_regs[32];
rtx restore_all;
int num_restore;
int default_stack;
unsigned int num_restore;
unsigned int default_stack;
int code;
int interrupt_handler = v850_interrupt_function_p (current_function_decl);
......@@ -1637,7 +1709,8 @@ expand_epilogue ()
/* 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 && actual_fsize >= default_stack
if (TARGET_PROLOG_FUNCTION && num_restore > 0
&& actual_fsize >= default_stack
&& !interrupt_handler)
{
int alloc_stack = (4 * num_restore) + default_stack;
......@@ -1675,7 +1748,8 @@ expand_epilogue ()
= gen_rtx (SET, VOIDmode,
restore_regs[i],
gen_rtx (MEM, Pmode,
plus_constant (stack_pointer_rtx, offset)));
plus_constant
(stack_pointer_rtx, offset)));
offset -= 4;
}
......@@ -1705,7 +1779,8 @@ expand_epilogue ()
INSN_CODE (insn) = code;
if (TARGET_DEBUG)
fprintf (stderr, "Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
fprintf (stderr, "\
Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
restore_normal_len - restore_func_len,
restore_normal_len, restore_func_len,
IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
......@@ -1727,9 +1802,13 @@ expand_epilogue ()
/* 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))
if (actual_fsize > init_stack_free
|| (interrupt_handler && actual_fsize))
{
int diff = actual_fsize - ((interrupt_handler) ? 0 : 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,
......@@ -1843,24 +1922,59 @@ notice_update_cc (body, insn)
break;
}
}
/* Return nonzero if ATTR is a valid attribute for DECL.
ATTRIBUTES are any existing attributes and ARGS are the arguments
supplied with ATTR.
/* Retrieve the data area that has been chosen for the given decl. */
Supported attributes:
v850_data_area
v850_get_data_area (decl)
tree decl;
{
if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_SDA;
if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_TDA;
if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE)
return DATA_AREA_ZDA;
return DATA_AREA_NORMAL;
}
interrupt_handler or interrupt: output a prologue and epilogue suitable
for an interrupt handler. */
/* Store the indicated data area in the decl's attributes. */
static void
v850_set_data_area (decl, data_area)
tree decl;
v850_data_area data_area;
{
tree name;
switch (data_area)
{
case DATA_AREA_SDA: name = get_identifier ("sda"); break;
case DATA_AREA_TDA: name = get_identifier ("tda"); break;
case DATA_AREA_ZDA: name = get_identifier ("zda"); break;
default:
return;
}
DECL_MACHINE_ATTRIBUTES (decl) = tree_cons
(name, NULL, DECL_MACHINE_ATTRIBUTES (decl));
}
/* Return nonzero if ATTR is a valid attribute for DECL.
ARGS are the arguments supplied with ATTR. */
int
v850_valid_machine_decl_attribute (decl, attributes, attr, args)
v850_valid_machine_decl_attribute (decl, attr, args)
tree decl;
tree attributes;
tree attr;
tree args;
{
v850_data_area data_area;
v850_data_area area;
if (args != NULL_TREE)
return 0;
......@@ -1868,6 +1982,37 @@ v850_valid_machine_decl_attribute (decl, attributes, attr, args)
|| is_attribute_p ("interrupt", attr))
return TREE_CODE (decl) == FUNCTION_DECL;
/* Implement data area attribute. */
if (is_attribute_p ("sda", attr))
data_area = DATA_AREA_SDA;
else if (is_attribute_p ("tda", attr))
data_area = DATA_AREA_TDA;
else if (is_attribute_p ("zda", attr))
data_area = DATA_AREA_ZDA;
else
return 0;
switch (TREE_CODE (decl))
{
case VAR_DECL:
if (current_function_decl != NULL_TREE)
error_with_decl (decl, "\
a data area attribute cannot be specified for local variables");
/* Drop through. */
case FUNCTION_DECL:
area = v850_get_data_area (decl);
if (area != DATA_AREA_NORMAL && data_area != area)
error_with_decl (decl, "\
data area of '%s' conflicts with previous declaration");
return 1;
default:
break;
}
return 0;
}
......@@ -1907,18 +2052,67 @@ v850_interrupt_function_p (func)
}
extern struct obstack *saveable_obstack;
extern struct obstack * saveable_obstack;
void
v850_encode_data_area (decl)
tree decl;
{
char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
int len = strlen (str);
char *newstr;
char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
int len = strlen (str);
char * newstr;
/* Map explict sections into the appropriate attribute */
if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
{
if (DECL_SECTION_NAME (decl))
{
char * name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
if (streq (name, ".zdata") || streq (name, ".zbss"))
v850_set_data_area (decl, DATA_AREA_ZDA);
else if (streq (name, ".sdata") || streq (name, ".sbss"))
v850_set_data_area (decl, DATA_AREA_SDA);
else if (streq (name, ".tdata"))
v850_set_data_area (decl, DATA_AREA_TDA);
}
/* If no attribute, support -m{zda,sda,tda}=n */
else
{
int size = int_size_in_bytes (TREE_TYPE (decl));
if (size <= 0)
;
else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max)
v850_set_data_area (decl, DATA_AREA_TDA);
else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max)
v850_set_data_area (decl, DATA_AREA_SDA);
else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max)
v850_set_data_area (decl, DATA_AREA_ZDA);
}
if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
return;
}
newstr = obstack_alloc (saveable_obstack, len + 2);
/* In the Cygnus sources we actually do something; this is just
here to make merges easier. */
return;
strcpy (newstr + 1, str);
switch (v850_get_data_area (decl))
{
case DATA_AREA_ZDA: *newstr = ZDA_NAME_FLAG_CHAR; break;
case DATA_AREA_TDA: *newstr = TDA_NAME_FLAG_CHAR; break;
case DATA_AREA_SDA: *newstr = SDA_NAME_FLAG_CHAR; break;
default: abort ();
}
XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
}
/* Return true if the given RTX is a register which can be restored
......@@ -1926,7 +2120,7 @@ v850_encode_data_area (decl)
int
register_is_ok_for_epilogue (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
/* The save/restore routines can only cope with registers 2, and 20 - 31 */
return (GET_CODE (op) == REG)
......@@ -1939,7 +2133,7 @@ register_is_ok_for_epilogue (op, mode)
int
pattern_is_ok_for_epilogue (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
int count = XVECLEN (op, 0);
int i;
......@@ -2085,7 +2279,7 @@ construct_restore_jr (op)
/* Note, it is possible to have gaps in the register mask.
We ignore this here, and generate a JR anyway. We will
be popping more registers thatn is strictly necessary, but
be popping more registers than is strictly necessary, but
it does save code space. */
if (first == last)
......@@ -2102,7 +2296,7 @@ construct_restore_jr (op)
int
pattern_is_ok_for_prologue (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
int count = XVECLEN (op, 0);
int i;
......@@ -2271,7 +2465,7 @@ construct_save_jarl (op)
/* Note, it is possible to have gaps in the register mask.
We ignore this here, and generate a JARL anyway. We will
be pushing more registers thatn is strictly necessary, but
be pushing more registers than is strictly necessary, but
it does save code space. */
if (first == last)
......@@ -2283,3 +2477,577 @@ construct_save_jarl (op)
return buff;
}
extern tree last_assemble_variable_decl;
extern int size_directive_output;
/* A version of asm_output_aligned_bss() that copes with the special
data areas of the v850. */
void
v850_output_aligned_bss (file, decl, name, size, align)
FILE * file;
tree decl;
char * name;
int size;
int align;
{
ASM_GLOBALIZE_LABEL (file, name);
switch (v850_get_data_area (decl))
{
case DATA_AREA_ZDA:
zbss_section ();
break;
case DATA_AREA_SDA:
sbss_section ();
break;
case DATA_AREA_TDA:
tdata_section ();
default:
bss_section ();
break;
}
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
#ifdef ASM_DECLARE_OBJECT_NAME
last_assemble_variable_decl = decl;
ASM_DECLARE_OBJECT_NAME (file, name, decl);
#else
/* Standard thing is just output label for the object. */
ASM_OUTPUT_LABEL (file, name);
#endif /* ASM_DECLARE_OBJECT_NAME */
ASM_OUTPUT_SKIP (file, size ? size : 1);
}
/* Called via the macro ASM_OUTPUT_DECL_COMMON */
void
v850_output_common (file, decl, name, size, align)
FILE * file;
tree decl;
char * name;
int size;
int align;
{
if (decl == NULL_TREE)
{
fprintf (file, "\t%s\t", COMMON_ASM_OP);
}
else
{
switch (v850_get_data_area (decl))
{
case DATA_AREA_ZDA:
fprintf (file, "\t%s\t", ZCOMMON_ASM_OP);
break;
case DATA_AREA_SDA:
fprintf (file, "\t%s\t", SCOMMON_ASM_OP);
break;
case DATA_AREA_TDA:
fprintf (file, "\t%s\t", TCOMMON_ASM_OP);
break;
default:
fprintf (file, "\t%s\t", COMMON_ASM_OP);
break;
}
}
assemble_name (file, name);
fprintf (file, ",%u,%u\n", size, align / BITS_PER_UNIT);
}
/* Called via the macro ASM_OUTPUT_DECL_LOCAL */
void
v850_output_local (file, decl, name, size, align)
FILE * file;
tree decl;
char * name;
int size;
int align;
{
fprintf (file, "\t%s\t", 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)
tree decl;
{
if (data_area_stack
&& data_area_stack->data_area
&& current_function_decl == NULL_TREE
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
&& v850_get_data_area (decl) == DATA_AREA_NORMAL)
v850_set_data_area (decl, data_area_stack->data_area);
/* Initialise the default names of the v850 specific sections,
if this has not been done before. */
if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL)
{
GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA]
= build_string (sizeof (".sdata")-1, ".sdata");
GHS_default_section_names [(int) GHS_SECTION_KIND_ROSDATA]
= build_string (sizeof (".rosdata")-1, ".rosdata");
GHS_default_section_names [(int) GHS_SECTION_KIND_TDATA]
= build_string (sizeof (".tdata")-1, ".tdata");
GHS_default_section_names [(int) GHS_SECTION_KIND_ZDATA]
= build_string (sizeof (".zdata")-1, ".zdata");
GHS_default_section_names [(int) GHS_SECTION_KIND_ROZDATA]
= build_string (sizeof (".rozdata")-1, ".rozdata");
}
if (current_function_decl == NULL_TREE
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == CONST_DECL
|| TREE_CODE (decl) == FUNCTION_DECL)
&& (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl))
&& !DECL_SECTION_NAME (decl))
{
enum GHS_section_kind kind = GHS_SECTION_KIND_DEFAULT;
tree chosen_section;
if (TREE_CODE (decl) == FUNCTION_DECL)
kind = GHS_SECTION_KIND_TEXT;
else
{
/* First choose a section kind based on the data area of the decl. */
switch (v850_get_data_area (decl))
{
default:
abort ();
case DATA_AREA_SDA:
kind = ((TREE_READONLY (decl))
? GHS_SECTION_KIND_ROSDATA
: GHS_SECTION_KIND_SDATA);
break;
case DATA_AREA_TDA:
kind = GHS_SECTION_KIND_TDATA;
break;
case DATA_AREA_ZDA:
kind = ((TREE_READONLY (decl))
? GHS_SECTION_KIND_ROZDATA
: GHS_SECTION_KIND_ZDATA);
break;
case DATA_AREA_NORMAL: /* default data area */
if (TREE_READONLY (decl))
kind = GHS_SECTION_KIND_RODATA;
else if (DECL_INITIAL (decl))
kind = GHS_SECTION_KIND_DATA;
else
kind = GHS_SECTION_KIND_BSS;
}
}
/* Now, if the section kind has been explicitly renamed,
then attach a section attribute. */
chosen_section = GHS_current_section_names [(int) kind];
/* Otherwise, if this kind of section needs an explicit section
attribute, then also attach one. */
if (chosen_section == NULL)
chosen_section = GHS_default_section_names [(int) kind];
if (chosen_section)
{
/* Only set the section name if specified by a pragma, because
otherwise it will force those variables to get allocated storage
in this module, rather than by the linker. */
DECL_SECTION_NAME (decl) = chosen_section;
}
}
}
......@@ -20,6 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "svr4.h" /* Automatically does #undef CPP_PREDEFINES */
#include "gansidecl.h" /* For the PROTO macro */
#undef ASM_SPEC
#define ASM_SPEC "%{mv*:-mv%*}"
......@@ -78,7 +79,7 @@ extern int target_flags;
* Doubles are normally 4 byte aligned, except in argument
lists where they are 8 byte aligned. Is the alignment
in the argument list based on the first parameter,
first stack parameter, etc., etc.
first stack parameter, etc etc.
* Passing/returning of large structures probably isn't the same
as GHS. We don't have enough documentation on their conventions
......@@ -112,21 +113,27 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
{{ "ghs", MASK_GHS }, \
{ "no-ghs", -MASK_GHS }, \
{ "long-calls", MASK_LONG_CALLS }, \
{ "no-long-calls", -MASK_LONG_CALLS }, \
{ "ep", MASK_EP }, \
{ "no-ep", -MASK_EP }, \
{ "prolog-function", MASK_PROLOG_FUNCTION }, \
{ "no-prolog-function", -MASK_PROLOG_FUNCTION }, \
{ "space", MASK_EP | MASK_PROLOG_FUNCTION }, \
{ "debug", MASK_DEBUG }, \
{ "v850", MASK_V850 }, \
{ "v850", -(MASK_V850 ^ MASK_CPU) }, \
{ "big-switch", MASK_BIG_SWITCH }, \
{{ "ghs", MASK_GHS, "Support Green Hills ABI" }, \
{ "no-ghs", -MASK_GHS, "" }, \
{ "long-calls", MASK_LONG_CALLS, \
"Prohibit PC relative function calls" },\
{ "no-long-calls", -MASK_LONG_CALLS, "" }, \
{ "ep", MASK_EP, \
"Reuse r30 on a per function basis" }, \
{ "no-ep", -MASK_EP, "" }, \
{ "prolog-function", MASK_PROLOG_FUNCTION, \
"Use stubs for function prologues" }, \
{ "no-prolog-function", -MASK_PROLOG_FUNCTION, "" }, \
{ "space", MASK_EP | MASK_PROLOG_FUNCTION, \
"Same as: -mep -mprolog-function" }, \
{ "debug", MASK_DEBUG, "Enable backend debugging" }, \
{ "v850", MASK_V850, \
"Compile for the v850 processor" }, \
{ "v850", -(MASK_V850 ^ MASK_CPU), "" }, \
{ "big-switch", MASK_BIG_SWITCH, \
"Use 4 byte entries in switch tables" },\
EXTRA_SWITCHES \
{ "", TARGET_DEFAULT}}
{ "", TARGET_DEFAULT, ""}}
#ifndef EXTRA_SWITCHES
#define EXTRA_SWITCHES
......@@ -176,12 +183,15 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
#define TARGET_OPTIONS \
{ \
{ "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
{ "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
{ "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
{ "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
{ "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
{ "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
{ "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value, \
"Set the max size of data eligible for the TDA area" }, \
{ "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value, "" }, \
{ "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value, \
"Set the max size of data eligible for the SDA area" }, \
{ "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value, "" }, \
{ "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value, \
"Set the max size of data eligible for the ZDA area" }, \
{ "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value, "" }, \
}
/* Sometimes certain combinations of command options do not make
......@@ -405,7 +415,8 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
For any two classes, it is very desirable that there be another
class that represents their union. */
enum reg_class {
enum reg_class
{
NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
};
......@@ -581,13 +592,14 @@ enum reg_class {
Do not define this macro if it would be the same as
`FRAME_POINTER_REGNUM'. */
#undef HARD_FRAME_POINTER_REGNUM
#define HARD_FRAME_POINTER_REGNUM 29
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM 33
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 5
#define STATIC_CHAIN_REGNUM 20
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms
......@@ -690,7 +702,6 @@ struct cum_arg { int nbytes; };
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
struct rtx_def *function_arg();
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED)
......@@ -1035,17 +1046,29 @@ do { \
into an indirect call. */
#define NO_FUNCTION_CSE
/* The four different data regions on the v850. */
typedef enum
{
DATA_AREA_NORMAL,
DATA_AREA_SDA,
DATA_AREA_TDA,
DATA_AREA_ZDA
} v850_data_area;
/* A list of names for sections other than the standard two, which are
`in_text' and `in_data'. You need not define this macro on a
system with no other sections (that GCC needs to use). */
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, in_dtors
#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, \
in_dtors, in_rozdata, in_rosdata, in_sbss, in_zbss, in_zcommon, in_scommon
/* One or more functions to be defined in `varasm.c'. These
functions should do jobs analogous to those of `text_section' and
`data_section', for your additional sections. Do not define this
macro if you do not define `EXTRA_SECTIONS'. */
#undef EXTRA_SECTION_FUNCTIONS
/* This could be done a lot more cleanly using ANSI C ... */
#define EXTRA_SECTION_FUNCTIONS \
CONST_SECTION_FUNCTION \
CTORS_SECTION_FUNCTION \
......@@ -1062,6 +1085,26 @@ sdata_section () \
} \
\
void \
rosdata_section () \
{ \
if (in_section != in_rosdata) \
{ \
fprintf (asm_out_file, "%s\n", ROSDATA_SECTION_ASM_OP); \
in_section = in_sdata; \
} \
} \
\
void \
sbss_section () \
{ \
if (in_section != in_sbss) \
{ \
fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
in_section = in_sbss; \
} \
} \
\
void \
tdata_section () \
{ \
if (in_section != in_tdata) \
......@@ -1079,16 +1122,42 @@ zdata_section () \
fprintf (asm_out_file, "%s\n", ZDATA_SECTION_ASM_OP); \
in_section = in_zdata; \
} \
} \
\
void \
rozdata_section () \
{ \
if (in_section != in_rozdata) \
{ \
fprintf (asm_out_file, "%s\n", ROZDATA_SECTION_ASM_OP); \
in_section = in_rozdata; \
} \
} \
\
void \
zbss_section () \
{ \
if (in_section != in_zbss) \
{ \
fprintf (asm_out_file, "%s\n", ZBSS_SECTION_ASM_OP); \
in_section = in_zbss; \
} \
}
#define TEXT_SECTION_ASM_OP "\t.section .text"
#define DATA_SECTION_ASM_OP "\t.section .data"
#define BSS_SECTION_ASM_OP "\t.section .bss"
#define TEXT_SECTION_ASM_OP "\t.section .text"
#define DATA_SECTION_ASM_OP "\t.section .data"
#define BSS_SECTION_ASM_OP "\t.section .bss"
#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\""
#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
#define ZDATA_SECTION_ASM_OP "\t.section .zdata,\"aw\""
#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\""
#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\""
#define TDATA_SECTION_ASM_OP "\t.section .tdata,\"aw\""
#define ROSDATA_SECTION_ASM_OP "\t.section .rosdata,\"a\""
#define ROZDATA_SECTION_ASM_OP "\t.section .rozdata,\"a\""
#define SCOMMON_ASM_OP ".scomm"
#define ZCOMMON_ASM_OP ".zcomm"
#define TCOMMON_ASM_OP ".tcomm"
/* A C statement or statements to switch to the appropriate section
for output of EXP. You can assume that EXP is either a `VAR_DECL'
......@@ -1099,18 +1168,48 @@ zdata_section () \
Do not define this macro if you put all read-only variables and
constants in the read-only data section (usually the text section). */
#undef SELECT_SECTION
#undef SELECT_SECTION
#define SELECT_SECTION(EXP, RELOC) \
do { \
if (TREE_CODE (EXP) == VAR_DECL) \
{ \
if (!TREE_READONLY (EXP) || TREE_SIDE_EFFECTS (EXP) \
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)))) \
data_section (); \
is_const = FALSE; \
else \
const_section (); \
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) \
const_section (); \
else \
data_section (); \
break; \
} \
} \
else if (TREE_CODE (EXP) == STRING_CST) \
{ \
......@@ -1203,6 +1302,24 @@ do { char dstr[30]; \
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
/* This says how to output the assembler to define a global
uninitialized, common symbol. */
#undef ASM_OUTPUT_ALIGNED_COMMON
#undef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_common (FILE, DECL, NAME, SIZE, ALIGN)
/* This says how to output the assembler to define a local
uninitialized symbol. */
#undef ASM_OUTPUT_ALIGNED_LOCAL
#undef ASM_OUTPUT_LOCAL
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_local (FILE, DECL, NAME, SIZE, ALIGN)
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
......@@ -1266,7 +1383,7 @@ do { char dstr[30]; \
/* Print an instruction operand X on file FILE.
look in v850.c for details */
#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE)
#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '.')
......@@ -1377,15 +1494,69 @@ do { char dstr[30]; \
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
v850_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
v850_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
/* Tell compiler we have {ZDA,TDA,SDA} small data regions */
#define HAVE_ZDA 1
#define HAVE_SDA 1
#define HAVE_TDA 1
/* A C statement that assigns default attributes to a newly created DECL. */
#define SET_DEFAULT_DECL_ATTRIBUTES(decl, attr) \
v850_set_default_decl_attr (decl)
/* Tell compiler we want to support GHS pragmas */
#define HANDLE_GHS_PRAGMA
#define HANDLE_PRAGMA(get, unget, name) v850_handle_pragma (get, unget, name)
enum v850_pragma_state
{
V850_PS_START,
V850_PS_SHOULD_BE_DONE,
V850_PS_BAD,
V850_PS_MAYBE_SECTION_NAME,
V850_PS_EXPECTING_EQUALS,
V850_PS_EXPECTING_SECTION_ALIAS,
V850_PS_MAYBE_COMMA
};
enum v850_pragma_type
{
V850_PT_UNKNOWN,
V850_PT_INTERRUPT,
V850_PT_SECTION,
V850_PT_START_SECTION,
V850_PT_END_SECTION
};
/* enum GHS_SECTION_KIND is an enumeration of the kinds of sections that
can appear in the "ghs section" pragma. These names are used to index
into the GHS_default_section_names[] and GHS_current_section_names[]
that are defined in v850.c, and so the ordering of each must remain
consistant.
These arrays give the default and current names for each kind of
section defined by the GHS pragmas. The current names can be changed
by the "ghs section" pragma. If the current names are null, use
the default names. Note that the two arrays have different types.
For the *normal* section kinds (like .data, .text, etc.) we do not
want to explicitly force the name of these sections, but would rather
let the linker (or at least the back end) choose the name of the
section, UNLESS the user has force a specific name for these section
kinds. To accomplish this set the name in ghs_default_section_names
to null. */
enum GHS_section_kind
{
GHS_SECTION_KIND_DEFAULT,
GHS_SECTION_KIND_TEXT,
GHS_SECTION_KIND_DATA,
GHS_SECTION_KIND_RODATA,
GHS_SECTION_KIND_BSS,
GHS_SECTION_KIND_SDATA,
GHS_SECTION_KIND_ROSDATA,
GHS_SECTION_KIND_TDATA,
GHS_SECTION_KIND_ZDATA,
GHS_SECTION_KIND_ROZDATA,
COUNT_OF_GHS_SECTION_KINDS /* must be last */
};
/* The assembler op to start the file. */
......@@ -1444,34 +1615,52 @@ do { \
{ "register_is_ok_for_epilogue",{ REG }}, \
{ "not_power_of_two_operand", { CONST_INT }},
extern void override_options ();
extern void asm_file_start ();
extern int function_arg_partial_nregs ();
extern int const_costs ();
extern void print_operand ();
extern void print_operand_address ();
extern char *output_move_double ();
extern char *output_move_single ();
extern int ep_operand ();
extern int reg_or_0_operand ();
extern int reg_or_int5_operand ();
extern int call_address_operand ();
extern int movsi_source_operand ();
extern int power_of_two_operand ();
extern int not_power_of_two_operand ();
extern void v850_reorg ();
extern int compute_register_save_size ();
extern int compute_frame_size ();
extern void expand_prologue ();
extern void expand_epilogue ();
extern void notice_update_cc ();
extern int v850_valid_machine_decl_attribute ();
extern int v850_interrupt_function_p ();
extern int pattern_is_ok_for_prologue();
extern int pattern_is_ok_for_epilogue();
extern int register_is_ok_for_epilogue ();
extern char *construct_save_jarl ();
extern char *construct_restore_jr ();
/* Note, due to dependency and search path conflicts, prototypes
involving the FILE, rtx or tree types cannot be included here.
They are included at the start of v850.c */
extern void asm_file_start ();
extern void print_operand ();
extern void print_operand_address ();
extern int function_arg_partial_nregs ();
extern int const_costs ();
extern char * output_move_double ();
extern char * output_move_single ();
extern int ep_memory_operand ();
extern int reg_or_0_operand ();
extern int reg_or_int5_operand ();
extern int call_address_operand ();
extern int movsi_source_operand ();
extern int power_of_two_operand ();
extern int not_power_of_two_operand ();
extern int special_symbolref_operand ();
extern void v850_reorg ();
extern void notice_update_cc ();
extern int v850_valid_machine_decl_attribute ();
extern int v850_interrupt_function_p ();
extern int pattern_is_ok_for_prologue ();
extern int pattern_is_ok_for_epilogue ();
extern int register_is_ok_for_epilogue ();
extern char * construct_save_jarl ();
extern char * construct_restore_jr ();
extern void override_options PROTO ((void));
extern int compute_register_save_size PROTO ((long *));
extern int compute_frame_size PROTO ((int, long *));
extern void expand_prologue PROTO ((void));
extern void expand_epilogue PROTO ((void));
extern void v850_output_aligned_bss ();
extern void v850_output_common ();
extern void v850_output_local ();
extern void sdata_section PROTO ((void));
extern void rosdata_section PROTO ((void));
extern void sbss_section PROTO ((void));
extern void tdata_section PROTO ((void));
extern void zdata_section PROTO ((void));
extern void rozdata_section PROTO ((void));
extern void zbss_section PROTO ((void));
extern int v850_handle_pragma PROTO ((int (*)(void), void (*)(int), char *));
extern void v850_encode_data_area ();
extern void v850_set_default_decl_attr ();
extern v850_data_area v850_get_data_area ();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment