/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 Free Software Foundation, Inc.
Contributed by Carnegie Mellon University, 1993.
Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
Modified by Ken Raeburn for gas-2.x and ECOFF support.
#include "as.h"
#include "subsegs.h"
-#include "struc-symbol.h"
#include "ecoff.h"
#include "opcode/alpha.h"
static const char *alpha_target_name = "<all>";
/* The hash table of instruction opcodes. */
-static struct hash_control *alpha_opcode_hash;
+static htab_t alpha_opcode_hash;
/* The hash table of macro opcodes. */
-static struct hash_control *alpha_macro_hash;
+static htab_t alpha_macro_hash;
#ifdef OBJ_ECOFF
/* The $gp relocation symbol. */
};
/* Hash table to link up literals with the appropriate lituse. */
-static struct hash_control *alpha_literal_hash;
+static htab_t alpha_literal_hash;
/* Sequence numbers for internal use by macros. */
static long next_sequence_num = -1;
sprintf (buffer, "!%ld", sequence);
- info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer);
+ info = (struct alpha_reloc_tag *) str_hash_find (alpha_literal_hash, buffer);
if (! info)
{
size_t len = strlen (buffer);
- const char *errmsg;
- info = (struct alpha_reloc_tag *)
- xcalloc (sizeof (struct alpha_reloc_tag) + len, 1);
+ info = notes_calloc (sizeof (struct alpha_reloc_tag) + len, 1);
info->segment = now_seg;
info->sequence = sequence;
strcpy (info->string, buffer);
- errmsg = hash_insert (alpha_literal_hash, info->string, (void *) info);
- if (errmsg)
- as_fatal ("%s", errmsg);
+ str_hash_insert (alpha_literal_hash, info->string, info, 0);
#ifdef OBJ_EVAX
info->sym = 0;
info->psym = 0;
present. Not implemented.
Also suppress the optimization if the !literals/!lituses are spread
- in different segments. This can happen with "intersting" uses of
+ in different segments. This can happen with "interesting" uses of
inline assembly; examples are present in the Linux kernel semaphores. */
for (fixp = seginfo->fix_root; fixp; fixp = next)
}
}
-fini:
+ fini:
if (saw_comma)
goto err;
input_line_pointer = old_input_line_pointer;
return ntok - (end_tok - tok);
-err:
+ err:
#ifdef RELOC_OP_P
is_end_of_line[(unsigned char) '!'] = 0;
#endif
return TOKENIZE_ERROR;
#ifdef RELOC_OP_P
-err_report:
+ err_report:
is_end_of_line[(unsigned char) '!'] = 0;
#endif
input_line_pointer = old_input_line_pointer;
const struct alpha_opcode *opcode;
/* Search opcodes. */
- opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ opcode = (const struct alpha_opcode *) str_hash_find (alpha_opcode_hash,
+ opname);
if (opcode)
{
int cpumatch;
*secp = new_sec = subseg_new (name, 0);
subseg_set (current_section, current_subsec);
- bfd_set_section_alignment (stdoutput, new_sec, 4);
- bfd_set_section_flags (stdoutput, new_sec,
- SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
- | SEC_DATA);
+ bfd_set_section_alignment (new_sec, 4);
+ bfd_set_section_flags (new_sec, (SEC_RELOC | SEC_ALLOC | SEC_LOAD
+ | SEC_READONLY | SEC_DATA));
S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec));
}
const char *file,
unsigned line)
{
- if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW))
+ if (!(operand->flags & AXP_OPERAND_NOOVERFLOW))
{
offsetT min, max;
#endif
if (local_macros_on)
{
- macro = ((const struct alpha_macro *)
- hash_find (alpha_macro_hash, opname));
+ macro = (const struct alpha_macro *) str_hash_find (alpha_macro_hash,
+ opname);
if (macro)
{
found_something = 1;
}
/* Search opcodes. */
- opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ opcode = (const struct alpha_opcode *) str_hash_find (alpha_opcode_hash,
+ opname);
if (opcode)
{
found_something = 1;
#ifdef OBJ_EVAX
/* Add sym+addend to link pool.
- Return offset from curent procedure value (pv) to entry in link pool.
+ Return offset from current procedure value (pv) to entry in link pool.
Add new fixup only if offset isn't 16bit. */
&& fixp->fx_offset == (valueT)addend
&& fixp->tc_fix_data.info
&& fixp->tc_fix_data.info->sym
- && fixp->tc_fix_data.info->sym->sy_value.X_op_symbol == basesym)
+ && symbol_symbolS (fixp->tc_fix_data.info->sym)
+ && (symbol_get_value_expression (fixp->tc_fix_data.info->sym)
+ ->X_op_symbol == basesym))
return fixp->tc_fix_data.info->sym;
}
/* Not found, add a new entry. */
subseg_set (alpha_link_section, 0);
- linksym = symbol_new
- (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), frag_now);
+ linksym = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now, frag_now_fix ());
p = frag_more (8);
memset (p, 0, 8);
}
#ifndef OBJ_EVAX
- know (symbolP->sy_frag == &zero_address_frag);
+ know (symbol_get_frag (symbolP) == &zero_address_frag);
#endif
demand_empty_rest_of_line ();
}
arg = get_absolute_expression ();
demand_empty_rest_of_line ();
- alpha_prologue_label = symbol_new
- (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), frag_now);
+ alpha_prologue_label = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now,
+ frag_now_fix ());
if (ECOFF_DEBUGGING)
sym = ecoff_get_cur_proc_sym ();
if (alpha_flag_mdebug < 0)
{
segT sec = subseg_new (".mdebug", 0);
- bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY);
- bfd_set_section_alignment (stdoutput, sec, 3);
+ bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY);
+ bfd_set_section_alignment (sec, 3);
ecoff_read_begin_hook ();
unless the compiler has done it for us. */
void
-alpha_elf_md_end (void)
+alpha_elf_md_finish (void)
{
struct alpha_elf_frame_data *p;
/* Create a temporary symbol at the same location as our
function symbol. This prevents problems with globals. */
cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym),
- S_GET_VALUE (p->func_sym),
- symbol_get_frag (p->func_sym)));
+ symbol_get_frag (p->func_sym),
+ S_GET_VALUE (p->func_sym)));
cfi_set_sections ();
cfi_set_return_column (p->ra_regno);
int no = 0;
flagword flag = 0;
- if (len == 5 && strncmp (str, "NO", 2) == 0)
+ if (len == 5 && startswith (str, "NO"))
{
no = 1;
str += 2;
if (len == 3)
{
- if (strncmp (str, "PIC", 3) == 0)
+ if (startswith (str, "PIC"))
flag = EGPS__V_PIC;
- else if (strncmp (str, "LIB", 3) == 0)
+ else if (startswith (str, "LIB"))
flag = EGPS__V_LIB;
- else if (strncmp (str, "OVR", 3) == 0)
+ else if (startswith (str, "OVR"))
flag = EGPS__V_OVR;
- else if (strncmp (str, "REL", 3) == 0)
+ else if (startswith (str, "REL"))
flag = EGPS__V_REL;
- else if (strncmp (str, "GBL", 3) == 0)
+ else if (startswith (str, "GBL"))
flag = EGPS__V_GBL;
- else if (strncmp (str, "SHR", 3) == 0)
+ else if (startswith (str, "SHR"))
flag = EGPS__V_SHR;
- else if (strncmp (str, "EXE", 3) == 0)
+ else if (startswith (str, "EXE"))
flag = EGPS__V_EXE;
- else if (strncmp (str, "WRT", 3) == 0)
+ else if (startswith (str, "WRT"))
flag = EGPS__V_WRT;
- else if (strncmp (str, "VEC", 3) == 0)
+ else if (startswith (str, "VEC"))
flag = EGPS__V_VEC;
- else if (strncmp (str, "MOD", 3) == 0)
+ else if (startswith (str, "MOD"))
{
flag = no ? EGPS__V_NOMOD : EGPS__V_NOMOD << EGPS__V_NO_SHIFT;
no = 0;
}
- else if (strncmp (str, "COM", 3) == 0)
+ else if (startswith (str, "COM"))
flag = EGPS__V_COM;
}
s_alpha_prologue (int ignore ATTRIBUTE_UNUSED)
{
demand_empty_rest_of_line ();
- alpha_prologue_label = symbol_new
- (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), frag_now);
+ alpha_prologue_label = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now,
+ frag_now_fix ());
}
/* Parse .pdesc <entry_name>,{null|stack|reg}
SKIP_WHITESPACE ();
name_end = get_symbol_name (&name);
- if (strncmp (name, "stack", 5) == 0)
+ if (startswith (name, "stack"))
alpha_evax_proc->pdsckind = PDSC_S_K_KIND_FP_STACK;
- else if (strncmp (name, "reg", 3) == 0)
+ else if (startswith (name, "reg"))
alpha_evax_proc->pdsckind = PDSC_S_K_KIND_FP_REGISTER;
- else if (strncmp (name, "null", 4) == 0)
+ else if (startswith (name, "null"))
alpha_evax_proc->pdsckind = PDSC_S_K_KIND_NULL;
else
BFD_RELOC_ALPHA_LINKAGE);
if (alpha_insn_label == NULL)
- alpha_insn_label = symbol_new
- (FAKE_LABEL_NAME, now_seg, (valueT) frag_now_fix (), frag_now);
+ alpha_insn_label = symbol_new (FAKE_LABEL_NAME, now_seg, frag_now,
+ frag_now_fix ());
/* Create a linkage element. */
linkage_fixup = XNEW (struct alpha_linkage_fixups);
}
/* Handle floating point allocation pseudo-ops. This is like the
- generic vresion, but it makes sure the current label, if any, is
+ generic version, but it makes sure the current label, if any, is
correctly aligned. */
static void
}
as_warn (_("Unknown CPU identifier `%s'"), name);
-found:
+ found:
(void) restore_line_pointer (ch);
demand_empty_rest_of_line ();
}
if (!sec)
return;
- vma = bfd_get_section_vma (sec->owner, sec);
+ vma = bfd_section_vma (sec);
if (vma && vma < alpha_gp_value)
alpha_gp_value = vma;
}
}
/* Create the opcode hash table. */
- alpha_opcode_hash = hash_new ();
+ alpha_opcode_hash = str_htab_create ();
for (i = 0; i < alpha_num_opcodes;)
{
- const char *name, *retval, *slash;
+ const char *name, *slash;
name = alpha_opcodes[i].name;
- retval = hash_insert (alpha_opcode_hash, name, (void *) &alpha_opcodes[i]);
- if (retval)
- as_fatal (_("internal error: can't hash opcode `%s': %s"),
- name, retval);
+ if (str_hash_insert (alpha_opcode_hash, name, &alpha_opcodes[i], 0))
+ as_fatal (_("duplicate %s"), name);
/* Some opcodes include modifiers of various sorts with a "/mod"
syntax, like the architecture manual suggests. However, for
if ((slash = strchr (name, '/')) != NULL)
{
- char *p = XNEWVEC (char, strlen (name));
+ size_t len = strlen (name);
+ char *p = notes_alloc (len);
+ size_t len1 = slash - name;
- memcpy (p, name, slash - name);
- strcpy (p + (slash - name), slash + 1);
+ memcpy (p, name, len1);
+ memcpy (p + len1, slash + 1, len - len1);
- (void) hash_insert (alpha_opcode_hash, p, (void *) &alpha_opcodes[i]);
+ (void) str_hash_insert (alpha_opcode_hash, p, &alpha_opcodes[i], 0);
/* Ignore failures -- the opcode table does duplicate some
variants in different forms, like "hw_stq" and "hw_st/q". */
}
}
/* Create the macro hash table. */
- alpha_macro_hash = hash_new ();
+ alpha_macro_hash = str_htab_create ();
for (i = 0; i < alpha_num_macros;)
{
- const char *name, *retval;
+ const char *name;
name = alpha_macros[i].name;
- retval = hash_insert (alpha_macro_hash, name, (void *) &alpha_macros[i]);
- if (retval)
- as_fatal (_("internal error: can't hash macro `%s': %s"),
- name, retval);
+ if (str_hash_insert (alpha_macro_hash, name, &alpha_macros[i], 0))
+ as_fatal (_("duplicate %s"), name);
while (++i < alpha_num_macros
&& (alpha_macros[i].name == name
char name[4];
sprintf (name, "$%d", i);
- alpha_register_table[i] = symbol_create (name, reg_section, i,
- &zero_address_frag);
+ alpha_register_table[i] = symbol_create (name, reg_section,
+ &zero_address_frag, i);
}
for (; i < 64; ++i)
char name[5];
sprintf (name, "$f%d", i - 32);
- alpha_register_table[i] = symbol_create (name, reg_section, i,
- &zero_address_frag);
+ alpha_register_table[i] = symbol_create (name, reg_section,
+ &zero_address_frag, i);
}
/* Create the special symbols and sections we'll be using. */
/* For handling the GP, create a symbol that won't be output in the
symbol table. We'll edit it out of relocs later. */
- alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section, 0x8000,
- &zero_address_frag);
+ alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section,
+ &zero_address_frag, 0x8000);
#endif
#ifdef OBJ_EVAX
if (ECOFF_DEBUGGING)
{
segT sec = subseg_new (".mdebug", (subsegT) 0);
- bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY);
- bfd_set_section_alignment (stdoutput, sec, 3);
+ bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY);
+ bfd_set_section_alignment (sec, 3);
}
#endif
/* Create literal lookup hash table. */
- alpha_literal_hash = hash_new ();
+ alpha_literal_hash = str_htab_create ();
subseg_set (text_section, 0);
}
valueT
md_section_align (segT seg, valueT size)
{
- int align = bfd_get_section_alignment (stdoutput, seg);
+ int align = bfd_section_alignment (seg);
valueT mask = ((valueT) 1 << align) - 1;
return (size + mask) & ~mask;
return vax_md_atof (type, litP, sizeP);
default:
- return ieee_md_atof (type, litP, sizeP, FALSE);
+ return ieee_md_atof (type, litP, sizeP, false);
}
}
md_number_to_chars (fixpos, value, 2);
break;
+ case BFD_RELOC_8:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_8_PCREL;
+ size = 1;
+ goto do_reloc_xx;
+
case BFD_RELOC_16:
if (fixP->fx_pcrel)
fixP->fx_r_type = BFD_RELOC_16_PCREL;
return;
}
- if ((abs (value) >> 2) & ~0xfffff)
+ if (value + (1u << 22) >= (1u << 23))
goto done;
else
{
return;
}
- if ((abs (value)) & ~0x7fff)
+ if (value + (1u << 15) >= (1u << 16))
goto done;
else
{
return;
}
- if ((abs (value) >> 2) & ~0xfffff)
+ if (value + (1u << 22) >= (1u << 23))
{
/* Out of range. */
if (fixP->fx_r_type == BFD_RELOC_ALPHA_BOH)
goto done;
}
-write_done:
+ write_done:
md_number_to_chars (fixpos, image, 4);
-done:
+ done:
fixP->fx_done = 1;
}
}
as_warn (_("frame reg expected, using $%d."), framereg);
-found:
+ found:
note_gpreg (framereg);
return framereg;
}