/* read.c - read a source file -
- Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 1997
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GAS; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#if 0
#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
#include "subsegs.h"
#include "sb.h"
#include "macro.h"
-#include "libiberty.h"
#include "obstack.h"
#include "listing.h"
+#include "ecoff.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x==':')
#define LEX_DOLLAR 3
#endif
+#ifndef LEX_TILDE
+/* The Delta 68k assembler permits ~ at start of label names. */
+#define LEX_TILDE 0
+#endif
+
/* used by is_... macros. our ctype[] */
char lex_type[256] =
{
LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 0, /* pqrstuvwxyz{|}~. */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static char *buffer; /* 1st char of each buffer of lines is here. */
static char *buffer_limit; /*->1 + last char in buffer. */
-#ifdef TARGET_BYTES_BIG_ENDIAN
-/* Hack to deal with tc-*.h defining TARGET_BYTES_BIG_ENDIAN to empty
- instead of to 0 or 1. */
-#if 5 - TARGET_BYTES_BIG_ENDIAN - 5 == 10
-#undef TARGET_BYTES_BIG_ENDIAN
-#define TARGET_BYTES_BIG_ENDIAN 1
-#endif
+/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
+ tc-<CPU>.h file. See the "Porting GAS" section of the internals manual. */
int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
-#else
-int target_big_endian /* = 0 */;
-#endif
static char *old_buffer; /* JF a hack */
static char *old_input;
may be needed. */
static int mri_pending_align;
+static void cons_worker PARAMS ((int, int));
static int scrub_from_string PARAMS ((char **));
-static void do_align PARAMS ((int, char *, int));
+static void do_align PARAMS ((int, char *, int, int));
+static void s_align PARAMS ((int, int));
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));
static segT get_known_segmented_expression PARAMS ((expressionS * expP));
static void pobegin PARAMS ((void));
{"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},
{"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'},
{
char *line_start = input_line_pointer;
char c;
+ int mri_line_macro;
+ LISTING_NEWLINE ();
HANDLE_CONDITIONAL_ASSEMBLY ();
c = get_symbol_end ();
- /* In MRI mode, the EQU pseudoop must be
- handled specially. */
+ /* In MRI mode, the EQU and MACRO pseudoops must
+ be handled specially. */
+ mri_line_macro = 0;
if (flag_m68k_mri)
{
char *rest = input_line_pointer + 1;
&& (rest[3] == ' ' || rest[3] == '\t'))
{
input_line_pointer = rest + 3;
- equals (line_start);
+ equals (line_start,
+ strncasecmp (rest, "SET", 3) == 0);
continue;
}
+ if (strncasecmp (rest, "MACRO", 5) == 0
+ && (rest[5] == ' '
+ || rest[5] == '\t'
+ || is_end_of_line[(unsigned char) rest[5]]))
+ mri_line_macro = 1;
}
- line_label = colon (line_start);
+ /* In MRI mode, we need to handle the MACRO
+ pseudo-op specially: we don't want to put the
+ symbol in the symbol table. */
+ if (! mri_line_macro)
+ line_label = colon (line_start);
+ else
+ line_label = symbol_create (line_start,
+ absolute_section,
+ (valueT) 0,
+ &zero_address_frag);
*input_line_pointer = c;
if (c == ':')
&& (rest[3] == ' ' || rest[3] == '\t'))
{
input_line_pointer = rest + 3;
- equals (s);
+ equals (s, 1);
continue;
}
}
}
else if (c == '='
- || (input_line_pointer[1] == '='
+ || ((c == ' ' || c == '\t')
+ && input_line_pointer[1] == '='
#ifdef TC_EQUAL_IN_INSN
&& ! TC_EQUAL_IN_INSN (c, input_line_pointer)
#endif
))
{
- equals (s);
+ equals (s, 1);
demand_empty_rest_of_line ();
}
else
|| ! ((pop->poc_handler == cons
&& pop->poc_val == 1)
|| (pop->poc_handler == s_space
- && pop->poc_val == 1))))
+ && pop->poc_val == 1)
+#ifdef tc_conditional_pseudoop
+ || tc_conditional_pseudoop (pop)
+#endif
+ || pop->poc_handler == s_if
+ || pop->poc_handler == s_ifdef
+ || pop->poc_handler == s_ifc
+ || pop->poc_handler == s_ifeqs
+ || pop->poc_handler == s_else
+ || pop->poc_handler == s_endif
+ || pop->poc_handler == s_globl
+ || pop->poc_handler == s_ignore)))
{
- do_align (1, (char *) NULL, 0);
+ do_align (1, (char *) NULL, 0, 0);
mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
}
/* Print the error msg now, while we still can */
goto quit;
}
else
- { /* machine instruction */
+ {
int inquote = 0;
- if (mri_pending_align)
- {
- do_align (1, (char *) NULL, 0);
- mri_pending_align = 0;
- }
-
/* WARNING: c has char, which may be end-of-line. */
/* Also: input_line_pointer->`\0` where c was. */
*input_line_pointer = c;
}
}
+ if (mri_pending_align)
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+
md_assemble (s); /* Assemble 1 instruction. */
*input_line_pointer++ = c;
} /* while (more buffers to scan) */
quit:
+
+#ifdef md_cleanup
+ md_cleanup();
+#endif
input_scrub_close (); /* Close the input file */
}
as_fatal (".abort detected. Abandoning ship.");
}
-/* Guts of .align directive. */
+/* Guts of .align directive. N is the power of two to which to align.
+ FILL may be NULL, or it may point to the bytes of the fill pattern.
+ LEN is the length of whatever FILL points to, if anything. MAX is
+ the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
static void
-do_align (n, fill, len)
+do_align (n, fill, len, max)
int n;
char *fill;
int len;
+ int max;
{
+ char default_fill;
+
#ifdef md_do_align
- md_do_align (n, fill, len, just_record_alignment);
+ md_do_align (n, fill, len, max, just_record_alignment);
#endif
- if (!fill)
- {
- /* @@ Fix this right for BFD! */
- static char zero;
- static char nop_opcode = NOP_OPCODE;
+ if (fill == NULL)
+ {
+ /* FIXME: Fix this right for BFD! */
if (now_seg != data_section && now_seg != bss_section)
- {
- fill = &nop_opcode;
- }
+ default_fill = NOP_OPCODE;
else
- {
- fill = &zero;
- }
+ default_fill = 0;
+ fill = &default_fill;
len = 1;
}
/* Only make a frag if we HAVE to. . . */
- if (n && !need_pass_2)
+ if (n != 0 && !need_pass_2)
{
if (len <= 1)
- frag_align (n, *fill);
+ frag_align (n, *fill, max);
else
- frag_align_pattern (n, fill, len);
+ frag_align_pattern (n, fill, len, max);
}
#ifdef md_do_align
record_alignment (now_seg, n);
}
-/* For machines where ".align 4" means align to a 4 byte boundary. */
-void
-s_align_bytes (arg)
+/* Handle the .align pseudo-op. A positive ARG is a default alignment
+ (in bytes). A negative ARG is the negative of the length of the
+ fill pattern. BYTES_P is non-zero if the alignment value should be
+ interpreted as the byte boundary, rather than the power of 2. */
+
+static void
+s_align (arg, bytes_p)
int arg;
+ int bytes_p;
{
- register unsigned int temp;
- char temp_fill;
- unsigned int i = 0;
- unsigned long max_alignment = 1 << 15;
+ register unsigned int align;
char *stop = NULL;
char stopc;
+ offsetT fill = 0;
+ int max;
+ int fill_p;
if (flag_mri)
stop = mri_comment_field (&stopc);
if (is_end_of_line[(unsigned char) *input_line_pointer])
{
if (arg < 0)
- temp = 0;
+ align = 0;
else
- temp = arg; /* Default value from pseudo-op table */
+ align = arg; /* Default value from pseudo-op table */
}
else
- temp = get_absolute_expression ();
-
- if (temp > max_alignment)
{
- as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
+ align = get_absolute_expression ();
+ SKIP_WHITESPACE ();
}
- /* For the sparc, `.align (1<<n)' actually means `.align n' so we
- have to convert it. */
- if (temp != 0)
+ if (bytes_p)
{
- for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
- ;
+ /* Convert to a power of 2. */
+ if (align != 0)
+ {
+ unsigned int i;
+
+ for (i = 0; (align & 1) == 0; align >>= 1, ++i)
+ ;
+ if (align != 1)
+ as_bad ("Alignment not a power of 2");
+ align = i;
+ }
}
- if (temp != 1)
- as_bad ("Alignment not a power of 2");
- temp = i;
- if (*input_line_pointer == ',')
+ if (align > 15)
{
- offsetT fillval;
- int len;
+ align = 15;
+ as_bad ("Alignment too large: %u assumed", align);
+ }
- input_line_pointer++;
- fillval = get_absolute_expression ();
- if (arg >= 0)
- len = 1;
+ if (*input_line_pointer != ',')
+ {
+ fill_p = 0;
+ max = 0;
+ }
+ else
+ {
+ ++input_line_pointer;
+ if (*input_line_pointer == ',')
+ fill_p = 0;
else
- len = - arg;
- if (len <= 1)
{
- temp_fill = fillval;
- do_align (temp, &temp_fill, len);
+ fill = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ fill_p = 1;
}
+
+ if (*input_line_pointer != ',')
+ max = 0;
else
{
- char ab[16];
-
- if (len > sizeof ab)
- abort ();
- md_number_to_chars (ab, fillval, len);
- do_align (temp, ab, len);
+ ++input_line_pointer;
+ max = get_absolute_expression ();
}
}
- else
+
+ if (! fill_p)
{
if (arg < 0)
as_warn ("expected fill pattern missing");
- do_align (temp, (char *) NULL, 0);
- }
-
- if (flag_mri)
- mri_comment_end (stop, stopc);
-
- demand_empty_rest_of_line ();
-}
-
-/* For machines where ".align 4" means align to 2**4 boundary. */
-void
-s_align_ptwo (arg)
- int arg;
-{
- register int temp;
- char temp_fill;
- long max_alignment = 15;
- char *stop = NULL;
- char stopc;
-
- if (flag_mri)
- stop = mri_comment_field (&stopc);
-
- temp = get_absolute_expression ();
- if (temp > max_alignment)
- as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
- else if (temp < 0)
- {
- as_bad ("Alignment negative. 0 assumed.");
- temp = 0;
+ do_align (align, (char *) NULL, 0, max);
}
- if (*input_line_pointer == ',')
+ else
{
- offsetT fillval;
- int len;
+ int fill_len;
- input_line_pointer++;
- fillval = get_absolute_expression ();
if (arg >= 0)
- len = 1;
+ fill_len = 1;
else
- len = - arg;
- if (len <= 1)
+ fill_len = - arg;
+ if (fill_len <= 1)
{
- temp_fill = fillval;
- do_align (temp, &temp_fill, len);
+ char fill_char;
+
+ fill_char = fill;
+ do_align (align, &fill_char, fill_len, max);
}
else
{
char ab[16];
- if (len > sizeof ab)
+ if (fill_len > sizeof ab)
abort ();
- md_number_to_chars (ab, fillval, len);
- do_align (temp, ab, len);
+ md_number_to_chars (ab, fill, fill_len);
+ do_align (align, ab, fill_len, max);
}
}
- else
- {
- if (arg < 0)
- as_warn ("expected fill pattern missing");
- do_align (temp, (char *) NULL, 0);
- }
if (flag_mri)
mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
}
+/* Handle the .align pseudo-op on machines where ".align 4" means
+ align to a 4 byte boundary. */
+
+void
+s_align_bytes (arg)
+ int arg;
+{
+ s_align (arg, 1);
+}
+
+/* Handle the .align pseud-op on machines where ".align 4" means align
+ to a 2**4 boundary. */
+
+void
+s_align_ptwo (arg)
+ int arg;
+{
+ s_align (arg, 0);
+}
+
void
s_comm (ignore)
int ignore;
}
else if (temp_repeat <= 0)
{
- as_warn ("Repeat < 0, .fill ignored");
+ if (temp_repeat < 0)
+ as_warn ("Repeat < 0, .fill ignored");
temp_size = 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
else
align = 0;
+#ifdef OBJ_EVAX
+ /* FIXME: This needs to be done in a more general fashion. */
+ align = 3;
+#endif
+
record_alignment(bss_seg, align);
}
else
{
/* Assume some objects may require alignment on some systems. */
-#ifdef TC_ALPHA
+#if defined (TC_ALPHA) && ! defined (VMS)
if (temp > 1)
{
align = ffs (temp) - 1;
subseg_set (bss_seg, 1);
if (align)
- frag_align (align, 0);
+ frag_align (align, 0, 0);
/* detach from old frag */
if (S_GET_SEGMENT (symbolP) == bss_seg)
symbolP->sy_frag->fr_symbol = NULL;
get_line_sb (line)
sb *line;
{
+ char quote1, quote2, inquote;
+
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+
if (input_line_pointer >= buffer_limit)
{
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
return 0;
}
- while (! is_end_of_line[(unsigned char) *input_line_pointer])
- sb_add_char (line, *input_line_pointer++);
- while (input_line_pointer < buffer_limit
- && is_end_of_line[(unsigned char) *input_line_pointer])
+ /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
+ code needs to be changed. */
+ if (! flag_m68k_mri)
+ quote1 = '"';
+ else
+ quote1 = '\0';
+
+ quote2 = '\0';
+ if (flag_m68k_mri)
+ quote2 = '\'';
+#ifdef LEX_IS_STRINGQUOTE
+ quote2 = '\'';
+#endif
+
+ inquote = '\0';
+ while (! is_end_of_line[(unsigned char) *input_line_pointer]
+ || (inquote != '\0' && *input_line_pointer != '\n'))
{
- if (*input_line_pointer == '\n')
+ if (inquote == *input_line_pointer)
+ inquote = '\0';
+ else if (inquote == '\0')
{
- bump_line_counters ();
- LISTING_NEWLINE ();
+ if (*input_line_pointer == quote1)
+ inquote = quote1;
+ else if (*input_line_pointer == quote2)
+ inquote = quote2;
}
+ sb_add_char (line, *input_line_pointer++);
+ }
+ while (input_line_pointer < buffer_limit && *input_line_pointer == '\n')
+ {
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
++input_line_pointer;
}
return 1;
sb s;
sb label;
const char *err;
+ const char *name;
as_where (&file, &line);
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);
+ err = define_macro (0, &s, &label, get_line_sb, &name);
if (err != NULL)
as_bad_where (file, line, "%s", err);
else
S_SET_VALUE (line_label, 0);
line_label->sy_frag = &zero_address_frag;
}
+
+ if (((flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+ || 1
+#endif
+ )
+ && hash_find (po_hash, name) != NULL)
+ || (! flag_m68k_mri
+ && *name == '.'
+ && hash_find (po_hash, name + 1) != NULL))
+ as_warn ("attempt to redefine pseudo-op `%s' ignored",
+ name);
}
sb_kill (&s);
int mult;
{
expressionS exp;
- long temp_fill;
+ expressionS val;
char *p = 0;
char *stop = NULL;
char stopc;
+ int bytes;
#ifdef md_flush_pending_output
md_flush_pending_output ();
if (flag_mri)
stop = mri_comment_field (&stopc);
- /* Just like .fill, but temp_size = 1 */
- expression (&exp);
- if (exp.X_op == O_constant)
+ /* In m68k MRI mode, we need to align to a word boundary, unless
+ this is ds.b. */
+ if (flag_m68k_mri && mult > 1)
{
- 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;
+ abs_section_offset += abs_section_offset & 1;
+ if (line_label != NULL)
+ S_SET_VALUE (line_label, abs_section_offset);
}
-
- /* 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 (mri_common_symbol != NULL)
{
- S_SET_VALUE (mri_common_symbol,
- S_GET_VALUE (mri_common_symbol) + repeat);
- goto getout;
- }
+ valueT val;
- 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)
- {
- as_bad ("space allocation too complex in absolute section");
- subseg_set (text_section, 0);
+ val = S_GET_VALUE (mri_common_symbol);
+ if ((val & 1) != 0)
+ {
+ S_SET_VALUE (mri_common_symbol, val + 1);
+ if (line_label != NULL)
+ {
+ know (line_label->sy_value.X_op == O_symbol);
+ know (line_label->sy_value.X_add_symbol == mri_common_symbol);
+ line_label->sy_value.X_add_number += 1;
+ }
+ }
}
- if (mri_common_symbol != NULL)
+ else
{
- as_bad ("space allocation too complex in common section");
- mri_common_symbol = NULL;
+ do_align (1, (char *) NULL, 0, 0);
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
}
- if (!need_pass_2)
- p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
- make_expr_symbol (&exp), 0L, (char *) 0);
}
+
+ bytes = mult;
+
+ expression (&exp);
+
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
- input_line_pointer++;
- temp_fill = get_absolute_expression ();
+ ++input_line_pointer;
+ expression (&val);
}
else
{
- temp_fill = 0;
+ val.X_op = O_constant;
+ val.X_add_number = 0;
}
- if (p)
+
+ 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))
{
- *p = temp_fill;
+ if (exp.X_op != O_constant)
+ as_bad ("Unsupported variable size or fill value");
+ else
+ {
+ offsetT i;
+
+ if (mult == 0)
+ mult = 1;
+ bytes = mult * exp.X_add_number;
+ for (i = 0; i < exp.X_add_number; i++)
+ emit_expr (&val, mult);
+ }
+ }
+ else
+ {
+ if (exp.X_op == O_constant)
+ {
+ long repeat;
+
+ repeat = exp.X_add_number;
+ if (mult)
+ repeat *= mult;
+ bytes = repeat;
+ 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);
+ }
+ 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");
+ 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 (p)
+ *p = val.X_add_number;
}
getout:
+
+ /* In MRI mode, after an odd number of bytes, we must align to an
+ even word boundary, unless the next instruction is a dc.b, ds.b
+ or dcb.b. */
+ if (flag_mri && (bytes & 1) != 0)
+ mri_pending_align = 1;
+
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
c = 0;
do
{
register valueT get;
register valueT use;
register valueT mask;
+ valueT hibit;
register valueT unmask;
/* JF << of >= number of bits in the object is undefined. In
particular SPARC (Sun 4) has problems */
if (nbytes >= sizeof (valueT))
- mask = 0;
+ {
+ mask = 0;
+ if (nbytes > sizeof (valueT))
+ hibit = 0;
+ else
+ hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+ }
else
- mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
+ {
+ /* Don't store these bits. */
+ mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
+ hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+ }
unmask = ~mask; /* Do store these bits. */
get = exp->X_add_number;
use = get & unmask;
- if ((get & mask) != 0 && (get & mask) != mask)
+ if ((get & mask) != 0
+ && ((get & mask) != mask
+ || (get & hibit) == 0))
{ /* Leading bits contain both 0s & 1s. */
- as_warn ("Value 0x%lx truncated to 0x%lx.", get, use);
+ as_warn ("Value 0x%lx truncated to 0x%lx.",
+ (unsigned long) get, (unsigned long) use);
}
/* put bytes in right order. */
md_number_to_chars (p, use, (int) nbytes);
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
- fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
- /* @@ Should look at CPU word size. */
- nbytes == 2 ? BFD_RELOC_16
- : nbytes == 8 ? BFD_RELOC_64
- : BFD_RELOC_32);
+ {
+ bfd_reloc_code_real_type r;
+
+ switch (nbytes)
+ {
+ case 1:
+ r = BFD_RELOC_8;
+ break;
+ case 2:
+ r = BFD_RELOC_16;
+ break;
+ case 4:
+ r = BFD_RELOC_32;
+ break;
+ case 8:
+ r = BFD_RELOC_64;
+ break;
+ default:
+ as_bad ("unsupported BFD relocation size %u", nbytes);
+ r = BFD_RELOC_32;
+ break;
+ }
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
+ 0, r);
+ }
#endif
#else
#ifdef TC_CONS_FIX_NEW
return;
}
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
do
{
/* input_line_pointer->1st char of a flonum (we hope!). */
c = NOT_A_CHAR;
break;
+ case '\n':
+ as_warn ("Unterminated string: Newline inserted.");
+ bump_line_counters ();
+ break;
+
#ifndef NO_STRING_ESCAPES
case '\\':
switch (c = *input_line_pointer++)
/* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
as_warn ("Unterminated string: Newline inserted.");
c = '\n';
+ bump_line_counters ();
break;
default:
} /* is_it_end_of_statement() */
void
-equals (sym_name)
+equals (sym_name, reassign)
char *sym_name;
+ int reassign;
{
register symbolS *symbolP; /* symbol we are working with */
char *stop;
else
{
symbolP = symbol_find_or_make (sym_name);
+ /* Permit register names to be redefined. */
+ if (! reassign
+ && S_IS_DEFINED (symbolP)
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP));
pseudo_set (symbolP);
}