10b57cec5SDimitry Andric //===-- LanaiMCCodeEmitter.cpp - Convert Lanai 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 LanaiMCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "LanaiAluCode.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/LanaiBaseInfo.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/LanaiFixupKinds.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/LanaiMCExpr.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 180b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 260b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 2706c3fb27SDimitry Andric #include "llvm/Support/EndianStream.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric #include <cassert> 300b57cec5SDimitry Andric #include <cstdint> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric namespace llvm { 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace { 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric class LanaiMCCodeEmitter : public MCCodeEmitter { 410b57cec5SDimitry Andric public: 420b57cec5SDimitry Andric LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) {} 430b57cec5SDimitry Andric LanaiMCCodeEmitter(const LanaiMCCodeEmitter &) = delete; 440b57cec5SDimitry Andric void operator=(const LanaiMCCodeEmitter &) = delete; 450b57cec5SDimitry Andric ~LanaiMCCodeEmitter() override = default; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // The functions below are called by TableGen generated functions for getting 480b57cec5SDimitry Andric // the binary encoding of instructions/opereands. 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the 510b57cec5SDimitry Andric // binary encoding for an instruction. 520b57cec5SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &Inst, 530b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 540b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // getMachineOpValue - Return binary encoding of operand. If the machine 570b57cec5SDimitry Andric // operand requires relocation, record the relocation and return zero. 580b57cec5SDimitry Andric unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp, 590b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 600b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo, 630b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 640b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo, 670b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 680b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo, 710b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 720b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo, 750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 760b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const; 770b57cec5SDimitry Andric 7806c3fb27SDimitry Andric void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB, 790b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 800b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const override; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 830b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 860b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 870b57cec5SDimitry Andric }; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric } // end anonymous namespace 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric static Lanai::Fixups FixupKind(const MCExpr *Expr) { 920b57cec5SDimitry Andric if (isa<MCSymbolRefExpr>(Expr)) 930b57cec5SDimitry Andric return Lanai::FIXUP_LANAI_21; 940b57cec5SDimitry Andric if (const LanaiMCExpr *McExpr = dyn_cast<LanaiMCExpr>(Expr)) { 950b57cec5SDimitry Andric LanaiMCExpr::VariantKind ExprKind = McExpr->getKind(); 960b57cec5SDimitry Andric switch (ExprKind) { 970b57cec5SDimitry Andric case LanaiMCExpr::VK_Lanai_None: 980b57cec5SDimitry Andric return Lanai::FIXUP_LANAI_21; 990b57cec5SDimitry Andric case LanaiMCExpr::VK_Lanai_ABS_HI: 1000b57cec5SDimitry Andric return Lanai::FIXUP_LANAI_HI16; 1010b57cec5SDimitry Andric case LanaiMCExpr::VK_Lanai_ABS_LO: 1020b57cec5SDimitry Andric return Lanai::FIXUP_LANAI_LO16; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric return Lanai::Fixups(0); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // getMachineOpValue - Return binary encoding of operand. If the machine 1090b57cec5SDimitry Andric // operand requires relocation, record the relocation and return zero. 1100b57cec5SDimitry Andric unsigned LanaiMCCodeEmitter::getMachineOpValue( 1110b57cec5SDimitry Andric const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups, 1120b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 1130b57cec5SDimitry Andric if (MCOp.isReg()) 1140b57cec5SDimitry Andric return getLanaiRegisterNumbering(MCOp.getReg()); 1150b57cec5SDimitry Andric if (MCOp.isImm()) 1160b57cec5SDimitry Andric return static_cast<unsigned>(MCOp.getImm()); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // MCOp must be an expression 1190b57cec5SDimitry Andric assert(MCOp.isExpr()); 1200b57cec5SDimitry Andric const MCExpr *Expr = MCOp.getExpr(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Extract the symbolic reference side of a binary expression. 1230b57cec5SDimitry Andric if (Expr->getKind() == MCExpr::Binary) { 1240b57cec5SDimitry Andric const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr); 1250b57cec5SDimitry Andric Expr = BinaryExpr->getLHS(); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric assert(isa<LanaiMCExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef); 1290b57cec5SDimitry Andric // Push fixup (all info is contained within) 1300b57cec5SDimitry Andric Fixups.push_back( 1310b57cec5SDimitry Andric MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr)))); 1320b57cec5SDimitry Andric return 0; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric // Helper function to adjust P and Q bits on load and store instructions. 1360b57cec5SDimitry Andric static unsigned adjustPqBits(const MCInst &Inst, unsigned Value, 1370b57cec5SDimitry Andric unsigned PBitShift, unsigned QBitShift) { 1380b57cec5SDimitry Andric const MCOperand AluOp = Inst.getOperand(3); 1390b57cec5SDimitry Andric unsigned AluCode = AluOp.getImm(); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Set the P bit to one iff the immediate is nonzero and not a post-op 1420b57cec5SDimitry Andric // instruction. 1430b57cec5SDimitry Andric const MCOperand Op2 = Inst.getOperand(2); 1440b57cec5SDimitry Andric Value &= ~(1 << PBitShift); 1450b57cec5SDimitry Andric if (!LPAC::isPostOp(AluCode) && 1460b57cec5SDimitry Andric ((Op2.isImm() && Op2.getImm() != 0) || 1470b57cec5SDimitry Andric (Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr()))) 1480b57cec5SDimitry Andric Value |= (1 << PBitShift); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // Set the Q bit to one iff it is a post- or pre-op instruction. 1510b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && 1520b57cec5SDimitry Andric "Expected register operand."); 1530b57cec5SDimitry Andric Value &= ~(1 << QBitShift); 1540b57cec5SDimitry Andric if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) || 1550b57cec5SDimitry Andric (Op2.isReg() && Op2.getReg() != Lanai::R0))) 1560b57cec5SDimitry Andric Value |= (1 << QBitShift); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric return Value; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric unsigned 1620b57cec5SDimitry Andric LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 1630b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1640b57cec5SDimitry Andric return adjustPqBits(Inst, Value, 17, 16); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric unsigned 1680b57cec5SDimitry Andric LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 1690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1700b57cec5SDimitry Andric return adjustPqBits(Inst, Value, 11, 10); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric void LanaiMCCodeEmitter::encodeInstruction( 17406c3fb27SDimitry Andric const MCInst &Inst, SmallVectorImpl<char> &CB, 17506c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1760b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 1770b57cec5SDimitry Andric // Get instruction encoding and emit it 1780b57cec5SDimitry Andric unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo); 1790b57cec5SDimitry Andric ++MCNumEmitted; // Keep track of the number of emitted insns. 1800b57cec5SDimitry Andric 181*5f757f3fSDimitry Andric support::endian::write<uint32_t>(CB, Value, llvm::endianness::big); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Encode Lanai Memory Operand 1850b57cec5SDimitry Andric unsigned LanaiMCCodeEmitter::getRiMemoryOpValue( 1860b57cec5SDimitry Andric const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 1870b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 1880b57cec5SDimitry Andric unsigned Encoding; 1890b57cec5SDimitry Andric const MCOperand Op1 = Inst.getOperand(OpNo + 0); 1900b57cec5SDimitry Andric const MCOperand Op2 = Inst.getOperand(OpNo + 1); 1910b57cec5SDimitry Andric const MCOperand AluOp = Inst.getOperand(OpNo + 2); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric assert(Op1.isReg() && "First operand is not register."); 1940b57cec5SDimitry Andric assert((Op2.isImm() || Op2.isExpr()) && 1950b57cec5SDimitry Andric "Second operand is neither an immediate nor an expression."); 1960b57cec5SDimitry Andric assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 1970b57cec5SDimitry Andric "Register immediate only supports addition operator"); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18); 2000b57cec5SDimitry Andric if (Op2.isImm()) { 2010b57cec5SDimitry Andric assert(isInt<16>(Op2.getImm()) && 2020b57cec5SDimitry Andric "Constant value truncated (limited to 16-bit)"); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric Encoding |= (Op2.getImm() & 0xffff); 2050b57cec5SDimitry Andric if (Op2.getImm() != 0) { 2060b57cec5SDimitry Andric if (LPAC::isPreOp(AluOp.getImm())) 2070b57cec5SDimitry Andric Encoding |= (0x3 << 16); 2080b57cec5SDimitry Andric if (LPAC::isPostOp(AluOp.getImm())) 2090b57cec5SDimitry Andric Encoding |= (0x1 << 16); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric } else 2120b57cec5SDimitry Andric getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric return Encoding; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric unsigned LanaiMCCodeEmitter::getRrMemoryOpValue( 2180b57cec5SDimitry Andric const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 2190b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 2200b57cec5SDimitry Andric unsigned Encoding; 2210b57cec5SDimitry Andric const MCOperand Op1 = Inst.getOperand(OpNo + 0); 2220b57cec5SDimitry Andric const MCOperand Op2 = Inst.getOperand(OpNo + 1); 2230b57cec5SDimitry Andric const MCOperand AluMCOp = Inst.getOperand(OpNo + 2); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric assert(Op1.isReg() && "First operand is not register."); 2260b57cec5SDimitry Andric Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15); 2270b57cec5SDimitry Andric assert(Op2.isReg() && "Second operand is not register."); 2280b57cec5SDimitry Andric Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric assert(AluMCOp.isImm() && "Third operator is not immediate."); 2310b57cec5SDimitry Andric // Set BBB 2320b57cec5SDimitry Andric unsigned AluOp = AluMCOp.getImm(); 2330b57cec5SDimitry Andric Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5; 2340b57cec5SDimitry Andric // Set P and Q 2350b57cec5SDimitry Andric if (LPAC::isPreOp(AluOp)) 2360b57cec5SDimitry Andric Encoding |= (0x3 << 8); 2370b57cec5SDimitry Andric if (LPAC::isPostOp(AluOp)) 2380b57cec5SDimitry Andric Encoding |= (0x1 << 8); 2390b57cec5SDimitry Andric // Set JJJJ 2400b57cec5SDimitry Andric switch (LPAC::getAluOp(AluOp)) { 2410b57cec5SDimitry Andric case LPAC::SHL: 2420b57cec5SDimitry Andric case LPAC::SRL: 2430b57cec5SDimitry Andric Encoding |= 0x10; 2440b57cec5SDimitry Andric break; 2450b57cec5SDimitry Andric case LPAC::SRA: 2460b57cec5SDimitry Andric Encoding |= 0x18; 2470b57cec5SDimitry Andric break; 2480b57cec5SDimitry Andric default: 2490b57cec5SDimitry Andric break; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric return Encoding; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric unsigned 2560b57cec5SDimitry Andric LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo, 2570b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2580b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 2590b57cec5SDimitry Andric unsigned Encoding; 2600b57cec5SDimitry Andric const MCOperand Op1 = Inst.getOperand(OpNo + 0); 2610b57cec5SDimitry Andric const MCOperand Op2 = Inst.getOperand(OpNo + 1); 2620b57cec5SDimitry Andric const MCOperand AluOp = Inst.getOperand(OpNo + 2); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric assert(Op1.isReg() && "First operand is not register."); 2650b57cec5SDimitry Andric assert((Op2.isImm() || Op2.isExpr()) && 2660b57cec5SDimitry Andric "Second operand is neither an immediate nor an expression."); 2670b57cec5SDimitry Andric assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 2680b57cec5SDimitry Andric "Register immediate only supports addition operator"); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12); 2710b57cec5SDimitry Andric if (Op2.isImm()) { 2720b57cec5SDimitry Andric assert(isInt<10>(Op2.getImm()) && 2730b57cec5SDimitry Andric "Constant value truncated (limited to 10-bit)"); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric Encoding |= (Op2.getImm() & 0x3ff); 2760b57cec5SDimitry Andric if (Op2.getImm() != 0) { 2770b57cec5SDimitry Andric if (LPAC::isPreOp(AluOp.getImm())) 2780b57cec5SDimitry Andric Encoding |= (0x3 << 10); 2790b57cec5SDimitry Andric if (LPAC::isPostOp(AluOp.getImm())) 2800b57cec5SDimitry Andric Encoding |= (0x1 << 10); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric } else 2830b57cec5SDimitry Andric getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric return Encoding; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric unsigned LanaiMCCodeEmitter::getBranchTargetOpValue( 2890b57cec5SDimitry Andric const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 2900b57cec5SDimitry Andric const MCSubtargetInfo &SubtargetInfo) const { 2910b57cec5SDimitry Andric const MCOperand &MCOp = Inst.getOperand(OpNo); 2920b57cec5SDimitry Andric if (MCOp.isReg() || MCOp.isImm()) 2930b57cec5SDimitry Andric return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo); 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric Fixups.push_back(MCFixup::create( 2960b57cec5SDimitry Andric 0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25))); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric return 0; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric #include "LanaiGenMCCodeEmitter.inc" 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric } // end namespace llvm 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric llvm::MCCodeEmitter * 3060b57cec5SDimitry Andric llvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo, 3070b57cec5SDimitry Andric MCContext &context) { 3080b57cec5SDimitry Andric return new LanaiMCCodeEmitter(InstrInfo, context); 3090b57cec5SDimitry Andric } 310