diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/v850/v850.c | 882 | ||||
-rw-r--r-- | gcc/config/v850/v850.h | 333 |
3 files changed, 1091 insertions, 129 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4e7eab7e38..149eeaadb49 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index 93fa8308018..8d9981c810c 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -1,5 +1,5 @@ /* 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; + } + } +} diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index 2ccbe98925b..8a417f079fc 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -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 (); |