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
15namespace llvm {
16namespace exegesis {
17
18static 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.
29static 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
40namespace {
41
42class ExegesisAArch64Target : public ExegesisTarget {
43public:
44 ExegesisAArch64Target()
45 : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
46
47private:
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
70static ExegesisTarget *getTheExegesisAArch64Target() {
71 static ExegesisAArch64Target Target;
72 return &Target;
73}
74
75void InitializeAArch64ExegesisTarget() {
76 ExegesisTarget::registerTarget(T: getTheExegesisAArch64Target());
77}
78
79} // namespace exegesis
80} // namespace llvm
81