1//===-- VEMCCodeEmitter.cpp - Convert VE code to machine code -------------===//
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//
9// This file implements the VEMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MCTargetDesc/VEFixupKinds.h"
14#include "VE.h"
15#include "VEMCAsmInfo.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/MC/MCCodeEmitter.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCFixup.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/MC/MCRegisterInfo.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
27#include "llvm/Support/EndianStream.h"
28#include <cassert>
29#include <cstdint>
30
31using namespace llvm;
32
33#define DEBUG_TYPE "mccodeemitter"
34
35STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
36
37namespace {
38
39class VEMCCodeEmitter : public MCCodeEmitter {
40 MCContext &Ctx;
41
42public:
43 VEMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
44 : Ctx(ctx) {}
45 VEMCCodeEmitter(const VEMCCodeEmitter &) = delete;
46 VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete;
47 ~VEMCCodeEmitter() override = default;
48
49 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
50 SmallVectorImpl<MCFixup> &Fixups,
51 const MCSubtargetInfo &STI) const override;
52
53 // getBinaryCodeForInstr - TableGen'erated function for getting the
54 // binary encoding for an instruction.
55 uint64_t getBinaryCodeForInstr(const MCInst &MI,
56 SmallVectorImpl<MCFixup> &Fixups,
57 const MCSubtargetInfo &STI) const;
58
59 /// getMachineOpValue - Return binary encoding of operand. If the machine
60 /// operand requires relocation, record the relocation and return zero.
61 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
62 SmallVectorImpl<MCFixup> &Fixups,
63 const MCSubtargetInfo &STI) const;
64
65 uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
66 SmallVectorImpl<MCFixup> &Fixups,
67 const MCSubtargetInfo &STI) const;
68 uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo,
69 SmallVectorImpl<MCFixup> &Fixups,
70 const MCSubtargetInfo &STI) const;
71 uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo,
72 SmallVectorImpl<MCFixup> &Fixups,
73 const MCSubtargetInfo &STI) const;
74};
75
76} // end anonymous namespace
77
78static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,
79 const MCExpr *Value, uint16_t Kind) {
80 bool PCRel = false;
81 switch (Kind) {
82 case VE::fixup_ve_srel32:
83 case VE::fixup_ve_pc_hi32:
84 case VE::fixup_ve_pc_lo32:
85 PCRel = true;
86 }
87 Fixups.push_back(Elt: MCFixup::create(Offset, Value, Kind, PCRel));
88}
89
90void VEMCCodeEmitter::encodeInstruction(const MCInst &MI,
91 SmallVectorImpl<char> &CB,
92 SmallVectorImpl<MCFixup> &Fixups,
93 const MCSubtargetInfo &STI) const {
94 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
95 support::endian::write<uint64_t>(Out&: CB, V: Bits, E: llvm::endianness::little);
96
97 ++MCNumEmitted; // Keep track of the # of mi's emitted.
98}
99
100unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI,
101 const MCOperand &MO,
102 SmallVectorImpl<MCFixup> &Fixups,
103 const MCSubtargetInfo &STI) const {
104 if (MO.isReg())
105 return Ctx.getRegisterInfo()->getEncodingValue(Reg: MO.getReg());
106 if (MO.isImm())
107 return static_cast<unsigned>(MO.getImm());
108
109 assert(MO.isExpr());
110
111 const MCExpr *Expr = MO.getExpr();
112 if (const auto *SExpr = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
113 auto Kind = VE::getFixupKind(S: SExpr->getSpecifier());
114 addFixup(Fixups, Offset: 0, Value: Expr, Kind);
115 return 0;
116 }
117
118 int64_t Res;
119 if (Expr->evaluateAsAbsolute(Res))
120 return Res;
121
122 llvm_unreachable("Unhandled expression!");
123 return 0;
124}
125
126uint64_t
127VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
128 SmallVectorImpl<MCFixup> &Fixups,
129 const MCSubtargetInfo &STI) const {
130 const MCOperand &MO = MI.getOperand(i: OpNo);
131 if (MO.isReg() || MO.isImm())
132 return getMachineOpValue(MI, MO, Fixups, STI);
133
134 addFixup(Fixups, Offset: 0, Value: MO.getExpr(), Kind: VE::fixup_ve_srel32);
135 return 0;
136}
137
138uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo,
139 SmallVectorImpl<MCFixup> &Fixups,
140 const MCSubtargetInfo &STI) const {
141 const MCOperand &MO = MI.getOperand(i: OpNo);
142 if (MO.isImm())
143 return VECondCodeToVal(
144 CC: static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI)));
145 return 0;
146}
147
148uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo,
149 SmallVectorImpl<MCFixup> &Fixups,
150 const MCSubtargetInfo &STI) const {
151 const MCOperand &MO = MI.getOperand(i: OpNo);
152 if (MO.isImm())
153 return VERDToVal(R: static_cast<VERD::RoundingMode>(
154 getMachineOpValue(MI, MO, Fixups, STI)));
155 return 0;
156}
157
158#include "VEGenMCCodeEmitter.inc"
159
160MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII,
161 MCContext &Ctx) {
162 return new VEMCCodeEmitter(MCII, Ctx);
163}
164