aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-07-22 13:03:22 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-07-22 13:03:22 -0700
commitb5d67b3f53ed7392a86110ebe4bfd7dcdda65ddd (patch)
tree886ae1f0d92d190700a54be09c835d1ab55c37f9
parent28fccff586e77d73d1ef58d0e3f2d167065513b0 (diff)
downloadriscv-gnu-toolchain-b5d67b3f53ed7392a86110ebe4bfd7dcdda65ddd.zip
riscv-gnu-toolchain-b5d67b3f53ed7392a86110ebe4bfd7dcdda65ddd.tar.gz
riscv-gnu-toolchain-b5d67b3f53ed7392a86110ebe4bfd7dcdda65ddd.tar.bz2
Avoid t0 for indirect calls
We sometimes use t0 as a link register, e.g. for the compressed prologues and epilogues, and so we want microarchitectures to push the RAS when rd=t0 and pop the RAS when rs1=t0. Thus, we want to avoid using t0 for indirect calls to avoid errant RAS operations.
-rw-r--r--binutils/bfd/elfnn-riscv.c16
-rw-r--r--gcc/gcc/config/riscv/constraints.md3
-rw-r--r--gcc/gcc/config/riscv/riscv.h5
-rw-r--r--gcc/gcc/config/riscv/riscv.md10
4 files changed, 20 insertions, 14 deletions
diff --git a/binutils/bfd/elfnn-riscv.c b/binutils/bfd/elfnn-riscv.c
index 16792c6..b6ef1cc 100644
--- a/binutils/bfd/elfnn-riscv.c
+++ b/binutils/bfd/elfnn-riscv.c
@@ -190,7 +190,7 @@ static void
riscv_make_plt0_entry(bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry)
{
/* auipc t2, %hi(.got.plt)
- sub t1, t1, t0 # shifted .got.plt offset + hdr size + 12
+ sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12
l[w|d] t3, %lo(.got.plt)(t2) # _dl_runtime_resolve
addi t1, t1, -(hdr size + 12) # shifted .got.plt offset
addi t0, t2, %lo(.got.plt) # &.got.plt
@@ -199,7 +199,7 @@ riscv_make_plt0_entry(bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry)
jr t3 */
entry[0] = RISCV_UTYPE (AUIPC, X_T2, RISCV_PCREL_HIGH_PART (gotplt_addr, addr));
- entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T0);
+ entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T3);
entry[2] = RISCV_ITYPE (LREG, X_T3, X_T2, RISCV_PCREL_LOW_PART (gotplt_addr, addr));
entry[3] = RISCV_ITYPE (ADDI, X_T1, X_T1, -(PLT_HEADER_SIZE + 12));
entry[4] = RISCV_ITYPE (ADDI, X_T0, X_T2, RISCV_PCREL_LOW_PART (gotplt_addr, addr));
@@ -213,14 +213,14 @@ riscv_make_plt0_entry(bfd_vma gotplt_addr, bfd_vma addr, uint32_t *entry)
static void
riscv_make_plt_entry(bfd_vma got_address, bfd_vma addr, uint32_t *entry)
{
- /* auipc t1, %hi(.got.plt entry)
- l[w|d] t0, %lo(.got.plt entry)(t1)
- jalr t1, t0
+ /* auipc t3, %hi(.got.plt entry)
+ l[w|d] t3, %lo(.got.plt entry)(t3)
+ jalr t1, t3
nop */
- entry[0] = RISCV_UTYPE (AUIPC, X_T1, RISCV_PCREL_HIGH_PART (got_address, addr));
- entry[1] = RISCV_ITYPE (LREG, X_T0, X_T1, RISCV_PCREL_LOW_PART(got_address, addr));
- entry[2] = RISCV_ITYPE (JALR, X_T1, X_T0, 0);
+ entry[0] = RISCV_UTYPE (AUIPC, X_T3, RISCV_PCREL_HIGH_PART (got_address, addr));
+ entry[1] = RISCV_ITYPE (LREG, X_T3, X_T3, RISCV_PCREL_LOW_PART(got_address, addr));
+ entry[2] = RISCV_ITYPE (JALR, X_T1, X_T3, 0);
entry[3] = RISCV_NOP;
}
diff --git a/gcc/gcc/config/riscv/constraints.md b/gcc/gcc/config/riscv/constraints.md
index a348fd1..19dbbd7 100644
--- a/gcc/gcc/config/riscv/constraints.md
+++ b/gcc/gcc/config/riscv/constraints.md
@@ -30,6 +30,9 @@
(define_register_constraint "j" "T_REGS"
"@internal")
+(define_register_constraint "l" "JALR_REGS"
+ "@internal")
+
;; Integer constraints
(define_constraint "Z"
diff --git a/gcc/gcc/config/riscv/riscv.h b/gcc/gcc/config/riscv/riscv.h
index bbfec02..f4d432c 100644
--- a/gcc/gcc/config/riscv/riscv.h
+++ b/gcc/gcc/config/riscv/riscv.h
@@ -549,6 +549,7 @@ enum reg_class
{
NO_REGS, /* no registers in set */
T_REGS, /* registers used by indirect sibcalls */
+ JALR_REGS, /* registers used by indirect calls */
GR_REGS, /* integer registers */
FP_REGS, /* floating point registers */
FRAME_REGS, /* $arg and $frame */
@@ -568,6 +569,7 @@ enum reg_class
{ \
"NO_REGS", \
"T_REGS", \
+ "JALR_REGS", \
"GR_REGS", \
"FP_REGS", \
"FRAME_REGS", \
@@ -588,7 +590,8 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0xf00000e0, 0x00000000, 0x00000000 }, /* T_REGS */ \
+ { 0xf0000040, 0x00000000, 0x00000000 }, /* T_REGS */ \
+ { 0xffffff40, 0x00000000, 0x00000000 }, /* JALR_REGS */ \
{ 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \
{ 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \
{ 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \
diff --git a/gcc/gcc/config/riscv/riscv.md b/gcc/gcc/config/riscv/riscv.md
index 8ce17ab..af3a3c2 100644
--- a/gcc/gcc/config/riscv/riscv.md
+++ b/gcc/gcc/config/riscv/riscv.md
@@ -2122,7 +2122,7 @@
})
(define_insn "indirect_jump<mode>"
- [(set (pc) (match_operand:P 0 "register_operand" "r"))]
+ [(set (pc) (match_operand:P 0 "register_operand" "l"))]
""
"jr\t%0"
[(set_attr "type" "jump")
@@ -2146,7 +2146,7 @@
})
(define_insn "tablejump<mode>"
- [(set (pc) (match_operand:GPR 0 "register_operand" "r"))
+ [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
(use (label_ref (match_operand 1 "" "")))]
""
"jr\t%0"
@@ -2343,7 +2343,7 @@
})
(define_insn "call_internal"
- [(call (mem:SI (match_operand 0 "call_insn_operand" "r,S"))
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S"))
(match_operand 1 "" ""))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
@@ -2366,7 +2366,7 @@
;; See comment for call_internal.
(define_insn "call_value_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "r,S"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "l,S"))
(match_operand 2 "" "")))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
@@ -2378,7 +2378,7 @@
;; See comment for call_internal.
(define_insn "call_value_multiple_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "r,S"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "l,S"))
(match_operand 2 "" "")))
(set (match_operand 3 "register_operand" "")
(call (mem:SI (match_dup 1))