aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog4
-rw-r--r--gas/config/tc-v850.c203
-rw-r--r--gas/config/tc-v850.h8
3 files changed, 148 insertions, 67 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index b10142b..c442bde 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,7 @@
+Tue Dec 2 17:05:13 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Brought up to date with the branch.
+
Mon Dec 1 20:24:18 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
* config/tc-sh.c (SWITCH_TABLE_CONS): Handle (fix)->fx_size == 1.
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
index f4a9ea9..563fc54 100644
--- a/gas/config/tc-v850.c
+++ b/gas/config/tc-v850.c
@@ -559,7 +559,6 @@ static const struct reg_name pre_defined_registers[] =
static const struct reg_name system_registers[] =
{
/* start-sanitize-v850e */
-
{ "ctbp", 20 },
{ "ctpc", 16 },
{ "ctpsw", 17 },
@@ -575,6 +574,15 @@ static const struct reg_name system_registers[] =
};
#define SYSREG_NAME_CNT (sizeof (system_registers) / sizeof (struct reg_name))
+/* start-sanitize-v850e */
+static const struct reg_name system_list_registers[] =
+{
+ {"PS", 5 },
+ {"SR", 0 + 1}
+};
+#define SYSREGLIST_NAME_CNT (sizeof (system_list_registers) / sizeof (struct reg_name))
+/* end-sanitize-v850e */
+
static const struct reg_name cc_names[] =
{
{ "c", 0x1 },
@@ -607,14 +615,34 @@ static const struct reg_name cc_names[] =
number from the array on success, or -1 on failure. */
static int
-reg_name_search (regs, regcount, name)
+reg_name_search (regs, regcount, name, accept_numbers)
const struct reg_name * regs;
int regcount;
const char * name;
+ boolean accept_numbers;
{
int middle, low, high;
int cmp;
+ symbolS * symbolP;
+ /* If the register name is a symbol, then evaluate it. */
+ if ((symbolP = symbol_find (name)) != NULL)
+ {
+ /* If the symbol is an alias for another name then use that.
+ If the symbol is an alias for a number, then return the number. */
+ if (symbolP->sy_value.X_op == O_symbol)
+ {
+ name = S_GET_NAME (symbolP->sy_value.X_add_symbol);
+ }
+ else if (accept_numbers)
+ {
+ int reg = S_GET_VALUE (symbolP);
+
+ if (reg >= 0 && reg <= 31)
+ return reg;
+ }
+ }
+
low = 0;
high = regcount - 1;
@@ -658,7 +686,7 @@ register_name (expressionP)
c = get_symbol_end ();
- reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+ reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name, FALSE);
* input_line_pointer = c; /* put back the delimiting char */
@@ -685,18 +713,31 @@ register_name (expressionP)
/* Summary of system_register_name().
*
- * in: Input_line_pointer points to 1st char of operand.
+ * in: Input_line_pointer points to 1st char of operand.
+ * expressionP points to an expression structure to be filled in.
+ * accept_numbers is true iff numerical register names may be used.
+ * start-sanitize-v850e
+ * accept_list_names is true iff the special names PS and SR may be
+ * accepted.
+ * end-sanitize-v850eq
*
- * out: A expressionS.
+ * out: A expressionS structure in expressionP.
* The operand may have been a register: in this case, X_op == O_register,
* X_add_number is set to the register number, and truth is returned.
* Input_line_pointer->(next non-blank) char after operand, or is in
* its original state.
*/
static boolean
-system_register_name (expressionP, accept_numbers)
+system_register_name (expressionP, accept_numbers
+ /* start-sanitize-v850e */
+ , accept_list_names
+ /* end-sanitize-v850e */
+ )
expressionS * expressionP;
boolean accept_numbers;
+/* start-sanitize-v850e */
+ boolean accept_list_names;
+/* end-sanitize-v850e */
{
int reg_number;
char * name;
@@ -707,7 +748,7 @@ system_register_name (expressionP, accept_numbers)
start = name = input_line_pointer;
c = get_symbol_end ();
- reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
+ reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name, accept_numbers);
* input_line_pointer = c; /* put back the delimiting char */
@@ -717,19 +758,30 @@ system_register_name (expressionP, accept_numbers)
input_line_pointer = start; /* reset input_line pointer */
if (isdigit (* input_line_pointer))
- reg_number = strtol (input_line_pointer, & input_line_pointer, 10);
+ {
+ reg_number = strtol (input_line_pointer, & input_line_pointer, 10);
- /* Make sure that the register number is allowable. */
- if ( reg_number < 0
- || reg_number > 5
+ /* Make sure that the register number is allowable. */
+ if ( reg_number < 0
+ || reg_number > 5
/* start-sanitize-v850e */
- && reg_number < 16
- || reg_number > 20
+ && reg_number < 16
+ || reg_number > 20
/* end-sanitize-v850e */
- )
+ )
+ {
+ reg_number = -1;
+ }
+ }
+/* start-sanitize-v850e */
+ else if (accept_list_names)
{
- reg_number = -1;
+ c = get_symbol_end ();
+ reg_number = reg_name_search (system_list_registers, SYSREGLIST_NAME_CNT, name, FALSE);
+
+ * input_line_pointer = c; /* put back the delimiting char */
}
+/* end-sanitize-v850e */
}
/* look to see if it's in the register table */
@@ -776,7 +828,7 @@ cc_name (expressionP)
start = name = input_line_pointer;
c = get_symbol_end ();
- reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
+ reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);
* input_line_pointer = c; /* put back the delimiting char */
@@ -954,7 +1006,7 @@ parse_register_list
return "illegal register included in list";
}
}
- else if (system_register_name (& exp, true))
+ else if (system_register_name (& exp, true, true))
{
if (regs == type1_regs)
{
@@ -967,8 +1019,10 @@ parse_register_list
else
* insn |= 0x8;
}
- else
+ else if (exp.X_add_number < 4)
* insn |= 0x80000;
+ else
+ return "High value system registers cannot be included in list";
}
else if (* input_line_pointer == '}')
{
@@ -1043,12 +1097,12 @@ md_show_usage (stream)
FILE * stream;
{
fprintf (stream, "V850 options:\n");
- fprintf (stream, "\t-wsigned_overflow Warn if signed immediate values overflow\n");
- fprintf (stream, "\t-wunsigned_overflow Warn if unsigned immediate values overflow\n");
- fprintf (stream, "\t-mv850 The code is targeted at the v850\n");
+ fprintf (stream, "\t-mwarn_signed_overflow Warn if signed immediate values overflow\n");
+ fprintf (stream, "\t-mwarn_unsigned_overflow Warn if unsigned immediate values overflow\n");
+ fprintf (stream, "\t-mv850 The code is targeted at the v850\n");
/* start-sanitize-v850e */
- fprintf (stream, "\t-mv850e The code is targeted at the v850e\n");
- fprintf (stream, "\t-mv850eq The code is targeted at the v850eq\n");
+ fprintf (stream, "\t-mv850e The code is targeted at the v850e\n");
+ fprintf (stream, "\t-mv850eq The code is targeted at the v850eq\n");
/* end-sanitize-v850e */
}
@@ -1057,46 +1111,38 @@ md_parse_option (c, arg)
int c;
char * arg;
{
- switch (c)
- {
- case 'w':
- if (strcmp (arg, "signed_overflow") == 0)
- {
- warn_signed_overflows = TRUE;
- return 1;
- }
- else if (strcmp (arg, "unsigned_overflow") == 0)
- {
- warn_unsigned_overflows = TRUE;
- return 1;
- }
- break;
+ if (c != 'm')
+ return 0;
- case 'm':
- if (strcmp (arg, "v850") == 0)
- {
- machine = 0;
- processor_mask = PROCESSOR_V850;
- return 1;
- }
+ if (strcmp (arg, "warn_signed_overflow") == 0)
+ {
+ warn_signed_overflows = TRUE;
+ }
+ else if (strcmp (arg, "warn_unsigned_overflow") == 0)
+ {
+ warn_unsigned_overflows = TRUE;
+ }
+ else if (strcmp (arg, "v850") == 0)
+ {
+ machine = 0;
+ processor_mask = PROCESSOR_V850;
+ }
/* start-sanitize-v850e */
- else if (strcmp (arg, "v850e") == 0)
- {
- machine = bfd_mach_v850e;
- processor_mask = PROCESSOR_V850E;
- return 1;
- }
- else if (strcmp (arg, "v850eq") == 0)
- {
- machine = bfd_mach_v850eq;
- processor_mask = PROCESSOR_V850EQ;
- return 1;
- }
-/* end-sanitize-v850e */
- break;
+ else if (strcmp (arg, "v850e") == 0)
+ {
+ machine = bfd_mach_v850e;
+ processor_mask = PROCESSOR_V850E;
+ }
+ else if (strcmp (arg, "v850eq") == 0)
+ {
+ machine = bfd_mach_v850eq;
+ processor_mask = PROCESSOR_V850EQ;
}
+/* end-sanitize-v850e */
+ else
+ return 0;
- return 0;
+ return 1;
}
symbolS *
@@ -1303,6 +1349,9 @@ md_begin ()
zcommon_section = subseg_new (".zcommon", 0);
bfd_set_section_flags (stdoutput, zcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
+ tcommon_section = subseg_new (".tcommon", 0);
+ bfd_set_section_flags (stdoutput, tcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
+
/* start-sanitize-v850e */
call_table_data_section = subseg_new (".call_table_data", 0);
bfd_set_section_flags (stdoutput, call_table_data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
@@ -1640,7 +1689,11 @@ md_assemble (str)
}
else if ((operand->flags & V850_OPERAND_SRG) != 0)
{
- if (!system_register_name (& ex, true))
+ if (!system_register_name (& ex, true
+ /* start-sanitize-v850e */
+ , false
+ /* end-sanitize-v850e */
+ ))
{
errmsg = "invalid system register name";
}
@@ -1717,12 +1770,28 @@ md_assemble (str)
ex.X_add_number = 0;
}
/* end-sanitize-v850e */
- else if (register_name (&ex)
+ else if (register_name (& ex)
&& (operand->flags & V850_OPERAND_REG) == 0)
{
- errmsg = "syntax error: register not expected";
+ /* It is possible that an alias has been defined that
+ matches a register name. For example the code may
+ include a ".set ZERO, 0" directive, which matches
+ the register name "zero". Attempt to reparse the
+ field as an expression, and only complain if we
+ cannot generate a constant. */
+
+ input_line_pointer = str;
+
+ expression (& ex);
+
+ if (ex.X_op != O_constant)
+ errmsg = "syntax error: register not expected";
}
- else if (system_register_name (& ex, false)
+ else if (system_register_name (& ex, false
+ /* start-sanitize-v850e */
+ , false
+ /* end-sanitize-v850e */
+ )
&& (operand->flags & V850_OPERAND_SRG) == 0)
{
errmsg = "syntax error: system register not expected";
@@ -2155,6 +2224,14 @@ v850_insert_operand (insn, operand, val, file, line)
const char * err = "operand out of range (%s not between %ld and %ld)";
char buf[100];
+ /* Restore min and mix to expected values for decimal ranges. */
+ if ((operand->flags & V850_OPERAND_SIGNED) && ! warn_signed_overflows)
+ max = (1 << (operand->bits - 1)) - 1;
+
+ if (! (operand->flags & V850_OPERAND_SIGNED)
+ && ! warn_unsigned_overflows)
+ min = 0;
+
sprint_value (buf, test);
if (file == (char *) NULL)
as_warn (err, buf, min, max);
diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h
index aa3dc83..2349cd2 100644
--- a/gas/config/tc-v850.h
+++ b/gas/config/tc-v850.h
@@ -39,7 +39,7 @@
/* Permit temporary numeric labels. */
#define LOCAL_LABELS_FB 1
-#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
/* We don't need to handle .word strangely. */
#define WORKING_DOT_WORD
@@ -63,16 +63,16 @@ extern const struct relax_type md_relax_table[];
#define ELF_TC_SPECIAL_SECTIONS \
{ ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
- { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
{ ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_GPREL }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
{ ".scommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
{ ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
{ ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
+ { ".tcommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
{ ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
{ ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_R0REL }, \
- { ".zcommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
{ ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
- { ".tcommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
+ { ".zcommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
{ ".call_table_data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
{ ".call_table_text", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR },