* read.c (abs_section_offset): New global variable.

(potable): Add offset, struct.
	(do_org): New static function; handle changing the origin in the
	absolute section.
	(s_org): Use do_org.
	(s_set): Likewise.
	(equals): Likewise.
	(s_space): In absolute_section, just increase abs_section_offset.
	(s_struct): New function.
	(emit_expr): Handle absolute_section specially.
	* read.h (abs_section_offset): Declare.
	(s_struct): Declare.

	* read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne.
	Change if to pass O_ne to s_if.
	(read_a_source_file): Don't define an label without a colon if
	ignore_input returns true.

	* read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w,
	dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen,
	noformat.
	(read_a_source_file): If pseudo-op handler is s_end, quit
	immediately.
	(s_end): New function.
	(s_fail): New function.
	(s_float_space): New function.
	(hex_float): New static function.
	(float_cons): Use hex_float.
	* read.h (s_fail): Declare.
	(s_float_space): Declare.
This commit is contained in:
Ian Lance Taylor 1995-08-09 19:36:25 +00:00
parent e120d9fbcd
commit e28c40d725
3 changed files with 379 additions and 108 deletions

View File

@ -1,5 +1,63 @@
Wed Aug 9 10:51:48 1995 Ian Lance Taylor <ian@cygnus.com>
* write.c (adjust_reloc_syms): Check that symbol is not NULL
before checking sy_mri_common.
(fixup_segment): Likewise.
* config/obj-coff.c (fixup_segment): Likewise.
* read.c (abs_section_offset): New global variable.
(potable): Add offset, struct.
(do_org): New static function; handle changing the origin in the
absolute section.
(s_org): Use do_org.
(s_set): Likewise.
(equals): Likewise.
(s_space): In absolute_section, just increase abs_section_offset.
(s_struct): New function.
(emit_expr): Handle absolute_section specially.
* read.h (abs_section_offset): Declare.
(s_struct): Declare.
* frags.c (frag_more): Warn if in absolute_section.
(frag_now_fix): In absolute_section, return abs_section_offset.
* subsegs.c (subseg_change): If switching to absolute_section,
just set now_seg and now_subseg.
(subseg_set_rest): Special handling when switching to or from
absolute_section.
* config/tc-m68k.c (m68k_float_copnum): New static variable.
(md_pseudo_table): Add fopt and mask2.
(m68k_ip): Use m68k_float_copnum, not COPNUM, when setting
coprocessor register to use. In case 'I' when checking operands,
correct coprocessor register numbers. In case 'I' when setting
operands, don't add 1.
(s_fopt): New static function.
* config/m68k-parse.h (COPNUM): Don't define.
* read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne.
Change if to pass O_ne to s_if.
(read_a_source_file): Don't define an label without a colon if
ignore_input returns true.
* cond.c (s_if): Treat argument as an operatorT describing how to
compare the argument against zero.
(ignore_input): Don't require an initial dot in MRI mode, or if
NO_PSEUDO_DOT is defined.
* read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w,
dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen,
noformat.
(read_a_source_file): If pseudo-op handler is s_end, quit
immediately.
(s_end): New function.
(s_fail): New function.
(s_float_space): New function.
(hex_float): New static function.
(float_cons): Use hex_float.
* read.h (s_fail): Declare.
(s_float_space): Declare.
* cond.c (s_end): Remove.
* listing.c (listing_psize): Treat argument as indicating whether
a height is expected.
* read.c (mri_pending_align): New static variable.
(read_a_source_file): Handle mri_pending_align.
(cons): Set mri_pending_align if appropriate.

View File

@ -169,6 +169,11 @@ struct broken_word *broken_words;
int new_broken_words;
#endif
/* The current offset into the absolute section. We don't try to
build frags in the absolute section, since no data can be stored
there. We just keep track of the current offset. */
addressT abs_section_offset;
/* 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;
@ -185,6 +190,8 @@ symbolS *mri_common_symbol;
static int mri_pending_align;
static void do_align PARAMS ((int, char *));
static int hex_float PARAMS ((int, char *));
static void do_org PARAMS ((segT, expressionS *, int));
char *demand_copy_string PARAMS ((int *lenP));
int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
@ -238,10 +245,21 @@ static const pseudo_typeS potable[] =
{"dc.s", float_cons, 'f'},
{"dc.w", cons, 2},
{"dc.x", float_cons, 'x'},
{"dcb", s_space, 2},
{"dcb.b", s_space, 1},
{"dcb.d", s_float_space, 'd'},
{"dcb.l", s_space, 4},
{"dcb.s", s_float_space, 'f'},
{"dcb.w", s_space, 2},
{"dcb.x", s_float_space, 'x'},
{"ds", s_space, 2},
{"ds.b", s_space, 1},
{"ds.d", s_space, 8},
{"ds.l", s_space, 4},
{"ds.p", s_space, 12},
{"ds.s", s_space, 4},
{"ds.w", s_space, 2},
{"ds.x", s_space, 12},
#ifdef S_SET_DESC
{"desc", s_desc, 0},
#endif
@ -250,7 +268,9 @@ static const pseudo_typeS potable[] =
/* dsect */
{"eject", listing_eject, 0}, /* Formfeed listing */
{"else", s_else, 0},
{"elsec", s_else, 0},
{"end", s_end, 0},
{"endc", s_endif, 0},
{"endif", s_endif, 0},
/* endef */
{"equ", s_set, 0},
@ -259,16 +279,24 @@ static const pseudo_typeS potable[] =
{"extern", s_ignore, 0}, /* We treat all undef as ext */
{"appfile", s_app_file, 1},
{"appline", s_app_line, 0},
{"fail", s_fail, 0},
{"file", s_app_file, 0},
{"fill", s_fill, 0},
{"float", float_cons, 'f'},
{"format", s_ignore, 0},
{"global", s_globl, 0},
{"globl", s_globl, 0},
{"hword", cons, 2},
{"if", s_if, 0},
{"if", s_if, (int) O_ne},
{"ifdef", s_ifdef, 0},
{"ifeq", s_if, (int) O_eq},
{"ifeqs", s_ifeqs, 0},
{"ifge", s_if, (int) O_ge},
{"ifgt", s_if, (int) O_gt},
{"ifle", s_if, (int) O_le},
{"iflt", s_if, (int) O_lt},
{"ifndef", s_ifdef, 1},
{"ifne", s_if, (int) O_ne},
{"ifnes", s_ifeqs, 1},
{"ifnotdef", s_ifdef, 1},
{"include", s_include, 0},
@ -276,10 +304,13 @@ static const pseudo_typeS potable[] =
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0}, /* Listing flags */
{"list", listing_list, 1}, /* Turn listing on */
{"llen", listing_psize, 1},
{"long", cons, 4},
{"lsym", s_lsym, 0},
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0}, /* Turn listing off */
{"octa", cons, 16},
{"offset", s_struct, 0},
{"org", s_org, 0},
{"p2align", s_align_ptwo, 0},
{"psize", listing_psize, 0}, /* set paper size */
@ -297,6 +328,7 @@ static const pseudo_typeS potable[] =
{"stabn", s_stab, 'n'},
{"stabs", s_stab, 's'},
{"string", stringer, 1},
{"struct", s_struct, 0},
/* tag */
{"text", s_text, 0},
@ -433,22 +465,28 @@ read_a_source_file (name)
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 (! ignore_input ())
{
if ((strncasecmp (input_line_pointer + 1, "EQU", 3)
== 0)
&& (input_line_pointer[4] == ' '
|| input_line_pointer[4] == '\t'))
/* In MRI mode, the EQU pseudoop must be
handled specially. */
if (flag_mri)
{
input_line_pointer += 4;
equals (line_start);
continue;
if (((strncasecmp (input_line_pointer + 1,
"EQU", 3) == 0)
|| (strncasecmp (input_line_pointer + 1,
"SET", 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);
}
mri_line_label = colon (line_start);
*input_line_pointer = c;
if (c == ':')
input_line_pointer++;
@ -595,6 +633,10 @@ read_a_source_file (name)
* after pseudo-operation.
*/
(*pop->poc_handler) (pop->poc_val);
/* If that was .end, just get out now. */
if (pop->poc_handler == s_end)
goto quit;
}
else
{ /* machine instruction */
@ -810,8 +852,9 @@ read_a_source_file (name)
}
}
} /* while (more buffers to scan) */
input_scrub_close (); /* Close the input file */
quit:
input_scrub_close (); /* Close the input file */
}
void
@ -1173,6 +1216,39 @@ s_app_line (ignore)
demand_empty_rest_of_line ();
}
/* Handle the .end pseudo-op. Actually, the real work is done in
read_a_source_file. */
void
s_end (ignore)
int ignore;
{
if (flag_mri)
{
/* The MRI assembler permits the start symbol to follow .end,
but we don't support that. */
SKIP_WHITESPACE ();
if (! is_end_of_line[(unsigned char) *input_line_pointer])
as_warn ("start address not supported");
}
}
/* Handle the MRI fail pseudo-op. */
void
s_fail (ignore)
int ignore;
{
offsetT temp;
temp = get_absolute_expression ();
if (temp >= 500)
as_warn (".fail %ld encountered", (long) temp);
else
as_bad (".fail %ld encountered", (long) temp);
demand_empty_rest_of_line ();
}
void
s_fill (ignore)
int ignore;
@ -1486,6 +1562,39 @@ s_lsym (ignore)
demand_empty_rest_of_line ();
} /* s_lsym() */
/* Handle changing the location counter. */
static void
do_org (segment, exp, fill)
segT segment;
expressionS *exp;
int fill;
{
if (segment != now_seg && segment != absolute_section)
as_bad ("invalid segment \"%s\"; segment \"%s\" assumed",
segment_name (segment), segment_name (now_seg));
if (now_seg == absolute_section)
{
if (fill != 0)
as_warn ("ignoring fill value in absolute section");
if (exp->X_op != O_constant)
{
as_bad ("only constant offsets supported in absolute section");
exp->X_add_number = 0;
}
abs_section_offset = exp->X_add_number;
}
else
{
char *p;
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
exp->X_add_number, (char *) NULL);
*p = fill;
}
}
void
s_org (ignore)
int ignore;
@ -1493,7 +1602,7 @@ s_org (ignore)
register segT segment;
expressionS exp;
register long temp_fill;
register char *p;
/* Don't believe the documentation of BSD 4.2 AS. There is no such
thing as a sub-segment-relative origin. Any absolute origin is
given a warning, then assumed to be segment-relative. Any
@ -1514,15 +1623,10 @@ s_org (ignore)
}
else
temp_fill = 0;
if (!need_pass_2)
{
if (segment != now_seg && segment != absolute_section)
as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
segment_name (segment), segment_name (now_seg));
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
exp.X_add_number, (char *) 0);
*p = temp_fill;
} /* if (ok to make frag) */
do_org (segment, &exp, temp_fill);
demand_empty_rest_of_line ();
} /* s_org() */
@ -1568,15 +1672,7 @@ s_set (ignore)
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
{
if (segment != now_seg && segment != absolute_section)
as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
segment_name (segment),
segment_name (now_seg));
ptr = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
exp.X_add_number, (char *) 0);
*ptr = 0;
} /* if (ok to make frag) */
do_org (segment, &exp, 0);
*end_name = delim;
return;
@ -1629,6 +1725,14 @@ s_space (mult)
return;
}
/* If we are in the absolute section, just bump the offset. */
if (now_seg == absolute_section)
{
abs_section_offset += repeat;
demand_empty_rest_of_line ();
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)
@ -1645,6 +1749,11 @@ s_space (mult)
}
else
{
if (now_seg == absolute_section)
{
as_bad ("space allocation too complex in absolute section");
subseg_set (text_section, 0);
}
if (mri_common_symbol != NULL)
{
as_bad ("space allocation too complex in common section");
@ -1671,6 +1780,85 @@ s_space (mult)
demand_empty_rest_of_line ();
}
/* This is like s_space, but the value is a floating point number with
the given precision. This is for the MRI dcb.s pseudo-op and
friends. */
void
s_float_space (float_type)
int float_type;
{
offsetT count;
int flen;
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
count = get_absolute_expression ();
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad ("missing value");
ignore_rest_of_line ();
return;
}
++input_line_pointer;
SKIP_WHITESPACE ();
/* Skip any 0{letter} that may be present. Don't even check if the
* letter is legal. */
if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
input_line_pointer += 2;
/* Accept :xxxx, where the x's are hex digits, for a floating point
with the exact digits specified. */
if (input_line_pointer[0] == ':')
{
flen = hex_float (float_type, temp);
if (flen < 0)
{
ignore_rest_of_line ();
return;
}
}
else
{
char *err;
err = md_atof (float_type, temp, &flen);
know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (flen > 0);
if (err)
{
as_bad ("Bad floating literal: %s", err);
ignore_rest_of_line ();
return;
}
}
while (--count >= 0)
{
char *p;
p = frag_more (flen);
memcpy (p, temp, (unsigned int) flen);
}
demand_empty_rest_of_line ();
}
/* Handle the .struct pseudo-op, as found in MIPS assemblers. */
void
s_struct (ignore)
int ignore;
{
abs_section_offset = get_absolute_expression ();
subseg_set (absolute_section, 0);
demand_empty_rest_of_line ();
}
void
s_text (ignore)
int ignore;
@ -1927,6 +2115,15 @@ emit_expr (exp, nbytes)
op = exp->X_op;
/* Allow `.word 0' in the absolute section. */
if (now_seg == absolute_section)
{
if (op != O_constant || exp->X_add_number != 0)
as_bad ("attempt to store value in absolute section");
abs_section_offset += nbytes;
return;
}
/* Handle a negative bignum. */
if (op == O_uminus
&& exp->X_add_number == 0
@ -2379,6 +2576,88 @@ parse_repeat_cons (exp, nbytes)
#endif /* REPEAT_CONS_EXPRESSIONS */
/* Parse a floating point number represented as a hex constant. This
permits users to specify the exact bits they want in the floating
point number. */
static int
hex_float (float_type, bytes)
int float_type;
char *bytes;
{
int length;
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);
return -1;
}
/* 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;
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");
return -1;
}
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;
}
bytes[i++] = d;
}
if (i < length)
memset (bytes + i, 0, length - i);
return length;
}
/*
* float_cons()
*
@ -2432,77 +2711,13 @@ float_cons (float_type)
point with the exact digits specified. */
if (input_line_pointer[0] == ':')
{
int i;
switch (float_type)
++input_line_pointer;
length = hex_float (float_type, temp);
if (length < 0)
{
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
{
@ -2924,15 +3139,7 @@ equals (sym_name)
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
{
if (segment != now_seg && segment != absolute_section)
as_warn ("Illegal segment \"%s\". Segment \"%s\" assumed.",
segment_name (segment),
segment_name (now_seg));
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
exp.X_add_number, (char *) 0);
*p = 0;
} /* if (ok to make frag) */
do_org (segment, &exp, 0);
}
else
{

View File

@ -60,6 +60,9 @@ extern const char line_separator_chars[];
/* This flag whether to generate line info for asm file */
extern int generate_asm_lineno;
/* The offset in the absolute section. */
extern addressT abs_section_offset;
/* This is used to support MRI common sections. */
extern symbolS *mri_common_symbol;
@ -86,13 +89,14 @@ void s_align_ptwo PARAMS ((int));
void s_app_file PARAMS ((int));
void s_app_line PARAMS ((int));
void s_comm PARAMS ((int));
void s_mri_common PARAMS ((int));
void s_data PARAMS ((int));
void s_desc PARAMS ((int));
void s_else PARAMS ((int arg));
void s_end PARAMS ((int arg));
void s_endif PARAMS ((int arg));
void s_fail PARAMS ((int));
void s_fill PARAMS ((int));
void s_float_space PARAMS ((int mult));
void s_globl PARAMS ((int arg));
void s_if PARAMS ((int arg));
void s_ifdef PARAMS ((int arg));
@ -101,10 +105,12 @@ void s_ignore PARAMS ((int arg));
void s_include PARAMS ((int arg));
void s_lcomm PARAMS ((int needs_align));
void s_lsym PARAMS ((int));
void s_mri_common PARAMS ((int));
void s_org PARAMS ((int));
void s_set PARAMS ((int));
void s_space PARAMS ((int mult));
void s_stab PARAMS ((int what));
void s_struct PARAMS ((int));
void s_text PARAMS ((int));
void stringer PARAMS ((int append_zero));
void s_xstab PARAMS ((int what));