summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2022-02-22 09:52:19 -0600
committerNemanja Ivanovic <nemanja.i.ibm@gmail.com>2022-02-22 09:53:08 -0600
commit2aaba44b5c2265f90ac9f0ae188417ef79201c82 (patch)
tree8aae82410155b22aaf08d85316332e891583536b /llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
parentfee4a9712f58caa9f1c3fc6c76ac46c5407475b6 (diff)
[PowerPC] Allow absolute expressions in relocations
The Linux kernel build uses absolute expressions suffixed with @lo/@ha relocations. This currently doesn't work for DS/DQ form instructions and there is no reason for it not to. It also works with GAS. This patch allows this as long as the value is a multiple of 4/16 for DS/DQ form. Differential revision: https://reviews.llvm.org/D115419
Diffstat (limited to 'llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp63
1 files changed, 24 insertions, 39 deletions
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 715cff72dcab..7113fe33b5d7 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -341,31 +341,11 @@ public:
bool isU10Imm() const { return Kind == Immediate && isUInt<10>(getImm()); }
bool isU12Imm() const { return Kind == Immediate && isUInt<12>(getImm()); }
- bool isU16Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isUInt<16>(getImmU16Context());
- default:
- return false;
- }
- }
- bool isS16Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isInt<16>(getImmS16Context());
- default:
- return false;
- }
- }
- bool isS16ImmX4() const { return Kind == Expression ||
- (Kind == Immediate && isInt<16>(getImm()) &&
- (getImm() & 3) == 0); }
+ bool isU16Imm() const { return isExtImm<16>(/*Signed*/ false, 1); }
+ bool isS16Imm() const { return isExtImm<16>(/*Signed*/ true, 1); }
+ bool isS16ImmX4() const { return isExtImm<16>(/*Signed*/ true, 4); }
+ bool isS16ImmX16() const { return isExtImm<16>(/*Signed*/ true, 16); }
+ bool isS17Imm() const { return isExtImm<17>(/*Signed*/ true, 1); }
bool isHashImmX8() const {
// The Hash Imm form is used for instructions that check or store a hash.
@@ -375,9 +355,6 @@ public:
(getImm() & 7) == 0);
}
- bool isS16ImmX16() const { return Kind == Expression ||
- (Kind == Immediate && isInt<16>(getImm()) &&
- (getImm() & 15) == 0); }
bool isS34ImmX16() const {
return Kind == Expression ||
(Kind == Immediate && isInt<34>(getImm()) && (getImm() & 15) == 0);
@@ -388,17 +365,6 @@ public:
return Kind == Expression || (Kind == Immediate && isInt<34>(getImm()));
}
- bool isS17Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isInt<17>(getImmS16Context());
- default:
- return false;
- }
- }
bool isTLSReg() const { return Kind == TLSRegister; }
bool isDirectBr() const {
if (Kind == Expression)
@@ -712,6 +678,25 @@ public:
return CreateExpr(Val, S, E, IsPPC64);
}
+
+private:
+ template <unsigned Width>
+ bool isExtImm(bool Signed, unsigned Multiple) const {
+ switch (Kind) {
+ default:
+ return false;
+ case Expression:
+ return true;
+ case Immediate:
+ case ContextImmediate:
+ if (Signed)
+ return isInt<Width>(getImmS16Context()) &&
+ (getImmS16Context() & (Multiple - 1)) == 0;
+ else
+ return isUInt<Width>(getImmU16Context()) &&
+ (getImmU16Context() & (Multiple - 1)) == 0;
+ }
+ }
};
} // end anonymous namespace.