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(unsigned 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(Val: 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, unsigned Reg, |
49 | const APInt &Value) const override { |
50 | if (AArch64::GPR32RegClass.contains(Reg)) |
51 | return {loadImmediate(Reg, RegBitWidth: 32, Value)}; |
52 | if (AArch64::GPR64RegClass.contains(Reg)) |
53 | return {loadImmediate(Reg, RegBitWidth: 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(P: 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(T: getTheExegesisAArch64Target()); |
77 | } |
78 | |
79 | } // namespace exegesis |
80 | } // namespace llvm |
81 | |