[llvm] a9a2eb8 - [JITLink][AArch64] Implement R_AARCH64_TSTBR14
Job Noorman via llvm-commits
llvm-commits at lists.llvm.org
Thu May 18 23:10:27 PDT 2023
Author: Job Noorman
Date: 2023-05-19T08:10:14+02:00
New Revision: a9a2eb81000dfd80978151dde8fd690df298394c
URL: https://github.com/llvm/llvm-project/commit/a9a2eb81000dfd80978151dde8fd690df298394c
DIFF: https://github.com/llvm/llvm-project/commit/a9a2eb81000dfd80978151dde8fd690df298394c.diff
LOG: [JITLink][AArch64] Implement R_AARCH64_TSTBR14
This relocation is used for the 14-bit immediate in test and branch
instructions.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D150778
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index b8d83ccaddc60..e7e8b99ad4562 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -107,6 +107,28 @@ enum EdgeKind_aarch64 : Edge::Kind {
/// out-of-range error will be returned.
Branch26PCRel,
+ /// A 14-bit PC-relative test and branch.
+ ///
+ /// Represents a PC-relative test and branch to a target within +/-32Kb. The
+ /// target must be 32-bit aligned.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 2 : int14
+ ///
+ /// Notes:
+ /// The '14' in the name refers to the number operand bits and follows the
+ /// naming convention used by the corresponding ELF relocation.
+ /// Since the low two bits must be zero (because of the 32-bit alignment of
+ /// the target) the operand is effectively a signed 16-bit number.
+ ///
+ ///
+ /// Errors:
+ /// - The result of the unshifted part of the fixup expression must be
+ /// 32-bit aligned otherwise an alignment error will be returned.
+ /// - The result of the fixup expression must fit into an int14 otherwise an
+ /// out-of-range error will be returned.
+ TestAndBranch14PCRel,
+
/// A 19-bit PC-relative conditional branch.
///
/// Represents a PC-relative conditional branch to a target within +/-1Mb. The
@@ -321,6 +343,11 @@ inline bool isLoadStoreImm12(uint32_t Instr) {
return (Instr & LoadStoreImm12Mask) == 0x39000000;
}
+inline bool isTestAndBranchImm14(uint32_t Instr) {
+ constexpr uint32_t TestAndBranchImm14Mask = 0x7e000000;
+ return (Instr & TestAndBranchImm14Mask) == 0x36000000;
+}
+
inline bool isCondBranchImm19(uint32_t Instr) {
constexpr uint32_t CondBranchImm19Mask = 0xfe000000;
return (Instr & CondBranchImm19Mask) == 0x54000000;
@@ -463,6 +490,23 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
*(ulittle32_t *)FixupPtr = FixedInstr;
break;
}
+ case TestAndBranch14PCRel: {
+ assert((FixupAddress.getValue() & 0x3) == 0 &&
+ "Test and branch is not 32-bit aligned");
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ assert(isTestAndBranchImm14(RawInstr) &&
+ "RawInstr is not a test and branch");
+ int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+ if (Delta & 0x3)
+ return make_error<JITLinkError>(
+ "Test and branch literal target is not 32-bit aligned");
+ if (!isInt<16>(Delta))
+ return makeTargetOutOfRangeError(G, B, E);
+ uint32_t EncodedImm = ((static_cast<uint32_t>(Delta) >> 2) & 0x3fff) << 5;
+ uint32_t FixedInstr = RawInstr | EncodedImm;
+ *(ulittle32_t *)FixupPtr = FixedInstr;
+ break;
+ }
case CondBranch19PCRel: {
assert((FixupAddress.getValue() & 0x3) == 0 &&
"Conditional branch is not 32-bit aligned");
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index 23ad696a2ba63..a062a6653bec7 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -58,6 +58,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
ELFMovwAbsG1,
ELFMovwAbsG2,
ELFMovwAbsG3,
+ ELFTstBr14,
ELFCondBr19,
ELFAbs32,
ELFAbs64,
@@ -100,6 +101,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
return ELFMovwAbsG2;
case ELF::R_AARCH64_MOVW_UABS_G3:
return ELFMovwAbsG3;
+ case ELF::R_AARCH64_TSTBR14:
+ return ELFTstBr14;
case ELF::R_AARCH64_CONDBR19:
return ELFCondBr19;
case ELF::R_AARCH64_ABS32:
@@ -290,6 +293,15 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
Kind = aarch64::MoveWide16;
break;
}
+ case ELFTstBr14: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isTestAndBranchImm14(Instr))
+ return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
+ "test and branch instruction");
+
+ Kind = aarch64::TestAndBranch14PCRel;
+ break;
+ }
case ELFCondBr19: {
uint32_t Instr = *(const ulittle32_t *)FixupContent;
if (!aarch64::isCondBranchImm19(Instr) &&
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 587b87d1d02f1..785e8cc24fe2a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -47,6 +47,8 @@ const char *getEdgeKindName(Edge::Kind R) {
return "MoveWide16";
case LDRLiteral19:
return "LDRLiteral19";
+ case TestAndBranch14PCRel:
+ return "TestAndBranch14PCRel";
case CondBranch19PCRel:
return "CondBranch19PCRel";
case Page21:
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index a74f37e22d331..e6185bf03491b 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -241,6 +241,30 @@ test_ld64_gotlo12_external:
ldr x0, [x0, :got_lo12:external_data]
.size test_ld64_gotlo12_external, .-test_ld64_gotlo12_external
+# Check R_AARCH64_TSTBR14 for tbz
+#
+# jitlink-check: decode_operand(test_tstbr14_tbz, 2) = \
+# jitlink-check: (test_tstbr14_tbz_target - test_tstbr14_tbz)[16:2]
+ .globl test_tstbr14_tbz, test_tstbr14_tbz_target
+ .p2align 2
+test_tstbr14_tbz:
+ tbz x0, 0, test_tstbr14_tbz_target
+ .skip (1 << 14)
+test_tstbr14_tbz_target:
+ .size test_tstbr14_tbz, .-test_tstbr14_tbz
+
+# Check R_AARCH64_TSTBR14 for tbnz
+#
+# jitlink-check: decode_operand(test_tstbr14_tbnz, 2) = \
+# jitlink-check: (test_tstbr14_tbnz_target - test_tstbr14_tbnz)[16:2]
+ .globl test_tstbr14_tbnz, test_tstbr14_tbnz_target
+ .p2align 2
+test_tstbr14_tbnz:
+ tbnz x0, 0, test_tstbr14_tbnz_target
+ .skip (1 << 14)
+test_tstbr14_tbnz_target:
+ .size test_tstbr14_tbnz, .-test_tstbr14_tbnz
+
# Check R_AARCH64_CONDBR19 for compare and branch instructions
#
# jitlink-check: decode_operand(test_condbr19_cbz, 1) = \
More information about the llvm-commits
mailing list