/* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
- Copyright (C) 1999-2016 Free Software Foundation, Inc.
+ Copyright (C) 1999-2020 Free Software Foundation, Inc.
Contributed by Timothy Wall (twall@cygnus.com)
This file is part of GAS, the GNU Assembler.
#include "sb.h"
#include "macro.h"
#include "subsegs.h"
-#include "struc-symbol.h"
#include "opcode/tic54x.h"
#include "obj-coff.h"
#include <math.h>
static int assembly_begun = 0;
/* Addressing mode is not entirely implemented; the latest rev of the Other
assembler doesn't seem to make any distinction whatsoever; all relocations
- are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16,
+ are stored as extended relocations. Older versions used REL16 vs RELEXT16,
but now it seems all relocations are RELEXT16. We use all RELEXT16.
The cpu version is kind of a waste of time as well. There is one
static struct hash_control *math_hash; /* Built-in math functions. */
/* Allow maximum levels of macro nesting; level 0 is the main substitution
symbol table. The other assembler only does 32 levels, so there! */
-static struct hash_control *subsym_hash[100];
+#define MAX_SUBSYM_HASH 100
+static struct hash_control *subsym_hash[MAX_SUBSYM_HASH];
/* Keep track of local labels so we can substitute them before GAS sees them
since macros use their own 'namespace' for local labels, use a separate hash
void
md_show_usage (FILE *stream)
{
- fprintf (stream, _("C54x-specific command line options:\n"));
+ fprintf (stream, _("C54x-specific command line options:\n"));
fprintf (stream, _("-mfar-mode | -mf Use extended addressing\n"));
fprintf (stream, _("-mcpu=<CPU version> Specify the CPU version\n"));
fprintf (stream, _("-merrors-to-file <filename>\n"));
fprintf (stream, _("-me <filename> Redirect errors to a file\n"));
}
-/* Output a single character (upper octect is zero). */
+/* Output a single character (upper octet is zero). */
static void
tic54x_emit_char (char c)
str = input_line_pointer;
while ((c = *input_line_pointer) != ',')
{
- if (is_end_of_line[(int) *input_line_pointer])
+ if (is_end_of_line[(unsigned char) c])
break;
++input_line_pointer;
}
symbolP = symbol_find_or_make (name);
if (S_GET_SEGMENT (symbolP) == bss_section)
- symbolP->sy_frag->fr_symbol = (symbolS *) NULL;
+ symbol_get_frag (symbolP)->fr_symbol = (symbolS *) NULL;
symbol_set_frag (symbolP, frag_now);
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
{
/* Offset is ignored in inner structs. */
SKIP_WHITESPACE ();
- if (!is_end_of_line[(int) *input_line_pointer])
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
start_offset = get_absolute_expression ();
else
start_offset = 0;
int longword_align = 0;
SKIP_WHITESPACE ();
- if (!is_end_of_line[(int) *input_line_pointer])
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
count = get_absolute_expression ();
switch (type)
if (c == ',')
{
input_line_pointer++;
- if (is_end_of_line[(int) *input_line_pointer])
+ if (is_end_of_line[(unsigned char) *input_line_pointer])
c = *input_line_pointer;
}
}
blocking_flag = alignment_flag = 0;
seg = subseg_new (name, 0);
- flags = bfd_get_section_flags (stdoutput, seg) | SEC_ALLOC;
+ flags = bfd_section_flags (seg) | SEC_ALLOC;
if (alignment_flag)
{
if (blocking_flag)
flags |= SEC_TIC54X_BLOCK;
- if (!bfd_set_section_flags (stdoutput, seg, flags))
+ if (!bfd_set_section_flags (seg, flags))
as_warn (_("Error setting flags for \"%s\": %s"), name,
bfd_errmsg (bfd_get_error ()));
SKIP_WHITESPACE ();
ver = input_line_pointer;
- while (!is_end_of_line[(int) *input_line_pointer])
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
c = *input_line_pointer;
*input_line_pointer = 0;
/* Only ".align" with no argument is allowed within .struct/.union. */
int count = arg;
- if (!is_end_of_line[(int) *input_line_pointer])
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
{
if (arg == 2)
as_warn (_("Argument to .even ignored"));
s_align_bytes (count << 1);
}
-/* Initialize multiple-bit fields withing a single word of memory. */
+/* Initialize multiple-bit fields within a single word of memory. */
static void
tic54x_field (int ignore ATTRIBUTE_UNUSED)
{
if (!tic54x_initialized_section (seg))
{
- as_bad (_("Current section is unitialized, "
+ as_bad (_("Current section is uninitialized, "
"section name required for .clink"));
ignore_rest_of_line ();
return;
else
{
filename = input_line_pointer;
- while (!is_end_of_line[(int) *input_line_pointer])
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
c = *input_line_pointer;
*input_line_pointer = '\0';
else
{
msg = input_line_pointer;
- while (!is_end_of_line[(int) *input_line_pointer])
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
c = *input_line_pointer;
*input_line_pointer = 0;
ILLEGAL_WITHIN_STRUCT ();
SKIP_WHITESPACE ();
- if (!is_end_of_line[(int) *input_line_pointer])
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
count = get_absolute_expression ();
- do_repeat (count, "LOOP", "ENDLOOP");
+ do_repeat ((size_t) count, "LOOP", "ENDLOOP");
}
/* Normally, endloop gets eaten by the preceding loop. */
ILLEGAL_WITHIN_STRUCT ();
SKIP_WHITESPACE ();
- if (!is_end_of_line[(int) *input_line_pointer])
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
cond = get_absolute_expression ();
if (cond)
seg->flags |= SEC_TIC54X_BLOCK;
c = *input_line_pointer;
- if (!is_end_of_line[(int) c])
+ if (!is_end_of_line[(unsigned char) c])
++input_line_pointer;
}
if (c == ',')
{
++input_line_pointer;
- if (is_end_of_line[(int) *input_line_pointer])
+ if (is_end_of_line[(unsigned char) *input_line_pointer])
c = *input_line_pointer;
}
}
{
SKIP_WHITESPACE ();
len = 0;
- while (!is_end_of_line[(int) *input_line_pointer]
+ while (!is_end_of_line[(unsigned char) *input_line_pointer]
&& !ISSPACE (*input_line_pointer))
{
obstack_1grow (¬es, *input_line_pointer);
void
tic54x_macro_start (void)
{
- ++macro_level;
+ if (++macro_level >= MAX_SUBSYM_HASH)
+ {
+ as_fatal (_("Macro nesting is too deep"));
+ return;
+ }
subsym_hash[macro_level] = hash_new ();
local_label_hash[macro_level] = hash_new ();
}
int expecting_operand = 0;
int i;
- while (numexp < MAX_OPERANDS && !is_end_of_line[(int) *lptr])
+ while (numexp < MAX_OPERANDS && !is_end_of_line[(unsigned char) *lptr])
{
int paren_not_balanced = 0;
char *op_start, *op_end;
while (*lptr && ISSPACE (*lptr++))
;
- if (!is_end_of_line[(int) *lptr])
+ if (!is_end_of_line[(unsigned char) *lptr])
{
as_bad (_("Extra junk on line"));
return -1;
emit_insn (tic54x_insn *insn)
{
int i;
- flagword oldflags = bfd_get_section_flags (stdoutput, now_seg);
+ flagword oldflags = bfd_section_flags (now_seg);
flagword flags = oldflags | SEC_CODE;
- if (! bfd_set_section_flags (stdoutput, now_seg, flags))
+ if (!bfd_set_section_flags (now_seg, flags))
as_warn (_("error setting flags for \"%s\": %s"),
- bfd_section_name (stdoutput, now_seg),
+ bfd_section_name (now_seg),
bfd_errmsg (bfd_get_error ()));
for (i = 0; i < insn->words; i++)
next_line_shows_parallel (char *next_line)
{
/* Look for the second half. */
- while (ISSPACE (*next_line))
+ while (*next_line != 0 && ISSPACE (*next_line))
++next_line;
return (next_line[0] == PARALLEL_SEPARATOR
if (strstr (line, ".macro"))
return line;
- while (!is_end_of_line[(int) *ptr])
+ unsigned char current_char;
+ while (!is_end_of_line[(current_char = * (unsigned char *) ptr)])
{
- int current_char = *ptr;
-
/* Need to update this since LINE may have been modified. */
if (eval_line)
eval_end = strrchr (ptr, ',');
len = get_absolute_expression ();
if (beg + len > strlen (value))
{
- as_bad (_("Invalid length (use 0 to %d"),
+ as_bad (_("Invalid length (use 0 to %d)"),
(int) strlen (value) - beg);
break;
}
char *replacement = NULL;
/* Work with a copy of the input line, including EOL char. */
- endp = input_line_pointer;
- while (!is_end_of_line[(int) *endp++])
- ;
+ for (endp = input_line_pointer; *endp != 0; )
+ if (is_end_of_line[(unsigned char) *endp++])
+ break;
+
line = xmemdup0 (input_line_pointer, endp - input_line_pointer);
/* Scan ahead for parallel insns. */
{
if (words > delay_slots)
{
- as_bad (_("Instruction does not fit in available delay "
- "slots (%d-word insn, %d slots left)"),
+ as_bad (ngettext ("Instruction does not fit in available "
+ "delay slots (%d-word insn, %d slot left)",
+ "Instruction does not fit in available "
+ "delay slots (%d-word insn, %d slots left)",
+ delay_slots),
words, delay_slots);
delay_slots = 0;
return;
{
if (words > delay_slots)
{
- as_warn (_("Instruction does not fit in available delay "
- "slots (%d-word insn, %d slots left). "
- "Resulting behavior is undefined."),
+ as_warn (ngettext ("Instruction does not fit in available "
+ "delay slots (%d-word insn, %d slot left). "
+ "Resulting behavior is undefined.",
+ "Instruction does not fit in available "
+ "delay slots (%d-word insn, %d slots left). "
+ "Resulting behavior is undefined.",
+ delay_slots),
words, delay_slots);
delay_slots = 0;
return;
Don't allow labels to start with '.' */
int
-tic54x_start_label (int nul_char, int next_char)
+tic54x_start_label (char * label_start, int nul_char, int next_char)
{
char *rest;
/* Disallow labels starting with "." */
if (next_char != ':')
{
- char *label = input_line_pointer;
-
- while (!is_end_of_line[(int) label[-1]])
- --label;
- if (*label == '.')
+ if (*label_start == '.')
{
- as_bad (_("Invalid label '%s'"), label);
+ as_bad (_("Invalid label '%s'"), label_start);
return 0;
}
}
- if (is_end_of_line[(int) next_char])
+ if (is_end_of_line[(unsigned char) next_char])
return 1;
rest = input_line_pointer;