aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliuzhensong <liuzhensong@loongson.cn>2022-07-15 16:04:34 +0800
committerliuzhensong <liuzhensong@loongson.cn>2022-07-25 09:59:08 +0800
commitf09482a8747b6fd4c2d59a6a64677d3a3fe1e092 (patch)
treea4a1f1fe565c4add001097ee0e113de28f66c9de
parentcbdbf445356c25521b606e30e5270f74e65011bc (diff)
downloadfsf-binutils-gdb-f09482a8747b6fd4c2d59a6a64677d3a3fe1e092.zip
fsf-binutils-gdb-f09482a8747b6fd4c2d59a6a64677d3a3fe1e092.tar.gz
fsf-binutils-gdb-f09482a8747b6fd4c2d59a6a64677d3a3fe1e092.tar.bz2
LoongArch: gas: Add new reloc types.
Generate new relocate types while use new macro insns. gas/config/ loongarch-lex.h loongarch-parse.y tc-loongarch.c tc-loongarch.h
-rw-r--r--gas/config/loongarch-lex.h3
-rw-r--r--gas/config/loongarch-parse.y72
-rw-r--r--gas/config/tc-loongarch.c140
-rw-r--r--gas/config/tc-loongarch.h7
4 files changed, 120 insertions, 102 deletions
diff --git a/gas/config/loongarch-lex.h b/gas/config/loongarch-lex.h
index 5921244..35d22db 100644
--- a/gas/config/loongarch-lex.h
+++ b/gas/config/loongarch-lex.h
@@ -32,3 +32,6 @@ loongarch_parse_expr (const char *expr,
size_t max_reloc_num,
size_t *reloc_num,
offsetT *imm);
+bfd_reloc_code_real_type
+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *l_r_name);
diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y
index 710f854..902d720 100644
--- a/gas/config/loongarch-parse.y
+++ b/gas/config/loongarch-parse.y
@@ -83,11 +83,11 @@ static const char *
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;
@@ -104,65 +104,31 @@ static void
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
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 08203d2..fbbaca5 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -362,18 +362,6 @@ loongarch_mach (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)
{
@@ -480,11 +468,6 @@ get_internal_label (expressionS *label_expr, unsigned long label,
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)
{
@@ -652,6 +635,15 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
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;
@@ -767,7 +759,12 @@ get_loongarch_opcode (struct loongarch_cl_insn *insn)
{
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)
@@ -800,10 +797,11 @@ static int
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
@@ -980,6 +978,7 @@ assember_macro_helper (const char *const args[], void *context_ptr)
ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
sizeof (args_buf));
}
+
return ret;
}
@@ -1096,6 +1095,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
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;
@@ -1104,26 +1104,40 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
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:
@@ -1143,11 +1157,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
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;
@@ -1190,6 +1217,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
}
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;
}
@@ -1210,6 +1256,18 @@ md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
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 *
@@ -1249,12 +1307,6 @@ loongarch_cfi_frame_initial_instructions (void)
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)
{
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 2664da5..f05926d 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -49,7 +49,8 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
/* This is called to see whether a reloc against a defined symbol
should be converted into a reloc against a section. */
-#define tc_fix_adjustable(fixp) 0
+extern int loongarch_fix_adjustable (struct fix *fix);
+#define tc_fix_adjustable(fixp) loongarch_fix_adjustable(fixp)
/* Values passed to md_apply_fix don't include symbol values. */
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
@@ -59,10 +60,6 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
#define TARGET_USE_CFIPOP 1
#define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra. */
#define DWARF2_CIE_DATA_ALIGNMENT -4
-extern int loongarch_dwarf2_addr_size (void);
-#define DWARF2_FDE_RELOC_SIZE loongarch_dwarf2_addr_size ()
-#define DWARF2_ADDR_SIZE(bfd) loongarch_dwarf2_addr_size ()
-#define CFI_DIFF_EXPR_OK 0
#define tc_cfi_frame_initial_instructions \
loongarch_cfi_frame_initial_instructions