/* Altera Nios II assembler.
- Copyright (C) 2012-2019 Free Software Foundation, Inc.
+ Copyright (C) 2012-2023 Free Software Foundation, Inc.
Contributed by Nigel Gray (ngray@altera.com).
Contributed by Mentor Graphics, Inc.
and macro expansions generate a warning.
.set at -> noat = 0, assembly code using at warn but macro expansions
do not generate warnings. */
- bfd_boolean noat;
+ bool noat;
/* .set nobreak -> nobreak = 1 allows assembly code to use ba,bt without
warning.
.set break -> nobreak = 0, assembly code using ba,bt warns. */
- bfd_boolean nobreak;
+ bool nobreak;
/* .cmd line option -relax-all allows all branches and calls to be replaced
with longer versions.
a section. */
relax_optionT relax;
-} nios2_as_options = {FALSE, FALSE, relax_section};
+} nios2_as_options = {false, false, relax_section};
typedef struct nios2_insn_reloc
} nios2_ps_insn_infoS;
/* Opcode hash table. */
-static struct hash_control *nios2_opcode_hash = NULL;
+static htab_t nios2_opcode_hash = NULL;
#define nios2_opcode_lookup(NAME) \
- ((struct nios2_opcode *) hash_find (nios2_opcode_hash, (NAME)))
+ ((struct nios2_opcode *) str_hash_find (nios2_opcode_hash, (NAME)))
/* Register hash table. */
-static struct hash_control *nios2_reg_hash = NULL;
+static htab_t nios2_reg_hash = NULL;
#define nios2_reg_lookup(NAME) \
- ((struct nios2_reg *) hash_find (nios2_reg_hash, (NAME)))
+ ((struct nios2_reg *) str_hash_find (nios2_reg_hash, (NAME)))
/* Pseudo-op hash table. */
-static struct hash_control *nios2_ps_hash = NULL;
+static htab_t nios2_ps_hash = NULL;
#define nios2_ps_lookup(NAME) \
- ((nios2_ps_insn_infoS *) hash_find (nios2_ps_hash, (NAME)))
+ ((nios2_ps_insn_infoS *) str_hash_find (nios2_ps_hash, (NAME)))
/* The known current alignment of the current section. */
static int nios2_current_align;
val = 0;
if (target_big_endian)
for (i = 0; i < n; ++i)
- val = val | ((buf[i] & 0xff) << 8 * (n - (i + 1)));
+ val = val | ((valueT) (buf[i] & 0xff) << 8 * (n - (i + 1)));
else
for (i = 0; i < n; ++i)
- val = val | ((buf[i] & 0xff) << 8 * i);
+ val = val | ((valueT) (buf[i] & 0xff) << 8 * i);
return val;
}
return NULL;
}
-/* Return true if STR starts with PREFIX, which should be a string literal. */
-#define strprefix(STR, PREFIX) \
- (strncmp ((STR), PREFIX, strlen (PREFIX)) == 0)
-
-
/* Return true if STR is prefixed with a special relocation operator. */
static int
nios2_special_relocation_p (const char *str)
{
- return (strprefix (str, "%lo")
- || strprefix (str, "%hi")
- || strprefix (str, "%hiadj")
- || strprefix (str, "%gprel")
- || strprefix (str, "%got")
- || strprefix (str, "%call")
- || strprefix (str, "%gotoff_lo")
- || strprefix (str, "%gotoff_hiadj")
- || strprefix (str, "%tls_gd")
- || strprefix (str, "%tls_ldm")
- || strprefix (str, "%tls_ldo")
- || strprefix (str, "%tls_ie")
- || strprefix (str, "%tls_le")
- || strprefix (str, "%gotoff"));
+ return (startswith (str, "%lo")
+ || startswith (str, "%hi")
+ || startswith (str, "%hiadj")
+ || startswith (str, "%gprel")
+ || startswith (str, "%got")
+ || startswith (str, "%call")
+ || startswith (str, "%gotoff_lo")
+ || startswith (str, "%gotoff_hiadj")
+ || startswith (str, "%tls_gd")
+ || startswith (str, "%tls_ldm")
+ || startswith (str, "%tls_ldo")
+ || startswith (str, "%tls_ie")
+ || startswith (str, "%tls_le")
+ || startswith (str, "%gotoff"));
}
if (label != NULL && !switched_seg_p)
{
symbolS *sym;
- int label_seen = FALSE;
+ int label_seen = false;
struct frag *old_frag;
valueT old_value;
valueT new_value;
if (symbol_get_frag (sym) == old_frag
&& S_GET_VALUE (sym) == old_value)
{
- label_seen = TRUE;
+ label_seen = true;
symbol_set_frag (sym, frag_now);
S_SET_VALUE (sym, new_value);
}
SKIP_WHITESPACE ();
if (is_end_of_line[(unsigned char) *input_line_pointer])
{
- bfd_boolean done = TRUE;
+ bool done = true;
*endline = 0;
if (!strcmp (directive, "noat"))
- nios2_as_options.noat = TRUE;
+ nios2_as_options.noat = true;
else if (!strcmp (directive, "at"))
- nios2_as_options.noat = FALSE;
+ nios2_as_options.noat = false;
else if (!strcmp (directive, "nobreak"))
- nios2_as_options.nobreak = TRUE;
+ nios2_as_options.nobreak = true;
else if (!strcmp (directive, "break"))
- nios2_as_options.nobreak = FALSE;
+ nios2_as_options.nobreak = false;
else if (!strcmp (directive, "norelax"))
nios2_as_options.relax = relax_none;
else if (!strcmp (directive, "relaxsection"))
else if (!strcmp (directive, "relaxall"))
nios2_as_options.relax = relax_all;
else
- done = FALSE;
+ done = false;
if (done)
{
fragS *sym_frag = symbol_get_frag (symbolp);
offsetT offset;
int n;
- bfd_boolean is_cdx = FALSE;
+ bool is_cdx = false;
target += S_GET_VALUE (symbolp);
if (IS_CDXBRANCH (subtype) && IS_UBRANCH (subtype)
&& offset >= -1024 && offset < 1024)
/* PC-relative CDX branch with 11-bit offset. */
- is_cdx = TRUE;
+ is_cdx = true;
else if (IS_CDXBRANCH (subtype) && IS_CBRANCH (subtype)
&& offset >= -128 && offset < 128)
/* PC-relative CDX branch with 8-bit offset. */
- is_cdx = TRUE;
+ is_cdx = true;
else if (offset >= -32768 && offset < 32768)
/* Fits in PC-relative branch. */
n = 0;
unsigned int addend_mask, addi_mask, op;
offsetT addend, remainder;
int i;
- bfd_boolean is_r2 = (bfd_get_mach (stdoutput) == bfd_mach_nios2r2);
+ bool is_r2 = (bfd_get_mach (stdoutput) == bfd_mach_nios2r2);
/* If this is a CDX branch we're not relaxing, just generate the fixup. */
if (IS_CDXBRANCH (subtype))
/** Fixups and overflow checking. */
/* Check a fixup for overflow. */
-static bfd_boolean
+static bool
nios2_check_overflow (valueT fixup, reloc_howto_type *howto)
{
/* If there is a rightshift, check that the low-order bits are
{
if ((~(~((valueT) 0) << howto->rightshift) & fixup)
&& howto->complain_on_overflow != complain_overflow_dont)
- return TRUE;
+ return true;
fixup = ((signed)fixup) >> howto->rightshift;
}
case complain_overflow_bitfield:
if ((fixup >> howto->bitsize) != 0
&& ((signed) fixup >> howto->bitsize) != -1)
- return TRUE;
+ return true;
break;
case complain_overflow_signed:
if ((fixup & 0x80000000) > 0)
{
/* Check for negative overflow. */
if ((signed) fixup < (signed) (~0U << (howto->bitsize - 1)))
- return TRUE;
+ return true;
}
else
{
/* Check for positive overflow. */
if (fixup >= ((unsigned) 1 << (howto->bitsize - 1)))
- return TRUE;
+ return true;
}
break;
case complain_overflow_unsigned:
if ((fixup >> howto->bitsize) != 0)
- return TRUE;
+ return true;
break;
default:
as_bad (_("error checking for overflow - broken assembler"));
break;
}
- return FALSE;
+ return false;
}
/* Emit diagnostic for fixup overflow. */
break;
default:
{
- fixup &= ((valueT) 1 << howto->bitsize) - 1;
+ fixup &= ((valueT) 2 << (howto->bitsize - 1)) - 1;
break;
}
}
}
}
- mask |= 1 << regno;
+ mask |= 1UL << regno;
last = regno;
}
*ret = 0;
/* Check for --. */
- if (strncmp (str, "--", 2) == 0)
+ if (startswith (str, "--"))
{
str += 2;
*direction -= 1;
return NULL;
/* Check for ++. */
- if (strncmp (str, "++", 2) == 0)
+ if (startswith (str, "++"))
{
str += 2;
*direction += 1;
{
while (*str == ' ')
str++;
- if (strncmp (str, "writeback", 9) == 0)
+ if (startswith (str, "writeback"))
{
*writeback = 1;
str += 9;
}
- else if (strncmp (str, "ret", 3) == 0)
+ else if (startswith (str, "ret"))
{
*ret = 1;
str += 3;
mask = (reglist & 0x00ffc000) >> 14;
if (reglist & (1 << 28))
mask |= 1 << 10;
- if (reglist & (1 << 31))
+ if (reglist & (1u << 31))
mask |= 1 << 11;
}
insn->insn_code |= SET_IW_F1X4L17_REGMASK (mask);
int i;
p = argstr;
i = 0;
- bfd_boolean terminate = FALSE;
+ bool terminate = false;
/* This rest of this function is it too fragile and it mostly works,
therefore special case this one. */
}
if (*parsestr == '\0' || (p != NULL && *p == '\0'))
- terminate = TRUE;
+ terminate = true;
++i;
}
static void
nios2_free_arg (char **parsed_args, int num ATTRIBUTE_UNUSED, int start)
{
- if (parsed_args[start])
- {
- free (parsed_args[start]);
- parsed_args[start] = NULL;
- }
+ free (parsed_args[start]);
+ parsed_args[start] = NULL;
}
/* This function swaps the pseudo-op for a real op. */
symbolS *symp = reloc->reloc_expression.X_add_symbol;
offsetT offset = reloc->reloc_expression.X_add_number;
char *f;
- bfd_boolean is_cdx = (insn->insn_nios2_opcode->size == 2);
+ bool is_cdx = (insn->insn_nios2_opcode->size == 2);
/* Tag dwarf2 debug info to the address at the start of the insn.
We must do it before frag_var() below closes off the frag. */
symbolS *symp = reloc->reloc_expression.X_add_symbol;
offsetT offset = reloc->reloc_expression.X_add_number;
char *f;
- bfd_boolean is_cdx = (insn->insn_nios2_opcode->size == 2);
+ bool is_cdx = (insn->insn_nios2_opcode->size == 2);
/* Tag dwarf2 debug info to the address at the start of the insn.
We must do it before frag_var() below closes off the frag. */
md_begin (void)
{
int i;
- const char *inserted;
switch (nios2_architecture)
{
/* Create and fill a hashtable for the Nios II opcodes, registers and
arguments. */
- nios2_opcode_hash = hash_new ();
- nios2_reg_hash = hash_new ();
- nios2_ps_hash = hash_new ();
+ nios2_opcode_hash = str_htab_create ();
+ nios2_reg_hash = str_htab_create ();
+ nios2_ps_hash = str_htab_create ();
for (i = 0; i < nios2_num_opcodes; ++i)
- {
- inserted
- = hash_insert (nios2_opcode_hash, nios2_opcodes[i].name,
- (PTR) & nios2_opcodes[i]);
- if (inserted != NULL)
- {
- fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
- nios2_opcodes[i].name, inserted);
- /* Probably a memory allocation problem? Give up now. */
- as_fatal (_("Broken assembler. No assembly attempted."));
- }
- }
+ if (str_hash_insert (nios2_opcode_hash, nios2_opcodes[i].name,
+ &nios2_opcodes[i], 0) != NULL)
+ as_fatal (_("duplicate %s"), nios2_opcodes[i].name);
for (i = 0; i < nios2_num_regs; ++i)
- {
- inserted
- = hash_insert (nios2_reg_hash, nios2_regs[i].name,
- (PTR) & nios2_regs[i]);
- if (inserted != NULL)
- {
- fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
- nios2_regs[i].name, inserted);
- /* Probably a memory allocation problem? Give up now. */
- as_fatal (_("Broken assembler. No assembly attempted."));
- }
-
- }
+ if (str_hash_insert (nios2_reg_hash, nios2_regs[i].name,
+ &nios2_regs[i], 0) != NULL)
+ as_fatal (_("duplicate %s"), nios2_regs[i].name);
for (i = 0; i < nios2_num_ps_insn_info_structs; ++i)
- {
- inserted
- = hash_insert (nios2_ps_hash, nios2_ps_insn_info_structs[i].pseudo_insn,
- (PTR) & nios2_ps_insn_info_structs[i]);
- if (inserted != NULL)
- {
- fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
- nios2_ps_insn_info_structs[i].pseudo_insn, inserted);
- /* Probably a memory allocation problem? Give up now. */
- as_fatal (_("Broken assembler. No assembly attempted."));
- }
- }
+ if (str_hash_insert (nios2_ps_hash,
+ nios2_ps_insn_info_structs[i].pseudo_insn,
+ &nios2_ps_insn_info_structs[i], 0) != NULL)
+ as_fatal (_("duplicate %s"), nios2_ps_insn_info_structs[i].pseudo_insn);
/* Assembler option defaults. */
- nios2_as_options.noat = FALSE;
- nios2_as_options.nobreak = FALSE;
-
- /* Debug information is incompatible with relaxation. */
- if (debug_type != DEBUG_UNSPECIFIED)
- nios2_as_options.relax = relax_none;
+ nios2_as_options.noat = false;
+ nios2_as_options.nobreak = false;
/* Initialize the alignment data. */
nios2_current_align_seg = now_seg;
unsigned long saved_pinfo = 0;
nios2_insn_infoS thisinsn;
nios2_insn_infoS *insn = &thisinsn;
- bfd_boolean ps_error = FALSE;
+ bool ps_error = false;
/* Make sure we are aligned on an appropriate boundary. */
if (nios2_current_align < nios2_min_align)
{
ps_insn = nios2_translate_pseudo_insn (insn);
if (!ps_insn)
- ps_error = TRUE;
+ ps_error = true;
}
/* If we found invalid pseudo-instruction syntax, the error's already
as_bad ("GOT already in the symbol table");
GOT_symbol = symbol_new (name, undefined_section,
- (valueT) 0, &zero_address_frag);
+ &zero_address_frag, 0);
}
return GOT_symbol;
return flags;
}
-/* Implement TC_PARSE_CONS_EXPRESSION to handle %tls_ldo(...) */
+/* Implement TC_PARSE_CONS_EXPRESSION to handle %tls_ldo(...) and
+ %gotoff(...). */
bfd_reloc_code_real_type
nios2_cons (expressionS *exp, int size)
{
- bfd_reloc_code_real_type nios2_tls_ldo_reloc = BFD_RELOC_NONE;
+ bfd_reloc_code_real_type explicit_reloc = BFD_RELOC_NONE;
+ const char *reloc_name = NULL;
SKIP_WHITESPACE ();
if (input_line_pointer[0] == '%')
{
- if (strprefix (input_line_pointer + 1, "tls_ldo"))
+ if (startswith (input_line_pointer + 1, "tls_ldo"))
{
+ reloc_name = "%tls_ldo";
if (size != 4)
as_bad (_("Illegal operands: %%tls_ldo in %d-byte data field"),
size);
else
{
input_line_pointer += 8;
- nios2_tls_ldo_reloc = BFD_RELOC_NIOS2_TLS_DTPREL;
+ explicit_reloc = BFD_RELOC_NIOS2_TLS_DTPREL;
}
}
- if (nios2_tls_ldo_reloc != BFD_RELOC_NONE)
+ else if (startswith (input_line_pointer + 1, "gotoff"))
+ {
+ reloc_name = "%gotoff";
+ if (size != 4)
+ as_bad (_("Illegal operands: %%gotoff in %d-byte data field"),
+ size);
+ else
+ {
+ input_line_pointer += 7;
+ explicit_reloc = BFD_RELOC_NIOS2_GOTOFF;
+ }
+ }
+
+ if (explicit_reloc != BFD_RELOC_NONE)
{
SKIP_WHITESPACE ();
if (input_line_pointer[0] != '(')
- as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+ as_bad (_("Illegal operands: %s requires arguments in ()"),
+ reloc_name);
else
{
int c;
}
if (c != ')')
- as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+ as_bad (_("Illegal operands: %s requires arguments in ()"),
+ reloc_name);
else
{
*end = '\0';
expression (exp);
*end = c;
if (input_line_pointer != end)
- as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+ as_bad (_("Illegal operands: %s requires arguments in ()"),
+ reloc_name);
else
{
input_line_pointer++;
SKIP_WHITESPACE ();
c = *input_line_pointer;
if (! is_end_of_line[c] && c != ',')
- as_bad (_("Illegal operands: garbage after %%tls_ldo()"));
+ as_bad (_("Illegal operands: garbage after %s()"),
+ reloc_name);
}
}
}
}
}
- if (nios2_tls_ldo_reloc == BFD_RELOC_NONE)
+ if (explicit_reloc == BFD_RELOC_NONE)
expression (exp);
- return nios2_tls_ldo_reloc;
+ return explicit_reloc;
}
/* Implement HANDLE_ALIGN. */