xref: /llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp (revision ff1b01bb7897bf2401540096af775d35b12eb247)
1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "../Target.h"
9 #include "AArch64.h"
10 #include "AArch64RegisterInfo.h"
11 
12 #define GET_AVAILABLE_OPCODE_CHECKER
13 #include "AArch64GenInstrInfo.inc"
14 
15 namespace llvm {
16 namespace exegesis {
17 
18 static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
19   switch (RegBitWidth) {
20   case 32:
21     return AArch64::MOVi32imm;
22   case 64:
23     return AArch64::MOVi64imm;
24   }
25   llvm_unreachable("Invalid Value Width");
26 }
27 
28 // Generates instruction to load an immediate value into a register.
29 static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
30                             const APInt &Value) {
31   if (Value.getBitWidth() > RegBitWidth)
32     llvm_unreachable("Value must fit in the Register");
33   return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
34       .addReg(Reg)
35       .addImm(Value.getZExtValue());
36 }
37 
38 #include "AArch64GenExegesis.inc"
39 
40 namespace {
41 
42 class ExegesisAArch64Target : public ExegesisTarget {
43 public:
44   ExegesisAArch64Target()
45       : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
46 
47 private:
48   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, MCRegister Reg,
49                                const APInt &Value) const override {
50     if (AArch64::GPR32RegClass.contains(Reg))
51       return {loadImmediate(Reg, 32, Value)};
52     if (AArch64::GPR64RegClass.contains(Reg))
53       return {loadImmediate(Reg, 64, Value)};
54     errs() << "setRegTo is not implemented, results will be unreliable\n";
55     return {};
56   }
57 
58   bool matchesArch(Triple::ArchType Arch) const override {
59     return Arch == Triple::aarch64 || Arch == Triple::aarch64_be;
60   }
61 
62   void addTargetSpecificPasses(PassManagerBase &PM) const override {
63     // Function return is a pseudo-instruction that needs to be expanded
64     PM.add(createAArch64ExpandPseudoPass());
65   }
66 };
67 
68 } // namespace
69 
70 static ExegesisTarget *getTheExegesisAArch64Target() {
71   static ExegesisAArch64Target Target;
72   return &Target;
73 }
74 
75 void InitializeAArch64ExegesisTarget() {
76   ExegesisTarget::registerTarget(getTheExegesisAArch64Target());
77 }
78 
79 } // namespace exegesis
80 } // namespace llvm
81