aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-05-10 16:44:17 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-05-10 16:44:17 -0700
commit70bf2e06055ba96934344b044756f9a58ed39bd5 (patch)
tree1538adbb1eb957bbc3b0d746e648cdf543d38be4 /binutils
parent0390c3cf4b8189aed3397575a4983f8f717a9f74 (diff)
downloadriscv-gnu-toolchain-70bf2e06055ba96934344b044756f9a58ed39bd5.zip
riscv-gnu-toolchain-70bf2e06055ba96934344b044756f9a58ed39bd5.tar.gz
riscv-gnu-toolchain-70bf2e06055ba96934344b044756f9a58ed39bd5.tar.bz2
binutils: support assembling JAL rd, constant
Diffstat (limited to 'binutils')
-rw-r--r--binutils/gas/config/tc-riscv.c88
1 files changed, 43 insertions, 45 deletions
diff --git a/binutils/gas/config/tc-riscv.c b/binutils/gas/config/tc-riscv.c
index 458fb14..cdc0a51 100644
--- a/binutils/gas/config/tc-riscv.c
+++ b/binutils/gas/config/tc-riscv.c
@@ -381,7 +381,8 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
/* Assume jumps are in range; the linker will catch any that aren't. */
length = jump ? 4 : 8;
- if (S_IS_DEFINED (fragp->fr_symbol)
+ if (fragp->fr_symbol != NULL
+ && S_IS_DEFINED (fragp->fr_symbol)
&& sec == S_GET_SEGMENT (fragp->fr_symbol))
{
offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
@@ -694,73 +695,70 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
if (reloc_type != BFD_RELOC_UNUSED)
{
+ reloc_howto_type *howto;
+
gas_assert(address_expr);
- if (address_expr->X_op == O_constant)
+ if (reloc_type == BFD_RELOC_12_PCREL
+ || reloc_type == BFD_RELOC_RISCV_JMP)
+ {
+ int j = reloc_type == BFD_RELOC_RISCV_JMP;
+ int best_case = riscv_insn_length (ip->insn_opcode);
+ int worst_case = relaxed_branch_length (NULL, NULL, 0);
+ add_relaxed_insn (ip, worst_case, best_case,
+ RELAX_BRANCH_ENCODE (j, best_case == 2, worst_case),
+ address_expr->X_add_symbol,
+ address_expr->X_add_number);
+ return;
+ }
+ else if (address_expr->X_op == O_constant)
{
switch (reloc_type)
{
case BFD_RELOC_32:
ip->insn_opcode |= address_expr->X_add_number;
- break;
+ goto append;
case BFD_RELOC_RISCV_HI20:
ip->insn_opcode |= ENCODE_UTYPE_IMM (
RISCV_CONST_HIGH_PART (address_expr->X_add_number));
- break;
+ goto append;
case BFD_RELOC_RISCV_LO12_S:
ip->insn_opcode |= ENCODE_STYPE_IMM (address_expr->X_add_number);
- break;
+ goto append;
case BFD_RELOC_RISCV_LO12_I:
ip->insn_opcode |= ENCODE_ITYPE_IMM (address_expr->X_add_number);
- break;
+ goto append;
default:
- internalError ();
+ break;
}
- reloc_type = BFD_RELOC_UNUSED;
- }
- else if (reloc_type == BFD_RELOC_12_PCREL
- || reloc_type == BFD_RELOC_RISCV_JMP)
- {
- int j = reloc_type == BFD_RELOC_RISCV_JMP;
- int best_case = riscv_insn_length (ip->insn_opcode);
- int worst_case = relaxed_branch_length (NULL, NULL, 0);
- add_relaxed_insn (ip, worst_case, best_case,
- RELAX_BRANCH_ENCODE (j, best_case == 2, worst_case),
- address_expr->X_add_symbol,
- address_expr->X_add_number);
- return;
- }
- else
- {
- reloc_howto_type *howto;
-
- howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
- if (howto == NULL)
- as_bad (_("Unsupported RISC-V relocation number %d"), reloc_type);
-
- ip->fixp = fix_new_exp (ip->frag, ip->where,
- bfd_get_reloc_size (howto),
- address_expr, FALSE, reloc_type);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (rv64
- && ! howto->partial_inplace
- && (reloc_type == BFD_RELOC_32
- || reloc_type == BFD_RELOC_64
- || reloc_type == BFD_RELOC_CTOR
- || reloc_type == BFD_RELOC_RISCV_HI20
- || reloc_type == BFD_RELOC_RISCV_LO12_I
- || reloc_type == BFD_RELOC_RISCV_LO12_S))
- ip->fixp->fx_no_overflow = 1;
}
+
+ howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
+ if (howto == NULL)
+ as_bad (_("Unsupported RISC-V relocation number %d"), reloc_type);
+
+ ip->fixp = fix_new_exp (ip->frag, ip->where,
+ bfd_get_reloc_size (howto),
+ address_expr, FALSE, reloc_type);
+
+ /* These relocations can have an addend that won't fit in
+ 4 octets for 64bit assembly. */
+ if (rv64
+ && ! howto->partial_inplace
+ && (reloc_type == BFD_RELOC_32
+ || reloc_type == BFD_RELOC_64
+ || reloc_type == BFD_RELOC_CTOR
+ || reloc_type == BFD_RELOC_RISCV_HI20
+ || reloc_type == BFD_RELOC_RISCV_LO12_I
+ || reloc_type == BFD_RELOC_RISCV_LO12_S))
+ ip->fixp->fx_no_overflow = 1;
}
+append:
add_fixed_insn (ip);
-
install_insn (ip);
}