aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-10-08 16:06:15 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-10-10 15:43:57 -0700
commitf3b1d520e47415544742a379f2236671e96cc80e (patch)
treec58f155c97f5b3c0331b05c178e5e8f6d308733b /binutils
parent7ad34375b81bba62cd7c447d438fd696c47ce96d (diff)
downloadriscv-gnu-toolchain-f3b1d520e47415544742a379f2236671e96cc80e.zip
riscv-gnu-toolchain-f3b1d520e47415544742a379f2236671e96cc80e.tar.gz
riscv-gnu-toolchain-f3b1d520e47415544742a379f2236671e96cc80e.tar.bz2
binutils: relax LUI to C.LUI
Diffstat (limited to 'binutils')
-rw-r--r--binutils/bfd/elfnn-riscv.c50
-rw-r--r--binutils/bfd/elfxx-riscv.c16
-rw-r--r--binutils/include/elf/riscv.h1
-rw-r--r--binutils/include/opcode/riscv.h5
4 files changed, 62 insertions, 10 deletions
diff --git a/binutils/bfd/elfnn-riscv.c b/binutils/bfd/elfnn-riscv.c
index 67f0d87..bd086d6 100644
--- a/binutils/bfd/elfnn-riscv.c
+++ b/binutils/bfd/elfnn-riscv.c
@@ -1531,6 +1531,12 @@ perform_relocation (const reloc_howto_type *howto,
value = ENCODE_RVC_J_IMM (value);
break;
+ case R_RISCV_RVC_LUI:
+ if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value)))
+ return bfd_reloc_overflow;
+ value = ENCODE_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value));
+ break;
+
case R_RISCV_32:
case R_RISCV_64:
case R_RISCV_ADD8:
@@ -1800,9 +1806,10 @@ riscv_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* These require nothing of us at all. */
continue;
+ case R_RISCV_HI20:
case R_RISCV_BRANCH:
case R_RISCV_RVC_BRANCH:
- case R_RISCV_HI20:
+ case R_RISCV_RVC_LUI:
/* These require no special handling beyond perform_relocation. */
break;
@@ -2712,19 +2719,42 @@ _bfd_riscv_relax_lui (bfd *abfd, asection *sec,
bfd_vma symval,
bfd_boolean *again)
{
+ bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
bfd_vma gp = riscv_global_pointer_value (link_info);
+ int use_rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
- /* Bail out if this symbol isn't in range of either gp or x0. */
- if (!VALID_ITYPE_IMM (symval - gp) && !(symval < RISCV_IMM_REACH/2))
- return TRUE;
-
- /* We can delete the unnecessary AUIPC. The corresponding LO12 reloc
- will be converted to GPREL during relocation. */
BFD_ASSERT (rel->r_offset + 4 <= sec->size);
- rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
- *again = TRUE;
- return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+ /* Is the reference in range of x0 or gp? */
+ if (VALID_ITYPE_IMM (symval - gp) || (symval < RISCV_IMM_REACH/2))
+ {
+ /* We can delete the unnecessary AUIPC. The corresponding LO12 reloc
+ will be converted to gp- or x0-relative during relocation. */
+ rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
+
+ *again = TRUE;
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
+ }
+
+ /* Can we relax LUI to C.LUI? Alignment might move the section forward;
+ account for this assuming page alignment at worst. */
+ if (use_rvc
+ && VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (symval))
+ && VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (symval + ELF_MAXPAGESIZE)))
+ {
+ /* Replace LUI with C.LUI. */
+ bfd_vma lui = bfd_get_32 (abfd, contents + rel->r_offset);
+ lui = (lui & (OP_MASK_RD << OP_SH_RD)) | MATCH_C_LUI;
+ bfd_put_32 (abfd, lui, contents + rel->r_offset);
+
+ /* Replace the R_RISCV_HI20 reloc. */
+ rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_RVC_LUI);
+
+ *again = TRUE;
+ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, 2);
+ }
+
+ return TRUE;
}
/* Relax non-PIC TLS references. */
diff --git a/binutils/bfd/elfxx-riscv.c b/binutils/bfd/elfxx-riscv.c
index 6053a74..447b791 100644
--- a/binutils/bfd/elfxx-riscv.c
+++ b/binutils/bfd/elfxx-riscv.c
@@ -674,6 +674,21 @@ static reloc_howto_type howto_table[] =
0, /* src_mask */
ENCODE_RVC_J_IMM (-1U), /* dst_mask */
TRUE), /* pcrel_offset */
+
+ /* High 6 bits of 18-bit absolute address. */
+ HOWTO (R_RISCV_RVC_LUI, /* type */
+ 0, /* rightshift */
+ 2, /* size */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_RVC_LUI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_RVC_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
@@ -723,6 +738,7 @@ static const struct elf_reloc_map riscv_reloc_map[] =
{ BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
{ BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
{ BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
+ { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
};
/* Given a BFD reloc type, return a howto structure. */
diff --git a/binutils/include/elf/riscv.h b/binutils/include/elf/riscv.h
index b066951..c250b65 100644
--- a/binutils/include/elf/riscv.h
+++ b/binutils/include/elf/riscv.h
@@ -76,6 +76,7 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type)
RELOC_NUMBER (R_RISCV_ALIGN, 43)
RELOC_NUMBER (R_RISCV_RVC_BRANCH, 44)
RELOC_NUMBER (R_RISCV_RVC_JUMP, 45)
+ RELOC_NUMBER (R_RISCV_RVC_LUI, 46)
END_RELOC_NUMBERS (R_RISCV_max)
/* Processor specific flags for the ELF header e_flags field. */
diff --git a/binutils/include/opcode/riscv.h b/binutils/include/opcode/riscv.h
index 5e13826..dd30c64 100644
--- a/binutils/include/opcode/riscv.h
+++ b/binutils/include/opcode/riscv.h
@@ -71,6 +71,8 @@ static const char * const riscv_pred_succ[16] = {
((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
#define EXTRACT_RVC_IMM(x) \
(RV_X(x, 2, 5) | (-RV_X(x, 12, 1) << 5))
+#define EXTRACT_RVC_LUI_IMM(x) \
+ (EXTRACT_RVC_IMM (x) << RISCV_IMM_BITS)
#define EXTRACT_RVC_SIMM3(x) \
(RV_X(x, 10, 2) | (-RV_X(x, 12, 1) << 2))
#define EXTRACT_RVC_ADDI4SPN_IMM(x) \
@@ -106,6 +108,8 @@ static const char * const riscv_pred_succ[16] = {
((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
#define ENCODE_RVC_IMM(x) \
((RV_X(x, 0, 5) << 2) | (RV_X(x, 5, 1) << 12))
+#define ENCODE_RVC_LUI_IMM(x) \
+ ENCODE_RVC_IMM ((x) >> RISCV_IMM_BITS)
#define ENCODE_RVC_SIMM3(x) \
(RV_X(x, 0, 3) << 10)
#define ENCODE_RVC_ADDI4SPN_IMM(x) \
@@ -135,6 +139,7 @@ static const char * const riscv_pred_succ[16] = {
#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x))
#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x))
#define VALID_RVC_IMM(x) (EXTRACT_RVC_IMM(ENCODE_RVC_IMM(x)) == (x))
+#define VALID_RVC_LUI_IMM(x) (EXTRACT_RVC_LUI_IMM(ENCODE_RVC_LUI_IMM(x)) == (x))
#define VALID_RVC_SIMM3(x) (EXTRACT_RVC_SIMM3(ENCODE_RVC_SIMM3(x)) == (x))
#define VALID_RVC_ADDI4SPN_IMM(x) (EXTRACT_RVC_ADDI4SPN_IMM(ENCODE_RVC_ADDI4SPN_IMM(x)) == (x))
#define VALID_RVC_ADDI16SP_IMM(x) (EXTRACT_RVC_ADDI16SP_IMM(ENCODE_RVC_ADDI16SP_IMM(x)) == (x))