my_getExpression (expressionS *ep, const char *str)
{
char *save_in, *ret;
+
if (*str == ':')
{
unsigned long j;
char *str_1 = (char *) str;
- str_1++;
j = strtol (str_1, &str_1, 10);
get_internal_label (ep, j, *str_1 == 'f');
return NULL;
reloc (const char *op_c_str, const char *id_c_str, offsetT addend)
{
expressionS id_sym_expr;
+ bfd_reloc_code_real_type btype;
if (end <= top)
as_fatal (_("expr too huge"));
- if (id_c_str)
- {
- my_getExpression (&id_sym_expr, id_c_str);
- id_sym_expr.X_add_number += addend;
- }
+ /* For compatible old asm code. */
+ if (0 == strcmp (op_c_str, "plt"))
+ btype = BFD_RELOC_LARCH_B26;
else
- {
- id_sym_expr.X_op = O_constant;
- id_sym_expr.X_add_number = addend;
- }
+ btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str);
- if (strcmp (op_c_str, "abs") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE;
- top++;
- }
- else if (strcmp (op_c_str, "pcrel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL;
- top++;
- }
- else if (strcmp (op_c_str, "gprel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL;
- top++;
- }
- else if (strcmp (op_c_str, "tprel") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL;
- top++;
- }
- else if (strcmp (op_c_str, "tlsgot") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT;
- top++;
- }
- else if (strcmp (op_c_str, "tlsgd") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GD;
- top++;
- }
- else if (strcmp (op_c_str, "plt") == 0)
- {
- top->value = id_sym_expr;
- top->type = BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL;
- top++;
- }
+ if (id_c_str)
+ {
+ my_getExpression (&id_sym_expr, id_c_str);
+ id_sym_expr.X_add_number += addend;
+ }
else
- as_fatal (_("unknown reloc hint: %s"), op_c_str);
+ {
+ id_sym_expr.X_op = O_constant;
+ id_sym_expr.X_add_number = addend;
+ }
+
+ top->value = id_sym_expr;
+ top->type = btype;
+ top++;
}
static void
static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
-static const char *
-my_getExpression (expressionS *ep, const char *str)
-{
- char *save_in, *ret;
- save_in = input_line_pointer;
- input_line_pointer = (char *) str;
- expression (ep);
- ret = input_line_pointer;
- input_line_pointer = save_in;
- return ret;
-}
-
static void
s_loongarch_align (int arg)
{
label_expr->X_add_number = 0;
}
-extern int loongarch_parse_expr (const char *expr,
- struct reloc_info *reloc_stack_top,
- size_t max_reloc_num, size_t *reloc_num,
- offsetT *imm_if_no_reloc);
-
static int
is_internal_label (const char *c_str)
{
as_fatal (
_("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
esc_ch1, esc_ch2, bit_field, arg);
+ if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
+ && ip->reloc_info[0].type < BFD_RELOC_LARCH_RELAX)
+ {
+ /* As we compact stack-relocs, it is no need for pop operation.
+ But break out until here in order to check the imm field.
+ May be reloc_num > 1 if implement relax? */
+ ip->reloc_num += reloc_num;
+ break;
+ }
reloc_num++;
ip->reloc_num += reloc_num;
ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
{
ase->name_hash_entry = str_htab_create ();
for (it = ase->opcodes; it->name; it++)
- str_hash_insert (ase->name_hash_entry, it->name, (void *) it, 0);
+ {
+ if ((!it->include || (it->include && *it->include))
+ && (!it->exclude || (it->exclude && !(*it->exclude))))
+ str_hash_insert (ase->name_hash_entry, it->name,
+ (void *) it, 0);
+ }
}
if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
check_this_insn_before_appending (struct loongarch_cl_insn *ip)
{
int ret = 0;
- if (strcmp (ip->name, "la.abs") == 0)
+
+ if (strncmp (ip->name, "la.abs", 6) == 0)
{
ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
- my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]);
+ ip->reloc_info[ip->reloc_num].value = const_0;
ip->reloc_num++;
}
else if (ip->insn->mask == 0xffff8000
ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
sizeof (args_buf));
}
+
return ret;
}
static int64_t stack_top;
static int last_reloc_is_sop_push_pcrel_1 = 0;
int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
+ segT sub_segment;
last_reloc_is_sop_push_pcrel_1 = 0;
char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
- case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
- case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL:
+ case BFD_RELOC_LARCH_TLS_LE_HI20:
+ case BFD_RELOC_LARCH_TLS_LE_LO12:
+ case BFD_RELOC_LARCH_TLS_LE64_LO20:
+ case BFD_RELOC_LARCH_TLS_LE64_HI12:
+ case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
+ case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
+ case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
+ case BFD_RELOC_LARCH_TLS_IE_HI20:
+ case BFD_RELOC_LARCH_TLS_IE_LO12:
+ case BFD_RELOC_LARCH_TLS_IE64_LO20:
+ case BFD_RELOC_LARCH_TLS_IE64_HI12:
+ case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_LD_HI20:
+ case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
+ case BFD_RELOC_LARCH_TLS_GD_HI20:
+ /* Add tls lo (got_lo reloc type). */
if (fixP->fx_addsy == NULL)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Relocation against a constant"));
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
- if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
- || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
- || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT)
- S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
+ if (fixP->fx_addsy == NULL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Relocation against a constant"));
- if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL)
- {
- last_reloc_is_sop_push_pcrel_1 = 1;
- if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
- stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
- - (fixP->fx_where + fixP->fx_frag->fr_address));
- else
- stack_top = 0;
- }
+ last_reloc_is_sop_push_pcrel_1 = 1;
+ if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
+ stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+ - (fixP->fx_where + fixP->fx_frag->fr_address));
+ else
+ stack_top = 0;
break;
case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
case BFD_RELOC_64:
case BFD_RELOC_32:
+ case BFD_RELOC_24:
+ case BFD_RELOC_16:
+ case BFD_RELOC_8:
+
+ if (fixP->fx_r_type == BFD_RELOC_32
+ && fixP->fx_addsy && fixP->fx_subsy
+ && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
+ && strcmp (sub_segment->name, ".eh_frame") == 0
+ && S_GET_VALUE (fixP->fx_subsy)
+ == fixP->fx_frag->fr_address + fixP->fx_where)
+ {
+ fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
+ fixP->fx_subsy = NULL;
+ break;
+ }
+
if (fixP->fx_subsy)
{
- case BFD_RELOC_24:
- case BFD_RELOC_16:
- case BFD_RELOC_8:
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
fixP->fx_next->fx_addsy = fixP->fx_subsy;
fixP->fx_next->fx_subsy = NULL;
}
break;
+ case BFD_RELOC_LARCH_B16:
+ case BFD_RELOC_LARCH_B21:
+ case BFD_RELOC_LARCH_B26:
+ if (fixP->fx_addsy == NULL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _ ("Relocation against a constant."));
+ }
+ if (S_GET_SEGMENT (fixP->fx_addsy) == seg
+ && !S_FORCE_RELOC (fixP->fx_addsy, 1))
+ {
+ int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
+ int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
+ fix_reloc_insn (fixP, sym_addend - pc, buf);
+ fixP->fx_done = 1;
+ }
+
+ break;
+
default:
break;
}
return 0;
}
+int
+loongarch_fix_adjustable (fixS *fix)
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fix->fx_addsy)
+ || S_IS_WEAK (fix->fx_addsy)
+ || S_FORCE_RELOC (fix->fx_addsy, true))
+ return 0;
+
+ return 1;
+}
+
/* Translate internal representation of relocation info to BFD target
format. */
arelent *
cfi_add_CFA_def_cfa_register (3 /* $sp */);
}
-int
-loongarch_dwarf2_addr_size (void)
-{
- return LARCH_opts.ase_lp64 ? 8 : 4;
-}
-
void
tc_loongarch_parse_to_dw2regnum (expressionS *exp)
{