aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-riscv.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-riscv.c')
-rw-r--r--gas/config/tc-riscv.c104
1 files changed, 55 insertions, 49 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index ca4030d..d0030de 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -93,6 +93,7 @@ enum riscv_csr_class
CSR_CLASS_SSAIA_AND_H_32, /* Ssaia with H, rv32 only */
CSR_CLASS_SSAIA_OR_SSCSRIND, /* Ssaia/Smcsrind */
CSR_CLASS_SSAIA_OR_SSCSRIND_AND_H, /* Ssaia/Smcsrind with H */
+ CSR_CLASS_SSCCFG, /* Ssccfg */
CSR_CLASS_SSCSRIND, /* Sscsrind */
CSR_CLASS_SSCSRIND_AND_H, /* Sscsrind with H */
CSR_CLASS_SSSTATEEN, /* S[ms]stateen only */
@@ -932,7 +933,7 @@ opcode_name_lookup (char **s)
save_c = *e;
*e = '\0';
- o = (struct opcode_name_t *) str_hash_find (opcode_names_hash, *s);
+ o = str_hash_find (opcode_names_hash, *s);
/* Advance to next token if one was recognized. */
if (o)
@@ -960,15 +961,15 @@ static htab_t reg_names_hash = NULL;
static htab_t csr_extra_hash = NULL;
#define ENCODE_REG_HASH(cls, n) \
- ((void *)(uintptr_t)((n) * RCLASS_MAX + (cls) + 1))
-#define DECODE_REG_CLASS(hash) (((uintptr_t)(hash) - 1) % RCLASS_MAX)
-#define DECODE_REG_NUM(hash) (((uintptr_t)(hash) - 1) / RCLASS_MAX)
+ ((n) * RCLASS_MAX + (cls) + 1)
+#define DECODE_REG_CLASS(hash) (((hash) - 1) % RCLASS_MAX)
+#define DECODE_REG_NUM(hash) (((hash) - 1) / RCLASS_MAX)
static void
hash_reg_name (enum reg_class class, const char *name, unsigned n)
{
- void *hash = ENCODE_REG_HASH (class, n);
- if (str_hash_insert (reg_names_hash, name, hash, 0) != NULL)
+ uintptr_t hash = ENCODE_REG_HASH (class, n);
+ if (str_hash_insert_int (reg_names_hash, name, hash, 0) != NULL)
as_fatal (_("internal: duplicate %s"), name);
}
@@ -994,7 +995,7 @@ riscv_init_csr_hash (const char *name,
bool need_enrty = true;
pre_entry = NULL;
- entry = (struct riscv_csr_extra *) str_hash_find (csr_extra_hash, name);
+ entry = str_hash_find (csr_extra_hash, name);
while (need_enrty && entry != NULL)
{
if (entry->csr_class == class
@@ -1118,6 +1119,9 @@ riscv_csr_address (const char *csr_name,
is_h_required = (csr_class == CSR_CLASS_SSAIA_OR_SSCSRIND_AND_H);
extension = "ssaia or sscsrind";
break;
+ case CSR_CLASS_SSCCFG:
+ extension = "ssccfg";
+ break;
case CSR_CLASS_SSCSRIND:
case CSR_CLASS_SSCSRIND_AND_H:
is_h_required = (csr_class == CSR_CLASS_SSCSRIND_AND_H);
@@ -1206,8 +1210,7 @@ riscv_csr_address (const char *csr_name,
static unsigned int
reg_csr_lookup_internal (const char *s)
{
- struct riscv_csr_extra *r =
- (struct riscv_csr_extra *) str_hash_find (csr_extra_hash, s);
+ struct riscv_csr_extra *r = str_hash_find (csr_extra_hash, s);
if (r == NULL)
return -1U;
@@ -1218,13 +1221,13 @@ reg_csr_lookup_internal (const char *s)
static unsigned int
reg_lookup_internal (const char *s, enum reg_class class)
{
- void *r;
+ uintptr_t r;
if (class == RCLASS_CSR)
return reg_csr_lookup_internal (s);
- r = str_hash_find (reg_names_hash, s);
- if (r == NULL || DECODE_REG_CLASS (r) != class)
+ r = str_hash_find_int (reg_names_hash, s);
+ if (r == (uintptr_t) -1 || DECODE_REG_CLASS (r) != class)
return -1;
if (riscv_subset_supports (&riscv_rps_as, "e")
@@ -2044,7 +2047,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
va_start (args, fmt);
r = BFD_RELOC_UNUSED;
- mo = (struct riscv_opcode *) str_hash_find (op_hash, name);
+ mo = str_hash_find (op_hash, name);
gas_assert (mo);
/* Find a non-RVC variant of the instruction. append_insn will compress
@@ -2860,7 +2863,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
break;
}
- insn = (struct riscv_opcode *) str_hash_find (hash, str);
+ insn = str_hash_find (hash, str);
probing_insn_operands = true;
@@ -4848,7 +4851,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
bfd_vma delta = target - md_pcrel_from (fixP);
bfd_putl32 (bfd_getl32 (buf) | ENCODE_JTYPE_IMM (delta), buf);
if (!riscv_opts.relax && S_IS_LOCAL (fixP->fx_addsy))
- fixP->fx_done = 1;
+ {
+ if (!VALID_JTYPE_IMM (delta))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid J-type offset (%+lld)"),
+ (long long) delta);
+ fixP->fx_done = 1;
+ }
}
break;
@@ -4860,7 +4869,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
bfd_vma delta = target - md_pcrel_from (fixP);
bfd_putl32 (bfd_getl32 (buf) | ENCODE_BTYPE_IMM (delta), buf);
if (!riscv_opts.relax && S_IS_LOCAL (fixP->fx_addsy))
- fixP->fx_done = 1;
+ {
+ if (!VALID_BTYPE_IMM (delta))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid B-type offset (%+lld)"),
+ (long long) delta);
+ fixP->fx_done = 1;
+ }
}
break;
@@ -4872,7 +4887,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
bfd_vma delta = target - md_pcrel_from (fixP);
bfd_putl16 (bfd_getl16 (buf) | ENCODE_CBTYPE_IMM (delta), buf);
if (!riscv_opts.relax && S_IS_LOCAL (fixP->fx_addsy))
- fixP->fx_done = 1;
+ {
+ if (!VALID_CBTYPE_IMM (delta))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid CB-type offset (%+lld)"),
+ (long long) delta);
+ fixP->fx_done = 1;
+ }
}
break;
@@ -4884,7 +4905,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
bfd_vma delta = target - md_pcrel_from (fixP);
bfd_putl16 (bfd_getl16 (buf) | ENCODE_CJTYPE_IMM (delta), buf);
if (!riscv_opts.relax && S_IS_LOCAL (fixP->fx_addsy))
- fixP->fx_done = 1;
+ {
+ if (!VALID_CJTYPE_IMM (delta))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid CJ-type offset (%+lld)"),
+ (long long) delta);
+ fixP->fx_done = 1;
+ }
}
break;
@@ -4919,7 +4946,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
| ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)),
buf);
if (!riscv_opts.relax)
- fixP->fx_done = 1;
+ {
+ if (xlen > 32
+ && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid pcrel_hi offset (%+lld)"),
+ (long long) value);
+ fixP->fx_done = 1;
+ }
}
relaxable = true;
break;
@@ -4945,7 +4979,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
bfd_putl32 (bfd_getl32 (buf) | ENCODE_STYPE_IMM (value), buf);
else
bfd_putl32 (bfd_getl32 (buf) | ENCODE_ITYPE_IMM (value), buf);
- /* Relaxations should never be enabled by `.option relax'. */
+ /* Relaxations should never be enabled by `.option relax'.
+ The offset is checked by corresponding %pcrel_hi entry. */
if (!riscv_opts.relax)
fixP->fx_done = 1;
}
@@ -5853,35 +5888,6 @@ s_variant_cc (int ignored ATTRIBUTE_UNUSED)
elfsym->internal_elf_sym.st_other |= STO_RISCV_VARIANT_CC;
}
-/* Same as elf_copy_symbol_attributes, but without copying st_other.
- This is needed so RISC-V specific st_other values can be independently
- specified for an IFUNC resolver (that is called by the dynamic linker)
- and the symbol it resolves (aliased to the resolver). In particular,
- if a function symbol has special st_other value set via directives,
- then attaching an IFUNC resolver to that symbol should not override
- the st_other setting. Requiring the directive on the IFUNC resolver
- symbol would be unexpected and problematic in C code, where the two
- symbols appear as two independent function declarations. */
-
-void
-riscv_elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
-{
- struct elf_obj_sy *srcelf = symbol_get_obj (src);
- struct elf_obj_sy *destelf = symbol_get_obj (dest);
- /* If size is unset, copy size from src. Because we don't track whether
- .size has been used, we can't differentiate .size dest, 0 from the case
- where dest's size is unset. */
- if (!destelf->size && S_GET_SIZE (dest) == 0)
- {
- if (srcelf->size)
- {
- destelf->size = XNEW (expressionS);
- *destelf->size = *srcelf->size;
- }
- S_SET_SIZE (dest, S_GET_SIZE (src));
- }
-}
-
/* RISC-V pseudo-ops table. */
static const pseudo_typeS riscv_pseudo_table[] =
{