char *input_line_pointer; /*->next char of source file to parse. */
-int generate_asm_lineno = 0; /* flag to generate line stab for .s file */
-
#if BITS_PER_CHAR != 8
/* The following table is indexed by[(char)] and will break if
a char does not have exactly 256 states (hopefully 0:255!)! */
char is_end_of_line[256] =
{
#ifdef CR_EOL
- _, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */
+ 99, _, _, _, _, _, _, _, _, _, 99, _, _, 99, _, _, /* @abcdefghijklmno */
#else
- _, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
+ 99, _, _, _, _, _, _, _, _, _, 99, _, _, _, _, _, /* @abcdefghijklmno */
#endif
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
#ifdef TC_HPPA
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));
{"endif", s_endif, 0},
/* endef */
{"equ", s_set, 0},
+ {"equiv", s_set, 1},
{"err", s_err, 0},
{"exitm", s_mexit, 0},
/* extend */
/* size */
{"space", s_space, 0},
{"skip", s_space, 0},
+ {"sleb128", s_leb128, 1},
{"spc", s_ignore, 0},
{"stabd", s_stab, 'd'},
{"stabn", s_stab, 'n'},
{"title", listing_title, 0}, /* Listing title */
{"ttl", listing_title, 0},
/* type */
+ {"uleb128", s_leb128, 0},
/* use */
/* val */
{"xcom", s_comm, 0},
buffer = input_scrub_new_file (name);
listing_file (name);
- listing_newline ("");
+ listing_newline (NULL);
+ register_dependency (name);
while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
{ /* We have another line to parse. */
char c;
int mri_line_macro;
+ LISTING_NEWLINE ();
HANDLE_CONDITIONAL_ASSEMBLY ();
c = get_symbol_end ();
&& (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
c = *input_line_pointer++;
}
know (c != ' '); /* No further leading whitespace. */
- LISTING_NEWLINE ();
+
+#ifndef NO_LISTING
+ /* If listing is on, and we are expanding a macro, then give
+ the listing code the contents of the expanded line. */
+ if (listing)
+ {
+ if ((listing & LISTING_MACEXP) && macro_nest > 0)
+ {
+ char *copy;
+ int len;
+
+ /* Find the end of the current expanded macro line. */
+ for (s = input_line_pointer-1; *s ; ++s)
+ if (is_end_of_line[(unsigned char) *s])
+ break;
+
+ /* Copy it for safe keeping. Also give an indication of
+ how much macro nesting is involved at this point. */
+ len = s - (input_line_pointer-1);
+ copy = (char *) xmalloc (len + macro_nest + 2);
+ memset (copy, '>', macro_nest);
+ copy[macro_nest] = ' ';
+ memcpy (copy + macro_nest + 1, input_line_pointer-1, len);
+ copy[macro_nest+1+len] = '\0';
+
+ /* Install the line with the listing facility. */
+ listing_newline (copy);
+ }
+ else
+ listing_newline (NULL);
+ }
+#endif
+
/*
* C is the 1st significant character.
* Input_line_pointer points after that character.
&& (rest[3] == ' ' || rest[3] == '\t'))
{
input_line_pointer = rest + 3;
- equals (s);
+ equals (s, 1);
continue;
}
}
#endif
))
{
- equals (s);
+ equals (s, 1);
demand_empty_rest_of_line ();
}
else
|| 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)
{
c = *input_line_pointer;
*input_line_pointer = '\0';
+ if (debug_type == DEBUG_STABS)
+ stabs_generate_asm_lineno ();
+
#ifdef OBJ_GENERATE_ASM_LINENO
- if (generate_asm_lineno == 0)
+#ifdef ECOFF_DEBUGGING
+ /* ECOFF assemblers automatically generate
+ debugging information. FIXME: This should
+ probably be handled elsewhere. */
+ if (debug_type == DEBUG_NONE)
{
- if (ecoff_no_current_file ())
- generate_asm_lineno = 1;
+ if (ecoff_no_current_file ())
+ debug_type = DEBUG_ECOFF;
}
- if (generate_asm_lineno == 1)
+
+ if (debug_type == DEBUG_ECOFF)
{
unsigned int lineno;
char *s;
as_where (&s, &lineno);
OBJ_GENERATE_ASM_LINENO (s, lineno);
- }
+ }
+#endif
#endif
if (macro_defined)
if (mri_pending_align)
{
- do_align (1, (char *) NULL, 0);
+ do_align (1, (char *) NULL, 0, 0);
mri_pending_align = 0;
if (line_label != NULL)
{
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)
+
+ if (fill == NULL)
{
- /* @@ Fix this right for BFD! */
- static char zero;
- static char nop_opcode = NOP_OPCODE;
+ int maybe_text;
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#else
if (now_seg != data_section && now_seg != bss_section)
- {
- fill = &nop_opcode;
- }
+ maybe_text = 1;
else
- {
- fill = &zero;
- }
+ maybe_text = 0;
+#endif
+
+ if (maybe_text)
+ default_fill = NOP_OPCODE;
+ else
+ 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 pseudo-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;
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
- if (S_IS_DEFINED (symbolP))
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
{
as_bad ("Ignoring attempt to re-define symbol `%s'.",
S_GET_NAME (symbolP));
align = get_absolute_expression ();
}
- if (S_IS_DEFINED (sym))
+ if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
{
-#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER)
- if (! S_IS_COMMON (sym))
-#endif
- {
- as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
- mri_comment_end (stop, stopc);
- ignore_rest_of_line ();
- return;
- }
+ as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
+ mri_comment_end (stop, stopc);
+ ignore_rest_of_line ();
+ return;
}
S_SET_EXTERNAL (sym);
/* If this is a fake .appfile, a fake newline was inserted into
the buffer. Passing -2 to new_logical_line tells it to
account for it. */
- new_logical_line (s, appfile ? -2 : -1);
+ int may_omit
+ = (! new_logical_line (s, appfile ? -2 : -1) && appfile);
/* In MRI mode, the preprocessor may have inserted an extraneous
backquote. */
++input_line_pointer;
demand_empty_rest_of_line ();
+ if (! may_omit)
+ {
#ifdef LISTING
- if (listing)
- listing_source_file (s);
+ if (listing)
+ listing_source_file (s);
#endif
- }
+ register_dependency (s);
#ifdef obj_app_file
- obj_app_file (s);
+ obj_app_file (s);
#endif
+ }
+ }
}
/* Handle the .appline pseudo-op. This is automatically generated by
if (temp_size && !need_pass_2)
{
- p = frag_var (rs_fill, (int) temp_size, (int) temp_size, (relax_substateT) 0, (symbolS *) 0, temp_repeat, (char *) 0);
+ p = frag_var (rs_fill, (int) temp_size, (int) temp_size,
+ (relax_substateT) 0, (symbolS *) 0, (offsetT) temp_repeat,
+ (char *) 0);
memset (p, 0, (unsigned int) temp_size);
/* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
* flavoured AS. The following bizzare behaviour is to be
demand_empty_rest_of_line ();
}
-void
-s_lcomm (needs_align)
+static void
+s_lcomm_internal (needs_align, bytes_p)
/* 1 if this was a ".bss" directive, which may require a 3rd argument
(alignment); 0 if it was an ".lcomm" (2 args only) */
int needs_align;
+ /* 1 if the alignment value should be interpreted as the byte boundary,
+ rather than the power of 2. */
+ int bytes_p;
{
register char *name;
register char c;
return;
}
align = get_absolute_expression ();
+ if (bytes_p)
+ {
+ /* 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 (align > max_alignment)
{
align = max_alignment;
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;
symbolP->sy_frag = frag_now;
pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
- temp, (char *)0);
+ (offsetT) temp, (char *) 0);
*pfrag = 0;
S_SET_SEGMENT (symbolP, bss_seg);
subseg_set (current_seg, current_subseg);
demand_empty_rest_of_line ();
-} /* s_lcomm() */
+} /* s_lcomm_internal() */
+
+void
+s_lcomm (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 0);
+}
+
+void s_lcomm_bytes (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 1);
+}
void
s_lsym (ignore)
get_line_sb (line)
sb *line;
{
+ char quote1, quote2, inquote;
+
if (input_line_pointer[-1] == '\n')
bump_line_counters ();
return 0;
}
- while (! is_end_of_line[(unsigned char) *input_line_pointer])
- sb_add_char (line, *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 (inquote == *input_line_pointer)
+ inquote = '\0';
+ else if (inquote == '\0')
+ {
+ 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
&& is_end_of_line[(unsigned char) *input_line_pointer])
{
s_mexit (ignore)
int ignore;
{
+ cond_exit_macro (macro_nest);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
+/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then
+ this is .equiv, and it is an error if the symbol is already
+ defined. */
+
void
-s_set (ignore)
- int ignore;
+s_set (equiv)
+ int equiv;
{
register char *name;
register char delim;
symbol_table_insert (symbolP);
*end_name = delim;
+
+ if (equiv
+ && S_IS_DEFINED (symbolP)
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP));
+
pseudo_set (symbolP);
demand_empty_rest_of_line ();
} /* s_set() */
}
else
{
- do_align (1, (char *) NULL, 0);
+ do_align (1, (char *) NULL, 0, 0);
if (line_label != NULL)
{
line_label->sy_frag = frag_now;
if (!need_pass_2)
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
- repeat, (char *) 0);
+ (offsetT) repeat, (char *) 0);
}
else
{
}
if (!need_pass_2)
p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
- make_expr_symbol (&exp), 0L, (char *) 0);
+ make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
}
if (p)
if (need_pass_2)
return;
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
+ appear as a four byte positive constant in the .line section,
+ followed by a 2 byte 0xffff. Look for that case here. */
+ {
+ static int dwarf_line = -1;
+
+ if (strcmp (segment_name (now_seg), ".line") != 0)
+ dwarf_line = -1;
+ else if (dwarf_line >= 0
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
+ listing_source_line ((unsigned int) dwarf_line);
+ else if (nbytes == 4
+ && exp->X_op == O_constant
+ && exp->X_add_number >= 0)
+ dwarf_line = exp->X_add_number;
+ else
+ dwarf_line = -1;
+ }
+#endif
+#endif
+
op = exp->X_op;
/* Allow `.word 0' in the absolute section. */
demand_empty_rest_of_line ();
} /* float_cons() */
\f
+/* Return the size of a LEB128 value */
+
+static inline int
+sizeof_sleb128 (value)
+ offsetT value;
+{
+ register int size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
+ Fortunately, we can structure things so that the extra work reduces
+ to a noop on systems that do things "properly". */
+ value = (value >> 7) | ~(-(offsetT)1 >> 7);
+ size += 1;
+ }
+ while (!(((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+
+ return size;
+}
+
+static inline int
+sizeof_uleb128 (value)
+ valueT value;
+{
+ register int size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ value >>= 7;
+ size += 1;
+ }
+ while (value != 0);
+
+ return size;
+}
+
+inline int
+sizeof_leb128 (value, sign)
+ valueT value;
+ int sign;
+{
+ if (sign)
+ return sizeof_sleb128 ((offsetT) value);
+ else
+ return sizeof_uleb128 (value);
+}
+
+/* Output a LEB128 value. */
+
+static inline int
+output_sleb128 (p, value)
+ char *p;
+ offsetT value;
+{
+ register char *orig = p;
+ register int more;
+
+ do
+ {
+ unsigned byte = (value & 0x7f);
+
+ /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
+ Fortunately, we can structure things so that the extra work reduces
+ to a noop on systems that do things "properly". */
+ value = (value >> 7) | ~(-(offsetT)1 >> 7);
+
+ more = !((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+
+ *p++ = byte;
+ }
+ while (more);
+
+ return p - orig;
+}
+
+static inline int
+output_uleb128 (p, value)
+ char *p;
+ valueT value;
+{
+ char *orig = p;
+
+ do
+ {
+ unsigned byte = (value & 0x7f);
+ value >>= 7;
+ if (value != 0)
+ /* More bytes to follow. */
+ byte |= 0x80;
+
+ *p++ = byte;
+ }
+ while (value != 0);
+
+ return p - orig;
+}
+
+inline int
+output_leb128 (p, value, sign)
+ char *p;
+ valueT value;
+ int sign;
+{
+ if (sign)
+ return output_sleb128 (p, (offsetT) value);
+ else
+ return output_uleb128 (p, value);
+}
+
+/* Do the same for bignums. We combine sizeof with output here in that
+ we don't output for NULL values of P. It isn't really as critical as
+ for "normal" values that this be streamlined. */
+
+static int
+output_big_sleb128 (p, bignum, size)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size;
+{
+ char *orig = p;
+ valueT val;
+ int loaded = 0;
+ unsigned byte;
+
+ /* Strip leading sign extensions off the bignum. */
+ while (size > 0 && bignum[size-1] == (LITTLENUM_TYPE)-1)
+ size--;
+
+ do
+ {
+ if (loaded < 7 && size > 0)
+ {
+ val |= (*bignum << loaded);
+ loaded += 8 * CHARS_PER_LITTLENUM;
+ size--;
+ bignum++;
+ }
+
+ byte = val & 0x7f;
+ loaded -= 7;
+ val >>= 7;
+
+ if (size == 0)
+ {
+ if ((val == 0 && (byte & 0x40) == 0)
+ || (~(val | ~(((valueT)1 << loaded) - 1)) == 0
+ && (byte & 0x40) != 0))
+ byte |= 0x80;
+ }
+
+ if (orig)
+ *p = byte;
+ p++;
+ }
+ while (byte & 0x80);
+
+ return p - orig;
+}
+
+static int
+output_big_uleb128 (p, bignum, size)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size;
+{
+ char *orig = p;
+ valueT val;
+ int loaded = 0;
+ unsigned byte;
+
+ /* Strip leading zeros off the bignum. */
+ /* XXX: Is this needed? */
+ while (size > 0 && bignum[size-1] == 0)
+ size--;
+
+ do
+ {
+ if (loaded < 7 && size > 0)
+ {
+ val |= (*bignum << loaded);
+ loaded += 8 * CHARS_PER_LITTLENUM;
+ size--;
+ bignum++;
+ }
+
+ byte = val & 0x7f;
+ loaded -= 7;
+ val >>= 7;
+
+ if (size > 0 || val)
+ byte |= 0x80;
+
+ if (orig)
+ *p = byte;
+ p++;
+ }
+ while (byte & 0x80);
+
+ return p - orig;
+}
+
+static inline int
+output_big_leb128 (p, bignum, size, sign)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size, sign;
+{
+ if (sign)
+ return output_big_sleb128 (p, bignum, size);
+ else
+ return output_big_uleb128 (p, bignum, size);
+}
+
+/* Generate the appropriate fragments for a given expression to emit a
+ leb128 value. */
+
+void
+emit_leb128_expr(exp, sign)
+ expressionS *exp;
+ int sign;
+{
+ operatorT op = exp->X_op;
+
+ if (op == O_absent || op == O_illegal)
+ {
+ as_warn ("zero assumed for missing expression");
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_big && exp->X_add_number <= 0)
+ {
+ as_bad ("floating point number invalid; zero assumed");
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_register)
+ {
+ as_warn ("register value used as expression");
+ op = O_constant;
+ }
+
+ if (op == O_constant)
+ {
+ /* If we've got a constant, emit the thing directly right now. */
+
+ valueT value = exp->X_add_number;
+ int size;
+ char *p;
+
+ size = sizeof_leb128 (value, sign);
+ p = frag_more (size);
+ output_leb128 (p, value, sign);
+ }
+ else if (op == O_big)
+ {
+ /* O_big is a different sort of constant. */
+
+ int size;
+ char *p;
+
+ size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
+ p = frag_more (size);
+ output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
+ }
+ else
+ {
+ /* Otherwise, we have to create a variable sized fragment and
+ resolve things later. */
+
+ frag_var (rs_leb128, sizeof_uleb128 (~(valueT)0), 0, sign,
+ make_expr_symbol (exp), 0, (char *) NULL);
+ }
+}
+
+/* Parse the .sleb128 and .uleb128 pseudos. */
+
+void
+s_leb128 (sign)
+ int sign;
+{
+ expressionS exp;
+
+ do {
+ expression (&exp);
+ emit_leb128_expr (&exp, sign);
+ } while (*input_line_pointer++ == ',');
+
+ input_line_pointer--;
+ demand_empty_rest_of_line ();
+}
+\f
/*
* stringer()
*
register int append_zero; /* 0: don't append '\0', else 1 */
{
register unsigned int c;
+ char *start;
#ifdef md_flush_pending_output
md_flush_pending_output ();
{
case '\"':
++input_line_pointer; /*->1st char of string. */
+ start = input_line_pointer;
while (is_a_char (c = next_char_of_string ()))
{
FRAG_APPEND_1_CHAR (c);
FRAG_APPEND_1_CHAR (0);
}
know (input_line_pointer[-1] == '\"');
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ /* In ELF, when gcc is emitting DWARF 1 debugging output, it
+ will emit .string with a filename in the .debug_sfnames
+ section to indicate a file name. I don't know if this
+ will work for compilers other than gcc, and I don't know
+ if it will work for DWARF 2. */
+ if (strcmp (segment_name (now_seg), ".debug_sfnames") == 0)
+ {
+ c = input_line_pointer[-1];
+ input_line_pointer[-1] = '\0';
+ listing_source_file (start);
+ input_line_pointer[-1] = c;
+ }
+#endif
+#endif
+
break;
case '<':
input_line_pointer++;
} /* 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);
}
path = filename;
gotit:
/* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
+ register_dependency (path);
newbuf = input_scrub_include_file (path, input_line_pointer);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
} /* s_include() */