1303231Sdim//===-- LanaiMCCodeEmitter.cpp - Convert Lanai code to machine code -------===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// This file implements the LanaiMCCodeEmitter class. 10303231Sdim// 11303231Sdim//===----------------------------------------------------------------------===// 12303231Sdim 13353358Sdim#include "LanaiAluCode.h" 14303231Sdim#include "MCTargetDesc/LanaiBaseInfo.h" 15303231Sdim#include "MCTargetDesc/LanaiFixupKinds.h" 16303231Sdim#include "MCTargetDesc/LanaiMCExpr.h" 17314564Sdim#include "llvm/ADT/SmallVector.h" 18303231Sdim#include "llvm/ADT/Statistic.h" 19303231Sdim#include "llvm/MC/MCCodeEmitter.h" 20321369Sdim#include "llvm/MC/MCExpr.h" 21303231Sdim#include "llvm/MC/MCFixup.h" 22303231Sdim#include "llvm/MC/MCInst.h" 23303231Sdim#include "llvm/MC/MCInstrInfo.h" 24303231Sdim#include "llvm/MC/MCRegisterInfo.h" 25303231Sdim#include "llvm/MC/MCSubtargetInfo.h" 26314564Sdim#include "llvm/Support/Casting.h" 27303231Sdim#include "llvm/Support/raw_ostream.h" 28314564Sdim#include <cassert> 29314564Sdim#include <cstdint> 30303231Sdim 31303231Sdim#define DEBUG_TYPE "mccodeemitter" 32303231Sdim 33303231SdimSTATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 34303231Sdim 35303231Sdimnamespace llvm { 36314564Sdim 37303231Sdimnamespace { 38314564Sdim 39303231Sdimclass LanaiMCCodeEmitter : public MCCodeEmitter { 40303231Sdimpublic: 41314564Sdim LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) {} 42314564Sdim LanaiMCCodeEmitter(const LanaiMCCodeEmitter &) = delete; 43314564Sdim void operator=(const LanaiMCCodeEmitter &) = delete; 44314564Sdim ~LanaiMCCodeEmitter() override = default; 45303231Sdim 46303231Sdim // The functions below are called by TableGen generated functions for getting 47303231Sdim // the binary encoding of instructions/opereands. 48303231Sdim 49303231Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 50303231Sdim // binary encoding for an instruction. 51303231Sdim uint64_t getBinaryCodeForInstr(const MCInst &Inst, 52303231Sdim SmallVectorImpl<MCFixup> &Fixups, 53303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 54303231Sdim 55303231Sdim // getMachineOpValue - Return binary encoding of operand. If the machine 56303231Sdim // operand requires relocation, record the relocation and return zero. 57303231Sdim unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp, 58303231Sdim SmallVectorImpl<MCFixup> &Fixups, 59303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 60303231Sdim 61303231Sdim unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo, 62303231Sdim SmallVectorImpl<MCFixup> &Fixups, 63303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 64303231Sdim 65303231Sdim unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo, 66303231Sdim SmallVectorImpl<MCFixup> &Fixups, 67303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 68303231Sdim 69303231Sdim unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo, 70303231Sdim SmallVectorImpl<MCFixup> &Fixups, 71303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 72303231Sdim 73303231Sdim unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo, 74303231Sdim SmallVectorImpl<MCFixup> &Fixups, 75303231Sdim const MCSubtargetInfo &SubtargetInfo) const; 76303231Sdim 77303231Sdim void encodeInstruction(const MCInst &Inst, raw_ostream &Ostream, 78303231Sdim SmallVectorImpl<MCFixup> &Fixups, 79303231Sdim const MCSubtargetInfo &SubtargetInfo) const override; 80303231Sdim 81303231Sdim unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 82303231Sdim const MCSubtargetInfo &STI) const; 83303231Sdim 84303231Sdim unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 85303231Sdim const MCSubtargetInfo &STI) const; 86303231Sdim}; 87303231Sdim 88314564Sdim} // end anonymous namespace 89314564Sdim 90321369Sdimstatic Lanai::Fixups FixupKind(const MCExpr *Expr) { 91303231Sdim if (isa<MCSymbolRefExpr>(Expr)) 92303231Sdim return Lanai::FIXUP_LANAI_21; 93303231Sdim if (const LanaiMCExpr *McExpr = dyn_cast<LanaiMCExpr>(Expr)) { 94303231Sdim LanaiMCExpr::VariantKind ExprKind = McExpr->getKind(); 95303231Sdim switch (ExprKind) { 96303231Sdim case LanaiMCExpr::VK_Lanai_None: 97303231Sdim return Lanai::FIXUP_LANAI_21; 98303231Sdim case LanaiMCExpr::VK_Lanai_ABS_HI: 99303231Sdim return Lanai::FIXUP_LANAI_HI16; 100303231Sdim case LanaiMCExpr::VK_Lanai_ABS_LO: 101303231Sdim return Lanai::FIXUP_LANAI_LO16; 102303231Sdim } 103303231Sdim } 104303231Sdim return Lanai::Fixups(0); 105303231Sdim} 106303231Sdim 107303231Sdim// getMachineOpValue - Return binary encoding of operand. If the machine 108303231Sdim// operand requires relocation, record the relocation and return zero. 109303231Sdimunsigned LanaiMCCodeEmitter::getMachineOpValue( 110303231Sdim const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups, 111303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 112303231Sdim if (MCOp.isReg()) 113303231Sdim return getLanaiRegisterNumbering(MCOp.getReg()); 114303231Sdim if (MCOp.isImm()) 115303231Sdim return static_cast<unsigned>(MCOp.getImm()); 116303231Sdim 117303231Sdim // MCOp must be an expression 118303231Sdim assert(MCOp.isExpr()); 119303231Sdim const MCExpr *Expr = MCOp.getExpr(); 120303231Sdim 121303231Sdim // Extract the symbolic reference side of a binary expression. 122303231Sdim if (Expr->getKind() == MCExpr::Binary) { 123303231Sdim const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr); 124303231Sdim Expr = BinaryExpr->getLHS(); 125303231Sdim } 126303231Sdim 127303231Sdim assert(isa<LanaiMCExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef); 128303231Sdim // Push fixup (all info is contained within) 129303231Sdim Fixups.push_back( 130303231Sdim MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr)))); 131303231Sdim return 0; 132303231Sdim} 133303231Sdim 134303231Sdim// Helper function to adjust P and Q bits on load and store instructions. 135321369Sdimstatic unsigned adjustPqBits(const MCInst &Inst, unsigned Value, 136321369Sdim unsigned PBitShift, unsigned QBitShift) { 137303231Sdim const MCOperand AluOp = Inst.getOperand(3); 138303231Sdim unsigned AluCode = AluOp.getImm(); 139303231Sdim 140303231Sdim // Set the P bit to one iff the immediate is nonzero and not a post-op 141303231Sdim // instruction. 142303231Sdim const MCOperand Op2 = Inst.getOperand(2); 143303231Sdim Value &= ~(1 << PBitShift); 144303231Sdim if (!LPAC::isPostOp(AluCode) && 145303231Sdim ((Op2.isImm() && Op2.getImm() != 0) || 146303231Sdim (Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr()))) 147303231Sdim Value |= (1 << PBitShift); 148303231Sdim 149303231Sdim // Set the Q bit to one iff it is a post- or pre-op instruction. 150303231Sdim assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && 151303231Sdim "Expected register operand."); 152303231Sdim Value &= ~(1 << QBitShift); 153303231Sdim if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) || 154303231Sdim (Op2.isReg() && Op2.getReg() != Lanai::R0))) 155303231Sdim Value |= (1 << QBitShift); 156303231Sdim 157303231Sdim return Value; 158303231Sdim} 159303231Sdim 160303231Sdimunsigned 161303231SdimLanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 162303231Sdim const MCSubtargetInfo &STI) const { 163303231Sdim return adjustPqBits(Inst, Value, 17, 16); 164303231Sdim} 165303231Sdim 166303231Sdimunsigned 167303231SdimLanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 168303231Sdim const MCSubtargetInfo &STI) const { 169303231Sdim return adjustPqBits(Inst, Value, 11, 10); 170303231Sdim} 171303231Sdim 172303231Sdimvoid LanaiMCCodeEmitter::encodeInstruction( 173303231Sdim const MCInst &Inst, raw_ostream &Ostream, SmallVectorImpl<MCFixup> &Fixups, 174303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 175303231Sdim // Get instruction encoding and emit it 176303231Sdim unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo); 177303231Sdim ++MCNumEmitted; // Keep track of the number of emitted insns. 178303231Sdim 179303231Sdim // Emit bytes in big-endian 180303231Sdim for (int i = (4 - 1) * 8; i >= 0; i -= 8) 181303231Sdim Ostream << static_cast<char>((Value >> i) & 0xff); 182303231Sdim} 183303231Sdim 184303231Sdim// Encode Lanai Memory Operand 185303231Sdimunsigned LanaiMCCodeEmitter::getRiMemoryOpValue( 186303231Sdim const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 187303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 188303231Sdim unsigned Encoding; 189303231Sdim const MCOperand Op1 = Inst.getOperand(OpNo + 0); 190303231Sdim const MCOperand Op2 = Inst.getOperand(OpNo + 1); 191303231Sdim const MCOperand AluOp = Inst.getOperand(OpNo + 2); 192303231Sdim 193303231Sdim assert(Op1.isReg() && "First operand is not register."); 194303231Sdim assert((Op2.isImm() || Op2.isExpr()) && 195303231Sdim "Second operand is neither an immediate nor an expression."); 196303231Sdim assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 197303231Sdim "Register immediate only supports addition operator"); 198303231Sdim 199303231Sdim Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18); 200303231Sdim if (Op2.isImm()) { 201303231Sdim assert(isInt<16>(Op2.getImm()) && 202303231Sdim "Constant value truncated (limited to 16-bit)"); 203303231Sdim 204303231Sdim Encoding |= (Op2.getImm() & 0xffff); 205303231Sdim if (Op2.getImm() != 0) { 206303231Sdim if (LPAC::isPreOp(AluOp.getImm())) 207303231Sdim Encoding |= (0x3 << 16); 208303231Sdim if (LPAC::isPostOp(AluOp.getImm())) 209303231Sdim Encoding |= (0x1 << 16); 210303231Sdim } 211303231Sdim } else 212303231Sdim getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 213303231Sdim 214303231Sdim return Encoding; 215303231Sdim} 216303231Sdim 217303231Sdimunsigned LanaiMCCodeEmitter::getRrMemoryOpValue( 218303231Sdim const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 219303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 220303231Sdim unsigned Encoding; 221303231Sdim const MCOperand Op1 = Inst.getOperand(OpNo + 0); 222303231Sdim const MCOperand Op2 = Inst.getOperand(OpNo + 1); 223303231Sdim const MCOperand AluMCOp = Inst.getOperand(OpNo + 2); 224303231Sdim 225303231Sdim assert(Op1.isReg() && "First operand is not register."); 226303231Sdim Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15); 227303231Sdim assert(Op2.isReg() && "Second operand is not register."); 228303231Sdim Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10); 229303231Sdim 230303231Sdim assert(AluMCOp.isImm() && "Third operator is not immediate."); 231303231Sdim // Set BBB 232303231Sdim unsigned AluOp = AluMCOp.getImm(); 233303231Sdim Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5; 234303231Sdim // Set P and Q 235303231Sdim if (LPAC::isPreOp(AluOp)) 236303231Sdim Encoding |= (0x3 << 8); 237303231Sdim if (LPAC::isPostOp(AluOp)) 238303231Sdim Encoding |= (0x1 << 8); 239303231Sdim // Set JJJJ 240303231Sdim switch (LPAC::getAluOp(AluOp)) { 241303231Sdim case LPAC::SHL: 242303231Sdim case LPAC::SRL: 243303231Sdim Encoding |= 0x10; 244303231Sdim break; 245303231Sdim case LPAC::SRA: 246303231Sdim Encoding |= 0x18; 247303231Sdim break; 248303231Sdim default: 249303231Sdim break; 250303231Sdim } 251303231Sdim 252303231Sdim return Encoding; 253303231Sdim} 254303231Sdim 255303231Sdimunsigned 256303231SdimLanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo, 257303231Sdim SmallVectorImpl<MCFixup> &Fixups, 258303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 259303231Sdim unsigned Encoding; 260303231Sdim const MCOperand Op1 = Inst.getOperand(OpNo + 0); 261303231Sdim const MCOperand Op2 = Inst.getOperand(OpNo + 1); 262303231Sdim const MCOperand AluOp = Inst.getOperand(OpNo + 2); 263303231Sdim 264303231Sdim assert(Op1.isReg() && "First operand is not register."); 265303231Sdim assert((Op2.isImm() || Op2.isExpr()) && 266303231Sdim "Second operand is neither an immediate nor an expression."); 267303231Sdim assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 268303231Sdim "Register immediate only supports addition operator"); 269303231Sdim 270303231Sdim Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12); 271303231Sdim if (Op2.isImm()) { 272303231Sdim assert(isInt<10>(Op2.getImm()) && 273303231Sdim "Constant value truncated (limited to 10-bit)"); 274303231Sdim 275303231Sdim Encoding |= (Op2.getImm() & 0x3ff); 276303231Sdim if (Op2.getImm() != 0) { 277303231Sdim if (LPAC::isPreOp(AluOp.getImm())) 278303231Sdim Encoding |= (0x3 << 10); 279303231Sdim if (LPAC::isPostOp(AluOp.getImm())) 280303231Sdim Encoding |= (0x1 << 10); 281303231Sdim } 282303231Sdim } else 283303231Sdim getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 284303231Sdim 285303231Sdim return Encoding; 286303231Sdim} 287303231Sdim 288303231Sdimunsigned LanaiMCCodeEmitter::getBranchTargetOpValue( 289303231Sdim const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 290303231Sdim const MCSubtargetInfo &SubtargetInfo) const { 291303231Sdim const MCOperand &MCOp = Inst.getOperand(OpNo); 292303231Sdim if (MCOp.isReg() || MCOp.isImm()) 293303231Sdim return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo); 294303231Sdim 295303231Sdim Fixups.push_back(MCFixup::create( 296303231Sdim 0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25))); 297303231Sdim 298303231Sdim return 0; 299303231Sdim} 300303231Sdim 301303231Sdim#include "LanaiGenMCCodeEmitter.inc" 302303231Sdim 303314564Sdim} // end namespace llvm 304314564Sdim 305303231Sdimllvm::MCCodeEmitter * 306303231Sdimllvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo, 307303231Sdim const MCRegisterInfo & /*MRI*/, 308303231Sdim MCContext &context) { 309303231Sdim return new LanaiMCCodeEmitter(InstrInfo, context); 310303231Sdim} 311