diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h @@ -155,6 +155,18 @@ /// Fixup <- (Target - *{8}Fixup - Addend) R_RISCV_SUB64, + /// 8-bit PC-relative branch offset + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) + R_RISCV_RVC_BRANCH, + + /// 11-bit PC-relative jump offset + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) + R_RISCV_RVC_JUMP, + /// 6 bits label subtraction /// /// Fixup expression diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -383,6 +383,41 @@ *(little64_t *)FixupPtr = static_cast(Value); break; } + case R_RISCV_RVC_BRANCH: { + int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; + if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 8))) + return makeTargetOutOfRangeError(G, B, E); + if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + uint16_t Imm8 = extractBits(Value, 8, 1) << 12; + uint16_t Imm4_3 = extractBits(Value, 3, 2) << 10; + uint16_t Imm7_6 = extractBits(Value, 6, 2) << 5; + uint16_t Imm2_1 = extractBits(Value, 1, 2) << 3; + uint16_t Imm5 = extractBits(Value, 5, 1) << 2; + uint16_t RawInstr = *(little16_t *)FixupPtr; + *(little16_t *)FixupPtr = + (RawInstr & 0xE383) | Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5; + break; + } + case R_RISCV_RVC_JUMP: { + int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; + if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 11))) + return makeTargetOutOfRangeError(G, B, E); + if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); + uint16_t Imm11 = extractBits(Value, 11, 1) << 12; + uint16_t Imm4 = extractBits(Value, 4, 1) << 11; + uint16_t Imm9_8 = extractBits(Value, 8, 2) << 9; + uint16_t Imm10 = extractBits(Value, 10, 1) << 8; + uint16_t Imm6 = extractBits(Value, 6, 1) << 7; + uint16_t Imm7 = extractBits(Value, 7, 1) << 6; + uint16_t Imm3_1 = extractBits(Value, 1, 3) << 3; + uint16_t Imm5 = extractBits(Value, 5, 1) << 2; + uint16_t RawInstr = *(little16_t *)FixupPtr; + *(little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 | + Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5; + break; + } case R_RISCV_SUB6: { int64_t Value = *(reinterpret_cast(FixupAddress.getValue())) & 0x3f; @@ -477,6 +512,10 @@ return EdgeKind_riscv::R_RISCV_SUB32; case ELF::R_RISCV_SUB64: return EdgeKind_riscv::R_RISCV_SUB64; + case ELF::R_RISCV_RVC_BRANCH: + return EdgeKind_riscv::R_RISCV_RVC_BRANCH; + case ELF::R_RISCV_RVC_JUMP: + return EdgeKind_riscv::R_RISCV_RVC_JUMP; case ELF::R_RISCV_SUB6: return EdgeKind_riscv::R_RISCV_SUB6; case ELF::R_RISCV_SET6: diff --git a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp @@ -62,6 +62,10 @@ return "R_RISCV_SUB32"; case R_RISCV_SUB64: return "R_RISCV_SUB64"; + case R_RISCV_RVC_BRANCH: + return "R_RISCV_RVC_BRANCH"; + case R_RISCV_RVC_JUMP: + return "R_RISCV_RVC_JUMP"; case R_RISCV_SUB6: return "R_RISCV_SUB6"; case R_RISCV_SET6: diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_rvc.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_rvc.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_rvc.s @@ -0,0 +1,49 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=riscv64 -mattr=+c,+relax -filetype=obj \ +# RUN: -o %t/elf_riscv64_rvc.o %s +# RUN: llvm-mc -triple=riscv32 -mattr=+c,+relax -filetype=obj \ +# RUN: -o %t/elf_riscv32_rvc.o %s +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ +# RUN: -check %s %t/elf_riscv64_rvc.o +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ +# RUN: -check %s %t/elf_riscv32_rvc.o + +.globl main +main: + ret + +# Test R_RISCV_RVC_BRANCH + +# jitlink-check: *{2}(test_rvc_branch) = 0xC111 +# jitlink-check: *{2}(test_rvc_branch+2) = 0xE109 +.globl test_rvc_branch +.type test_rvc_branch,@function +test_rvc_branch: + c.beqz a0, test_rvc_branch_ret + c.bnez a0, test_rvc_branch_ret +test_rvc_branch_ret: + ret +# jitlink-check: *{2}(test_rvc_branch+6) = 0xDD7D +# jitlink-check: *{2}(test_rvc_branch+8) = 0xFD75 +test_rvc_branch2: + c.beqz a0, test_rvc_branch_ret + c.bnez a0, test_rvc_branch_ret + +.size test_rvc_branch, .-test_rvc_branch + +# Test R_RISCV_RVC_JUMP + +# jitlink-check: *{2}(test_rvc_jump) = 0xA009 +.globl test_rvc_jump +.type test_rvc_jump,@function +test_rvc_jump: + c.j test_rvc_jump_ret +test_rvc_jump_ret: + ret +# jitlink-check: *{2}(test_rvc_jump+4) = 0xBFFD +test_rvc_jump2: + c.j test_rvc_jump_ret + +.size test_rvc_jump, .-test_rvc_jump