{"ascii", stringer, 0},
{"asciz", stringer, 1},
{"balign", s_align_bytes, 0},
- {"balignw", s_align_bytes, 2},
- {"balignl", s_align_bytes, 4},
+ {"balignw", s_align_bytes, -2},
+ {"balignl", s_align_bytes, -4},
/* block */
{"byte", cons, 1},
{"comm", s_comm, 0},
{"irepc", s_irp, 1},
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0}, /* Listing flags */
+ {"linkonce", s_linkonce, 0},
{"list", listing_list, 1}, /* Turn listing on */
{"llen", listing_psize, 1},
{"long", cons, 4},
{"lsym", s_lsym, 0},
{"macro", s_macro, 0},
{"mexit", s_mexit, 0},
+ {"mri", s_mri, 0},
+ {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */
{"name", s_ignore, 0},
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0}, /* Turn listing off */
{"offset", s_struct, 0},
{"org", s_org, 0},
{"p2align", s_align_ptwo, 0},
- {"p2alignw", s_align_ptwo, 2},
- {"p2alignl", s_align_ptwo, 4},
+ {"p2alignw", s_align_ptwo, -2},
+ {"p2alignl", s_align_ptwo, -4},
{"page", listing_eject, 0},
{"plen", listing_psize, 0},
{"print", s_print, 0},
{"single", float_cons, 'f'},
/* size */
{"space", s_space, 0},
+ {"skip", s_space, 0},
{"spc", s_ignore, 0},
{"stabd", s_stab, 'd'},
{"stabn", s_stab, 'n'},
stop = mri_comment_field (&stopc);
if (is_end_of_line[(unsigned char) *input_line_pointer])
- temp = arg; /* Default value from pseudo-op table */
+ {
+ if (arg < 0)
+ temp = 0;
+ else
+ temp = arg; /* Default value from pseudo-op table */
+ }
else
temp = get_absolute_expression ();
if (*input_line_pointer == ',')
{
offsetT fillval;
+ int len;
input_line_pointer++;
fillval = get_absolute_expression ();
- if (arg == 0)
- arg = 1;
- if (arg <= 1)
+ if (arg >= 0)
+ len = 1;
+ else
+ len = - arg;
+ if (len <= 1)
{
temp_fill = fillval;
- do_align (temp, &temp_fill, arg);
+ do_align (temp, &temp_fill, len);
}
else
{
char ab[16];
- if (arg > sizeof ab)
+ if (len > sizeof ab)
abort ();
- md_number_to_chars (ab, fillval, arg);
- do_align (temp, ab, arg);
+ md_number_to_chars (ab, fillval, len);
+ do_align (temp, ab, len);
}
}
else
{
- if (arg > 0)
+ if (arg < 0)
as_warn ("expected fill pattern missing");
do_align (temp, (char *) NULL, 0);
}
if (*input_line_pointer == ',')
{
offsetT fillval;
+ int len;
input_line_pointer++;
fillval = get_absolute_expression ();
- if (arg == 0)
- arg = 1;
- if (arg <= 1)
+ if (arg >= 0)
+ len = 1;
+ else
+ len = - arg;
+ if (len <= 1)
{
temp_fill = fillval;
- do_align (temp, &temp_fill, arg);
+ do_align (temp, &temp_fill, len);
}
else
{
char ab[16];
- if (arg > sizeof ab)
+ if (len > sizeof ab)
abort ();
- md_number_to_chars (ab, fillval, arg);
- do_align (temp, ab, arg);
+ md_number_to_chars (ab, fillval, len);
+ do_align (temp, ab, len);
}
}
else
{
- if (arg > 0)
+ if (arg < 0)
as_warn ("expected fill pattern missing");
do_align (temp, (char *) NULL, 0);
}
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
+/* Handle the .linkonce pseudo-op. This tells the assembler to mark
+ the section to only be linked once. However, this is not supported
+ by most object file formats. This takes an optional argument,
+ which is what to do about duplicates. */
+
+void
+s_linkonce (ignore)
+ int ignore;
+{
+ enum linkonce_type type;
+
+ SKIP_WHITESPACE ();
+
+ type = LINKONCE_DISCARD;
+
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ char *s;
+ char c;
+
+ s = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (s, "discard") == 0)
+ type = LINKONCE_DISCARD;
+ else if (strcasecmp (s, "one_only") == 0)
+ type = LINKONCE_ONE_ONLY;
+ else if (strcasecmp (s, "same_size") == 0)
+ type = LINKONCE_SAME_SIZE;
+ else if (strcasecmp (s, "same_contents") == 0)
+ type = LINKONCE_SAME_CONTENTS;
+ else
+ as_warn ("unrecognized .linkonce type `%s'", s);
+
+ *input_line_pointer = c;
+ }
+
+#ifdef obj_handle_link_once
+ obj_handle_link_once (type);
+#else /* ! defined (obj_handle_link_once) */
+#ifdef BFD_ASSEMBLER
+ {
+ flagword flags;
+
+ if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
+ as_warn (".linkonce is not supported for this object file format");
+
+ flags = bfd_get_section_flags (stdoutput, now_seg);
+ flags |= SEC_LINK_ONCE;
+ switch (type)
+ {
+ default:
+ abort ();
+ case LINKONCE_DISCARD:
+ flags |= SEC_LINK_DUPLICATES_DISCARD;
+ break;
+ case LINKONCE_ONE_ONLY:
+ flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+ break;
+ case LINKONCE_SAME_SIZE:
+ flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
+ break;
+ case LINKONCE_SAME_CONTENTS:
+ flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
+ break;
+ }
+ if (! bfd_set_section_flags (stdoutput, now_seg, flags))
+ as_bad ("bfd_set_section_flags: %s",
+ bfd_errmsg (bfd_get_error ()));
+ }
+#else /* ! defined (BFD_ASSEMBLER) */
+ as_warn (".linkonce is not supported for this object file format");
+#endif /* ! defined (BFD_ASSEMBLER) */
+#endif /* ! defined (obj_handle_link_once) */
+
+ demand_empty_rest_of_line ();
+}
+
void
s_lcomm (needs_align)
/* 1 if this was a ".bss" directive, which may require a 3rd argument
{
bss_seg = subseg_new (".sbss", 1);
seg_info (bss_seg)->bss = 1;
+#ifdef BFD_ASSEMBLER
+ if (! bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
+ as_warn ("error setting flags for \".sbss\": %s",
+ bfd_errmsg (bfd_get_error ()));
+#endif
}
}
#endif
get_line_sb (line)
sb *line;
{
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+
if (input_line_pointer >= buffer_limit)
{
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
while (input_line_pointer < buffer_limit
&& is_end_of_line[(unsigned char) *input_line_pointer])
{
- if (*input_line_pointer == '\n')
- {
- bump_line_counters ();
- LISTING_NEWLINE ();
- }
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
++input_line_pointer;
}
return 1;
if (line_label != NULL)
sb_add_string (&label, S_GET_NAME (line_label));
- demand_empty_rest_of_line ();
-
err = define_macro (0, &s, &label, get_line_sb);
if (err != NULL)
as_bad_where (file, line, "%s", err);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
+/* Switch in and out of MRI mode. */
+
+void
+s_mri (ignore)
+ int ignore;
+{
+ int on, old_flag;
+
+ on = get_absolute_expression ();
+ old_flag = flag_mri;
+ if (on != 0)
+ {
+ flag_mri = 1;
+#ifdef TC_M68K
+ flag_m68k_mri = 1;
+#endif
+ }
+ else
+ {
+ flag_mri = 0;
+ flag_m68k_mri = 0;
+ }
+
+#ifdef MRI_MODE_CHANGE
+ if (on != old_flag)
+ MRI_MODE_CHANGE (on);
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
/* Handle changing the location counter. */
static void
/* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be
called by the obj-format routine which handles section changing
when in MRI mode. It will create a new section, and return it. It
- will set *TYPE to the section type: one of '\0' (unspecified), 'C'
- (code), 'D' (data), 'M' (mixed), or 'R' (romable). If
- BFD_ASSEMBLER is defined, the flags will be set in the section. */
+ will set *TYPE to the section type: one of 'C' (code), 'D' (data),
+ 'M' (mixed), or 'R' (romable). If BFD_ASSEMBLER is defined, the
+ flags will be set in the section. */
void
s_mri_sect (type)
*input_line_pointer = '\0';
}
- name = strdup (name);
- if (name == NULL)
- as_fatal ("virtual memory exhausted");
+ name = xstrdup (name);
*input_line_pointer = c;
record_alignment (seg, align);
}
- *type = '\0';
+ *type = 'C';
if (*input_line_pointer == ',')
{
c = *++input_line_pointer;
flags = SEC_NO_FLAGS;
if (*type == 'C')
- flags = SEC_CODE;
- else if (*type == 'D')
- flags = SEC_DATA;
+ flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
+ else if (*type == 'D' || *type == 'M')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
else if (*type == 'R')
- flags = SEC_ROM;
+ flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
if (flags != SEC_NO_FLAGS)
{
if (! bfd_set_section_flags (stdoutput, seg, flags))
name = input_line_pointer;
c = get_symbol_end ();
- name = strdup (name);
- if (name == NULL)
- as_fatal ("virtual memory exhausted");
+ name = xstrdup (name);
*input_line_pointer = c;
int mult;
{
expressionS exp;
- long temp_fill;
+ expressionS val;
char *p = 0;
char *stop = NULL;
char stopc;
if (flag_mri)
stop = mri_comment_field (&stopc);
- /* Just like .fill, but temp_size = 1 */
expression (&exp);
- if (exp.X_op == O_constant)
- {
- long repeat;
- repeat = exp.X_add_number;
- if (mult)
- repeat *= mult;
- if (repeat <= 0)
- {
- if (! flag_mri || repeat < 0)
- as_warn (".space repeat count is %s, ignored",
- repeat ? "negative" : "zero");
- goto getout;
- }
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ expression (&val);
+ }
+ else
+ {
+ val.X_op = O_constant;
+ val.X_add_number = 0;
+ }
- /* If we are in the absolute section, just bump the offset. */
- if (now_seg == absolute_section)
+ if (val.X_op != O_constant
+ || val.X_add_number < - 0x80
+ || val.X_add_number > 0xff
+ || (mult != 0 && mult != 1 && val.X_add_number != 0))
+ {
+ if (exp.X_op != O_constant)
+ as_bad ("Unsupported variable size or fill value");
+ else
{
- abs_section_offset += repeat;
- goto getout;
- }
+ offsetT i;
- /* 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);
- goto getout;
+ if (mult == 0)
+ mult = 1;
+ for (i = 0; i < exp.X_add_number; i++)
+ emit_expr (&val, mult);
}
-
- if (!need_pass_2)
- p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
- repeat, (char *) 0);
}
else
{
- if (now_seg == absolute_section)
+ if (exp.X_op == O_constant)
{
- as_bad ("space allocation too complex in absolute section");
- subseg_set (text_section, 0);
+ long repeat;
+
+ repeat = exp.X_add_number;
+ if (mult)
+ repeat *= mult;
+ if (repeat <= 0)
+ {
+ if (! flag_mri || repeat < 0)
+ as_warn (".space repeat count is %s, ignored",
+ repeat ? "negative" : "zero");
+ goto getout;
+ }
+
+ /* If we are in the absolute section, just bump the offset. */
+ if (now_seg == absolute_section)
+ {
+ abs_section_offset += repeat;
+ goto getout;
+ }
+
+ /* 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);
+ goto getout;
+ }
+
+ if (!need_pass_2)
+ p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
+ repeat, (char *) 0);
}
- if (mri_common_symbol != NULL)
+ else
{
- as_bad ("space allocation too complex in common section");
- mri_common_symbol = NULL;
+ 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");
+ 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);
}
- if (!need_pass_2)
- p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
- make_expr_symbol (&exp), 0L, (char *) 0);
- }
- SKIP_WHITESPACE ();
- if (*input_line_pointer == ',')
- {
- input_line_pointer++;
- temp_fill = get_absolute_expression ();
- }
- else
- {
- temp_fill = 0;
- }
- if (p)
- {
- *p = temp_fill;
+
+ if (p)
+ *p = val.X_add_number;
}
getout: