10b57cec5SDimitry Andric //===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the SparcMCCodeEmitter class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "MCTargetDesc/SparcFixupKinds.h"
140b57cec5SDimitry Andric #include "SparcMCExpr.h"
150b57cec5SDimitry Andric #include "SparcMCTargetDesc.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
25e8d8bef9SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
290b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
300b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
310b57cec5SDimitry Andric #include "llvm/Support/EndianStream.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
330b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3406c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
350b57cec5SDimitry Andric #include <cassert>
360b57cec5SDimitry Andric #include <cstdint>
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter"
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric namespace {
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric class SparcMCCodeEmitter : public MCCodeEmitter {
470b57cec5SDimitry Andric MCContext &Ctx;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric public:
SparcMCCodeEmitter(const MCInstrInfo &,MCContext & ctx)50753f127fSDimitry Andric SparcMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
51753f127fSDimitry Andric : Ctx(ctx) {}
520b57cec5SDimitry Andric SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
530b57cec5SDimitry Andric SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete;
540b57cec5SDimitry Andric ~SparcMCCodeEmitter() override = default;
550b57cec5SDimitry Andric
5606c3fb27SDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
570b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
580b57cec5SDimitry Andric const MCSubtargetInfo &STI) const override;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the
610b57cec5SDimitry Andric // binary encoding for an instruction.
620b57cec5SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI,
630b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
640b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine
670b57cec5SDimitry Andric /// operand requires relocation, record the relocation and return zero.
680b57cec5SDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
690b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
700b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
710b57cec5SDimitry Andric unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
720b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
730b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
740b57cec5SDimitry Andric unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
760b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
77e8d8bef9SDimitry Andric unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
78e8d8bef9SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
79e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) const;
800b57cec5SDimitry Andric unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
810b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
820b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
830b57cec5SDimitry Andric unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
840b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const;
860b57cec5SDimitry Andric };
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric } // end anonymous namespace
890b57cec5SDimitry Andric
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const9006c3fb27SDimitry Andric void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,
9106c3fb27SDimitry Andric SmallVectorImpl<char> &CB,
920b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
930b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
940b57cec5SDimitry Andric unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
9506c3fb27SDimitry Andric support::endian::write(CB, Bits,
96*5f757f3fSDimitry Andric Ctx.getAsmInfo()->isLittleEndian()
97*5f757f3fSDimitry Andric ? llvm::endianness::little
98*5f757f3fSDimitry Andric : llvm::endianness::big);
9981ad6265SDimitry Andric
10081ad6265SDimitry Andric // Some instructions have phantom operands that only contribute a fixup entry.
10181ad6265SDimitry Andric unsigned SymOpNo = 0;
1020b57cec5SDimitry Andric switch (MI.getOpcode()) {
1030b57cec5SDimitry Andric default: break;
10481ad6265SDimitry Andric case SP::TLS_CALL: SymOpNo = 1; break;
10581ad6265SDimitry Andric case SP::GDOP_LDrr:
10681ad6265SDimitry Andric case SP::GDOP_LDXrr:
1070b57cec5SDimitry Andric case SP::TLS_ADDrr:
1080b57cec5SDimitry Andric case SP::TLS_LDrr:
10981ad6265SDimitry Andric case SP::TLS_LDXrr: SymOpNo = 3; break;
1100b57cec5SDimitry Andric }
11181ad6265SDimitry Andric if (SymOpNo != 0) {
11281ad6265SDimitry Andric const MCOperand &MO = MI.getOperand(SymOpNo);
1130b57cec5SDimitry Andric uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
1140b57cec5SDimitry Andric assert(op == 0 && "Unexpected operand value!");
1150b57cec5SDimitry Andric (void)op; // suppress warning.
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted.
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1220b57cec5SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO,
1230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1250b57cec5SDimitry Andric if (MO.isReg())
1260b57cec5SDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric if (MO.isImm())
1290b57cec5SDimitry Andric return MO.getImm();
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric assert(MO.isExpr());
1320b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr();
1330b57cec5SDimitry Andric if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
1340b57cec5SDimitry Andric MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
1350b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind));
1360b57cec5SDimitry Andric return 0;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric int64_t Res;
1400b57cec5SDimitry Andric if (Expr->evaluateAsAbsolute(Res))
1410b57cec5SDimitry Andric return Res;
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric llvm_unreachable("Unhandled expression!");
1440b57cec5SDimitry Andric return 0;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
147e8d8bef9SDimitry Andric unsigned
getSImm13OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const148e8d8bef9SDimitry Andric SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
149e8d8bef9SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
150e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) const {
151e8d8bef9SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
152e8d8bef9SDimitry Andric
153e8d8bef9SDimitry Andric if (MO.isImm())
154e8d8bef9SDimitry Andric return MO.getImm();
155e8d8bef9SDimitry Andric
156e8d8bef9SDimitry Andric assert(MO.isExpr() &&
157e8d8bef9SDimitry Andric "getSImm13OpValue expects only expressions or an immediate");
158e8d8bef9SDimitry Andric
159e8d8bef9SDimitry Andric const MCExpr *Expr = MO.getExpr();
160e8d8bef9SDimitry Andric
161e8d8bef9SDimitry Andric // Constant value, no fixup is needed
162e8d8bef9SDimitry Andric if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
163e8d8bef9SDimitry Andric return CE->getValue();
164e8d8bef9SDimitry Andric
165e8d8bef9SDimitry Andric MCFixupKind Kind;
166e8d8bef9SDimitry Andric if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
167e8d8bef9SDimitry Andric Kind = MCFixupKind(SExpr->getFixupKind());
168e8d8bef9SDimitry Andric } else {
169e8d8bef9SDimitry Andric bool IsPic = Ctx.getObjectFileInfo()->isPositionIndependent();
170e8d8bef9SDimitry Andric Kind = IsPic ? MCFixupKind(Sparc::fixup_sparc_got13)
171e8d8bef9SDimitry Andric : MCFixupKind(Sparc::fixup_sparc_13);
172e8d8bef9SDimitry Andric }
173e8d8bef9SDimitry Andric
174e8d8bef9SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind));
175e8d8bef9SDimitry Andric return 0;
176e8d8bef9SDimitry Andric }
177e8d8bef9SDimitry Andric
1780b57cec5SDimitry Andric unsigned SparcMCCodeEmitter::
getCallTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1790b57cec5SDimitry Andric getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
1800b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
1810b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
1820b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
183e8d8bef9SDimitry Andric const MCExpr *Expr = MO.getExpr();
184e8d8bef9SDimitry Andric const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr);
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric if (MI.getOpcode() == SP::TLS_CALL) {
1870b57cec5SDimitry Andric // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
1880b57cec5SDimitry Andric // encodeInstruction.
1890b57cec5SDimitry Andric #ifndef NDEBUG
1900b57cec5SDimitry Andric // Verify that the callee is actually __tls_get_addr.
1910b57cec5SDimitry Andric assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
1920b57cec5SDimitry Andric "Unexpected expression in TLS_CALL");
1930b57cec5SDimitry Andric const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
1940b57cec5SDimitry Andric assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
1950b57cec5SDimitry Andric "Unexpected function for TLS_CALL");
1960b57cec5SDimitry Andric #endif
1970b57cec5SDimitry Andric return 0;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
200e8d8bef9SDimitry Andric MCFixupKind Kind = MCFixupKind(SExpr->getFixupKind());
201e8d8bef9SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind));
2020b57cec5SDimitry Andric return 0;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric unsigned SparcMCCodeEmitter::
getBranchTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2060b57cec5SDimitry Andric getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
2070b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
2080b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
2090b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
2100b57cec5SDimitry Andric if (MO.isReg() || MO.isImm())
2110b57cec5SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI);
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
2140b57cec5SDimitry Andric (MCFixupKind)Sparc::fixup_sparc_br22));
2150b57cec5SDimitry Andric return 0;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric unsigned SparcMCCodeEmitter::
getBranchPredTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2190b57cec5SDimitry Andric getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
2200b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
2210b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
2220b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
2230b57cec5SDimitry Andric if (MO.isReg() || MO.isImm())
2240b57cec5SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI);
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(),
2270b57cec5SDimitry Andric (MCFixupKind)Sparc::fixup_sparc_br19));
2280b57cec5SDimitry Andric return 0;
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric unsigned SparcMCCodeEmitter::
getBranchOnRegTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2320b57cec5SDimitry Andric getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
2330b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
2340b57cec5SDimitry Andric const MCSubtargetInfo &STI) const {
2350b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
2360b57cec5SDimitry Andric if (MO.isReg() || MO.isImm())
2370b57cec5SDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI);
2380b57cec5SDimitry Andric
23906c3fb27SDimitry Andric Fixups.push_back(
24006c3fb27SDimitry Andric MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br16));
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric return 0;
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric #include "SparcGenMCCodeEmitter.inc"
2460b57cec5SDimitry Andric
createSparcMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)2470b57cec5SDimitry Andric MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
2480b57cec5SDimitry Andric MCContext &Ctx) {
2490b57cec5SDimitry Andric return new SparcMCCodeEmitter(MCII, Ctx);
2500b57cec5SDimitry Andric }
251