aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp79
1 files changed, 78 insertions, 1 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
index 942e667bc261..a4e6a09863e6 100644
--- a/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
@@ -97,13 +97,90 @@ public:
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
unsigned NumOps = Inst.getNumOperands();
- if (isBranch(Inst) || Inst.getOpcode() == LoongArch::BL) {
+ if ((isBranch(Inst) && !isIndirectBranch(Inst)) ||
+ Inst.getOpcode() == LoongArch::BL) {
Target = Addr + Inst.getOperand(NumOps - 1).getImm();
return true;
}
return false;
}
+
+ bool isTerminator(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isTerminator(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() == LoongArch::R0;
+ }
+ }
+
+ bool isCall(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isCall(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() != LoongArch::R0;
+ }
+ }
+
+ bool isReturn(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isReturn(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+ Inst.getOperand(1).getReg() == LoongArch::R1;
+ }
+ }
+
+ bool isBranch(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isBranch(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+ Inst.getOperand(1).getReg() != LoongArch::R1;
+ }
+ }
+
+ bool isUnconditionalBranch(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isUnconditionalBranch(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+ Inst.getOperand(1).getReg() != LoongArch::R1;
+ }
+ }
+
+ bool isIndirectBranch(const MCInst &Inst) const override {
+ if (MCInstrAnalysis::isIndirectBranch(Inst))
+ return true;
+
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case LoongArch::JIRL:
+ return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+ Inst.getOperand(1).getReg() != LoongArch::R1;
+ }
+ }
};
} // end namespace