forked from Imagelibrary/binutils-gdb
* struc-symbol.h (struct symbol): Add sy_mri_common bit.
* read.h (mri_comon_symbol): Declare. (s_mri_common): Declare. * read.c (mri_line_label): New static variable. (mri_common_symbol): New global variable. (potable): Add "common" and "common.s". (read_a_source_file): In MRI mode, set mri_line_label for a label at the start of a line. (s_mri_common): New function. (s_space): Handle mri_common_symbol. * symbols.c (colon): Change return value from void to symbolS *, and return new symbol. If mri_common_symbol is set, attach the new symbol to it. (resolve_symbol_value): Handle an sy_mri_common symbol. * symbols.h (colon): Change return value in declaration. * subsegs.c (subseg_set_rest): Clear mri_common_symbol. (subseg_set (both versions)): Likewise. * frags.c (frag_more): Warn if mri_common_symbol is not NULL. * write.c (adjust_reloc_syms): Skip sy_mri_common symbols. (write_object_file): Discard sy_mri_common symbols. (fixup_segment): Change relocations against sy_mri_common symbols to be against the common symbol itself. * config/obj-coff.c (yank_symbols): Discard sy_mri_common symbols. (fixup_segment): Change relocations against sy_mri_common symbols to be against the common symbol itself. * config/obj-aout.c (obj_crawl_symbol_chain): Discard sy_mri_common symbols.
This commit is contained in:
348
gas/read.c
348
gas/read.c
@@ -42,7 +42,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
|
||||
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
|
||||
#include "libiberty.h"
|
||||
#include "obstack.h"
|
||||
#include "listing.h"
|
||||
|
||||
@@ -84,7 +84,7 @@ die horribly;
|
||||
#endif
|
||||
|
||||
/* used by is_... macros. our ctype[] */
|
||||
const char lex_type[256] =
|
||||
char lex_type[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
|
||||
@@ -169,6 +169,15 @@ struct broken_word *broken_words;
|
||||
int new_broken_words;
|
||||
#endif
|
||||
|
||||
/* If this line had an MRI style label, it is stored in this variable.
|
||||
This is used by some of the MRI pseudo-ops. */
|
||||
static symbolS *mri_line_label;
|
||||
|
||||
/* This global variable is used to support MRI common sections. We
|
||||
translate such sections into a common symbol. This variable is
|
||||
non-NULL when we are in an MRI common section. */
|
||||
symbolS *mri_common_symbol;
|
||||
|
||||
char *demand_copy_string PARAMS ((int *lenP));
|
||||
int is_it_end_of_statement PARAMS ((void));
|
||||
static segT get_segmented_expression PARAMS ((expressionS *expP));
|
||||
@@ -193,11 +202,14 @@ read_begin ()
|
||||
for (p = line_separator_chars; *p; p++)
|
||||
is_end_of_line[(unsigned char) *p] = 1;
|
||||
/* Use more. FIXME-SOMEDAY. */
|
||||
|
||||
if (flag_mri)
|
||||
lex_type['?'] = 3;
|
||||
}
|
||||
|
||||
/* set up pseudo-op tables */
|
||||
|
||||
struct hash_control *po_hash;
|
||||
static struct hash_control *po_hash;
|
||||
|
||||
static const pseudo_typeS potable[] =
|
||||
{
|
||||
@@ -209,7 +221,20 @@ static const pseudo_typeS potable[] =
|
||||
/* block */
|
||||
{"byte", cons, 1},
|
||||
{"comm", s_comm, 0},
|
||||
{"common", s_mri_common, 0},
|
||||
{"common.s", s_mri_common, 1},
|
||||
{"data", s_data, 0},
|
||||
{"dc", cons, 2},
|
||||
{"dc.b", cons, 1},
|
||||
{"dc.d", float_cons, 'd'},
|
||||
{"dc.l", cons, 4},
|
||||
{"dc.s", float_cons, 'f'},
|
||||
{"dc.w", cons, 2},
|
||||
{"dc.x", float_cons, 'x'},
|
||||
{"ds", s_space, 2},
|
||||
{"ds.b", s_space, 1},
|
||||
{"ds.l", s_space, 4},
|
||||
{"ds.w", s_space, 2},
|
||||
#ifdef S_SET_DESC
|
||||
{"desc", s_desc, 0},
|
||||
#endif
|
||||
@@ -282,6 +307,7 @@ static const pseudo_typeS potable[] =
|
||||
/* type */
|
||||
/* use */
|
||||
/* val */
|
||||
{"xdef", s_globl, 0},
|
||||
{"xstabs", s_xstab, 's'},
|
||||
{"word", cons, 2},
|
||||
{"zero", s_space, 0},
|
||||
@@ -385,22 +411,43 @@ read_a_source_file (name)
|
||||
if (input_line_pointer[-1] == '\n')
|
||||
bump_line_counters ();
|
||||
|
||||
#if defined (MRI) || defined (LABELS_WITHOUT_COLONS)
|
||||
/* Text at the start of a line must be a label, we run down
|
||||
and stick a colon in. */
|
||||
if (is_name_beginner (*input_line_pointer))
|
||||
{
|
||||
char *line_start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
colon (line_start);
|
||||
*input_line_pointer = c;
|
||||
if (c == ':')
|
||||
input_line_pointer++;
|
||||
|
||||
}
|
||||
if (flag_mri
|
||||
#ifdef LABELS_WITHOUT_COLONS
|
||||
|| 1
|
||||
#endif
|
||||
}
|
||||
)
|
||||
{
|
||||
mri_line_label = NULL;
|
||||
|
||||
/* Text at the start of a line must be a label, we
|
||||
run down and stick a colon in. */
|
||||
if (is_name_beginner (*input_line_pointer))
|
||||
{
|
||||
char *line_start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
|
||||
/* In MRI mode, the EQU pseudoop must be handled
|
||||
specially. */
|
||||
if (flag_mri)
|
||||
{
|
||||
if ((strncasecmp (input_line_pointer + 1, "EQU", 3)
|
||||
== 0)
|
||||
&& (input_line_pointer[4] == ' '
|
||||
|| input_line_pointer[4] == '\t'))
|
||||
{
|
||||
input_line_pointer += 4;
|
||||
equals (line_start);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
mri_line_label = colon (line_start);
|
||||
*input_line_pointer = c;
|
||||
if (c == ':')
|
||||
input_line_pointer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are at the begining of a line, or similar place.
|
||||
@@ -464,11 +511,6 @@ read_a_source_file (name)
|
||||
}
|
||||
else
|
||||
{ /* expect pseudo-op or machine instruction */
|
||||
#ifdef MRI
|
||||
if (!done_pseudo (s))
|
||||
|
||||
#else
|
||||
|
||||
pop = NULL;
|
||||
|
||||
#define IGNORE_OPCODE_CASE
|
||||
@@ -484,12 +526,18 @@ read_a_source_file (name)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flag_mri
|
||||
#ifdef NO_PSEUDO_DOT
|
||||
/* The m88k uses pseudo-ops without a period. */
|
||||
pop = (pseudo_typeS *) hash_find (po_hash, s);
|
||||
if (pop != NULL && pop->poc_handler == NULL)
|
||||
pop = NULL;
|
||||
|| 1
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* The MRI assembler and the m88k use pseudo-ops
|
||||
without a period. */
|
||||
pop = (pseudo_typeS *) hash_find (po_hash, s);
|
||||
if (pop != NULL && pop->poc_handler == NULL)
|
||||
pop = NULL;
|
||||
}
|
||||
|
||||
if (pop != NULL || *s == '.')
|
||||
{
|
||||
@@ -528,7 +576,6 @@ read_a_source_file (name)
|
||||
(*pop->poc_handler) (pop->poc_val);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ /* machine instruction */
|
||||
/* WARNING: c has char, which may be end-of-line. */
|
||||
/* Also: input_line_pointer->`\0` where c was. */
|
||||
@@ -917,6 +964,104 @@ s_comm (ignore)
|
||||
demand_empty_rest_of_line ();
|
||||
} /* s_comm() */
|
||||
|
||||
/* The MRI COMMON pseudo-op. We handle this by creating a common
|
||||
symbol with the appropriate name. We make s_space do the right
|
||||
thing by increasing the size. */
|
||||
|
||||
void
|
||||
s_mri_common (small)
|
||||
int small;
|
||||
{
|
||||
char *name;
|
||||
char c;
|
||||
char *alc = NULL;
|
||||
symbolS *sym;
|
||||
offsetT align;
|
||||
|
||||
if (! flag_mri)
|
||||
{
|
||||
s_comm (0);
|
||||
return;
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
name = input_line_pointer;
|
||||
if (! isdigit ((unsigned char) *name))
|
||||
c = get_symbol_end ();
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
++input_line_pointer;
|
||||
}
|
||||
while (isdigit ((unsigned char) *input_line_pointer));
|
||||
c = *input_line_pointer;
|
||||
*input_line_pointer = '\0';
|
||||
|
||||
if (mri_line_label != NULL)
|
||||
{
|
||||
alc = (char *) xmalloc (strlen (S_GET_NAME (mri_line_label))
|
||||
+ (input_line_pointer - name)
|
||||
+ 1);
|
||||
sprintf (alc, "%s%s", name, S_GET_NAME (mri_line_label));
|
||||
name = alc;
|
||||
}
|
||||
}
|
||||
|
||||
sym = symbol_find_or_make (name);
|
||||
*input_line_pointer = c;
|
||||
if (alc != NULL)
|
||||
free (alc);
|
||||
|
||||
if (*input_line_pointer != ',')
|
||||
align = 0;
|
||||
else
|
||||
{
|
||||
++input_line_pointer;
|
||||
align = get_absolute_expression ();
|
||||
}
|
||||
|
||||
if (S_IS_DEFINED (sym))
|
||||
{
|
||||
#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER)
|
||||
if (! S_IS_COMMON (sym))
|
||||
#endif
|
||||
{
|
||||
as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
S_SET_EXTERNAL (sym);
|
||||
mri_common_symbol = sym;
|
||||
|
||||
#ifdef S_SET_ALIGN
|
||||
if (align != 0)
|
||||
S_SET_ALIGN (sym, align);
|
||||
#endif
|
||||
|
||||
if (mri_line_label != NULL)
|
||||
{
|
||||
mri_line_label->sy_value.X_op = O_symbol;
|
||||
mri_line_label->sy_value.X_add_symbol = sym;
|
||||
mri_line_label->sy_value.X_add_number = S_GET_VALUE (sym);
|
||||
mri_line_label->sy_frag = &zero_address_frag;
|
||||
S_SET_SEGMENT (mri_line_label, expr_section);
|
||||
}
|
||||
|
||||
/* FIXME: We just ignore the small argument, which distinguishes
|
||||
COMMON and COMMON.S. I don't know what we can do about it. */
|
||||
|
||||
/* Ignore the type and hptype. */
|
||||
if (*input_line_pointer == ',')
|
||||
input_line_pointer += 2;
|
||||
if (*input_line_pointer == ',')
|
||||
input_line_pointer += 2;
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_data (ignore)
|
||||
int ignore;
|
||||
@@ -1457,12 +1602,27 @@ s_space (mult)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we are secretly in an MRI common section, then creating
|
||||
space just increases the size of the common symbol. */
|
||||
if (mri_common_symbol != NULL)
|
||||
{
|
||||
S_SET_VALUE (mri_common_symbol,
|
||||
S_GET_VALUE (mri_common_symbol) + repeat);
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!need_pass_2)
|
||||
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
|
||||
repeat, (char *) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mri_common_symbol != NULL)
|
||||
{
|
||||
as_bad ("space allocation too complex in common section");
|
||||
mri_common_symbol = NULL;
|
||||
}
|
||||
if (!need_pass_2)
|
||||
p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
|
||||
make_expr_symbol (&exp), 0L, (char *) 0);
|
||||
@@ -1659,17 +1819,15 @@ pseudo_set (symbolP)
|
||||
are defined, which is the normal case, then only simple expressions
|
||||
are permitted. */
|
||||
|
||||
static void
|
||||
parse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
|
||||
|
||||
#ifndef TC_PARSE_CONS_EXPRESSION
|
||||
#ifdef BITFIELD_CONS_EXPRESSIONS
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
|
||||
static void
|
||||
parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
|
||||
#endif
|
||||
#ifdef MRI
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_mri_cons (EXP)
|
||||
static void
|
||||
parse_mri_cons PARAMS ((expressionS *exp));
|
||||
#endif
|
||||
#ifdef REPEAT_CONS_EXPRESSIONS
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
|
||||
static void
|
||||
@@ -1703,7 +1861,10 @@ cons (nbytes)
|
||||
|
||||
do
|
||||
{
|
||||
TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
|
||||
if (flag_mri)
|
||||
parse_mri_cons (&exp, (unsigned int) nbytes);
|
||||
else
|
||||
TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
|
||||
emit_expr (&exp, (unsigned int) nbytes);
|
||||
}
|
||||
while (*input_line_pointer++ == ',');
|
||||
@@ -2076,20 +2237,34 @@ parse_bitfield_cons (exp, nbytes)
|
||||
|
||||
#endif /* BITFIELD_CONS_EXPRESSIONS */
|
||||
|
||||
#ifdef MRI
|
||||
/* Handle an MRI style string expression. */
|
||||
|
||||
static void
|
||||
parse_mri_cons (exp, nbytes)
|
||||
expressionS *exp;
|
||||
unsigned int nbytes;
|
||||
{
|
||||
if (*input_line_pointer == '\'')
|
||||
if (*input_line_pointer != '\''
|
||||
&& (input_line_pointer[1] != '\''
|
||||
|| (*input_line_pointer != 'A'
|
||||
&& *input_line_pointer != 'E')))
|
||||
TC_PARSE_CONS_EXPRESSION (exp, nbytes);
|
||||
else
|
||||
{
|
||||
/* An MRI style string, cut into as many bytes as will fit into
|
||||
a nbyte chunk, left justify if necessary, and separate with
|
||||
commas so we can try again later */
|
||||
int scan = 0;
|
||||
unsigned int result = 0;
|
||||
|
||||
/* An MRI style string. Cut into as many bytes as will fit into
|
||||
a nbyte chunk, left justify if necessary, and separate with
|
||||
commas so we can try again later. */
|
||||
if (*input_line_pointer == 'A')
|
||||
++input_line_pointer;
|
||||
else if (*input_line_pointer == 'E')
|
||||
{
|
||||
as_bad ("EBCDIC constants are not supported");
|
||||
++input_line_pointer;
|
||||
}
|
||||
|
||||
input_line_pointer++;
|
||||
for (scan = 0; scan < nbytes; scan++)
|
||||
{
|
||||
@@ -2125,11 +2300,7 @@ parse_mri_cons (exp, nbytes)
|
||||
else
|
||||
input_line_pointer++;
|
||||
}
|
||||
else
|
||||
expression (&exp);
|
||||
}
|
||||
|
||||
#endif /* MRI */
|
||||
|
||||
#ifdef REPEAT_CONS_EXPRESSIONS
|
||||
|
||||
@@ -2221,14 +2392,93 @@ float_cons (float_type)
|
||||
if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
|
||||
input_line_pointer += 2;
|
||||
|
||||
err = md_atof (float_type, temp, &length);
|
||||
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
|
||||
know (length > 0);
|
||||
if (err)
|
||||
/* Accept :xxxx, where the x's are hex digits, for a floating
|
||||
point with the exact digits specified. */
|
||||
if (input_line_pointer[0] == ':')
|
||||
{
|
||||
as_bad ("Bad floating literal: %s", err);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
int i;
|
||||
|
||||
switch (float_type)
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 's':
|
||||
case 'S':
|
||||
length = 4;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
case 'r':
|
||||
case 'R':
|
||||
length = 8;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
length = 12;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'P':
|
||||
length = 12;
|
||||
break;
|
||||
|
||||
default:
|
||||
as_bad ("Unknown floating type type '%c'", float_type);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* It would be nice if we could go through expression to
|
||||
parse the hex constant, but if we get a bignum it's a
|
||||
pain to sort it into the buffer correctly. */
|
||||
i = 0;
|
||||
++input_line_pointer;
|
||||
while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
|
||||
{
|
||||
int d;
|
||||
|
||||
/* The MRI assembler accepts arbitrary underscores
|
||||
strewn about through the hex constant, so we ignore
|
||||
them as well. */
|
||||
if (*input_line_pointer == '_')
|
||||
{
|
||||
++input_line_pointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i >= length)
|
||||
{
|
||||
as_warn ("Floating point constant too large");
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
d = hex_value (*input_line_pointer) << 4;
|
||||
++input_line_pointer;
|
||||
while (*input_line_pointer == '_')
|
||||
++input_line_pointer;
|
||||
if (hex_p (*input_line_pointer))
|
||||
{
|
||||
d += hex_value (*input_line_pointer);
|
||||
++input_line_pointer;
|
||||
}
|
||||
temp[i++] = d;
|
||||
}
|
||||
if (i < length)
|
||||
memset (temp + i, 0, length - i);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = md_atof (float_type, temp, &length);
|
||||
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
|
||||
know (length > 0);
|
||||
if (err)
|
||||
{
|
||||
as_bad ("Bad floating literal: %s", err);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!need_pass_2)
|
||||
|
||||
Reference in New Issue
Block a user