diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-05-10 16:44:17 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-05-10 16:44:17 -0700 |
commit | 70bf2e06055ba96934344b044756f9a58ed39bd5 (patch) | |
tree | 1538adbb1eb957bbc3b0d746e648cdf543d38be4 /binutils | |
parent | 0390c3cf4b8189aed3397575a4983f8f717a9f74 (diff) | |
download | riscv-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.c | 88 |
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); } |