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.
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;
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));
{"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
/* 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},
{"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},
{"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 */
{"stabn", s_stab, 'n'},
{"stabs", s_stab, 's'},
{"string", stringer, 1},
+ {"struct", s_struct, 0},
/* tag */
{"text", s_text, 0},
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++;
* 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 */
}
}
} /* while (more buffers to scan) */
- input_scrub_close (); /* Close the input file */
+ quit:
+ input_scrub_close (); /* Close the input file */
}
void
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;
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;
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
}
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() */
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;
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)
}
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");
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;
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
#endif /* REPEAT_CONS_EXPRESSIONS */
\f
+/* 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()
*
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
{
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
{