diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-07-22 13:03:22 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-07-22 13:03:22 -0700 |
commit | b5d67b3f53ed7392a86110ebe4bfd7dcdda65ddd (patch) | |
tree | 886ae1f0d92d190700a54be09c835d1ab55c37f9 | |
parent | 28fccff586e77d73d1ef58d0e3f2d167065513b0 (diff) | |
download | riscv-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.c | 16 | ||||
-rw-r--r-- | gcc/gcc/config/riscv/constraints.md | 3 | ||||
-rw-r--r-- | gcc/gcc/config/riscv/riscv.h | 5 | ||||
-rw-r--r-- | gcc/gcc/config/riscv/riscv.md | 10 |
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)) |