aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-08-09 19:36:25 +0000
committerIan Lance Taylor <ian@airs.com>1995-08-09 19:36:25 +0000
commite28c40d72519ff512fd217c6e74ef27a249b7693 (patch)
tree69b3089146732e32d9c999f4a0cb0462fae6f635
parente120d9fbcd6e5768201d7263c6cc2c387b7a837f (diff)
downloadgdb-e28c40d72519ff512fd217c6e74ef27a249b7693.zip
gdb-e28c40d72519ff512fd217c6e74ef27a249b7693.tar.gz
gdb-e28c40d72519ff512fd217c6e74ef27a249b7693.tar.bz2
* 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.
-rw-r--r--gas/ChangeLog58
-rw-r--r--gas/read.c421
-rw-r--r--gas/read.h8
3 files changed, 379 insertions, 108 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 4955aaa..09e0b74 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/read.c b/gas/read.c
index c77f588..af8c775 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -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
{
diff --git a/gas/read.h b/gas/read.h
index 3a3d82d..4a00b32 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -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));