10b57cec5SDimitry Andric //===-- MSP430MCCodeEmitter.cpp - Convert MSP430 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 MSP430MCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MSP430.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MSP430MCTargetDesc.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/MSP430FixupKinds.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.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" 250b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 270b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 280b57cec5SDimitry Andric #include "llvm/Support/EndianStream.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric class MSP430MCCodeEmitter : public MCCodeEmitter { 360b57cec5SDimitry Andric MCContext &Ctx; 370b57cec5SDimitry Andric MCInstrInfo const &MCII; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // Offset keeps track of current word number being emitted 400b57cec5SDimitry Andric // inside a particular instruction. 410b57cec5SDimitry Andric mutable unsigned Offset; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// TableGen'erated function for getting the binary encoding for an 440b57cec5SDimitry Andric /// instruction. 450b57cec5SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 460b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 470b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// Returns the binary encoding of operands. 500b57cec5SDimitry Andric /// 510b57cec5SDimitry Andric /// If an operand requires relocation, the relocation is recorded 520b57cec5SDimitry Andric /// and zero is returned. 530b57cec5SDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 540b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 550b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric unsigned getMemOpValue(const MCInst &MI, unsigned Op, 580b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 590b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op, 620b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 630b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric unsigned getCGImmOpValue(const MCInst &MI, unsigned Op, 660b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 670b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric unsigned getCCOpValue(const MCInst &MI, unsigned Op, 700b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 710b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric public: 740b57cec5SDimitry Andric MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 750b57cec5SDimitry Andric : Ctx(ctx), MCII(MCII) {} 760b57cec5SDimitry Andric 7706c3fb27SDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 780b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 790b57cec5SDimitry Andric const MCSubtargetInfo &STI) const override; 800b57cec5SDimitry Andric }; 810b57cec5SDimitry Andric 8206c3fb27SDimitry Andric void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, 8306c3fb27SDimitry Andric SmallVectorImpl<char> &CB, 840b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 860b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 870b57cec5SDimitry Andric // Get byte count of instruction. 880b57cec5SDimitry Andric unsigned Size = Desc.getSize(); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // Initialize fixup offset 910b57cec5SDimitry Andric Offset = 2; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI); 940b57cec5SDimitry Andric size_t WordCount = Size / 2; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric while (WordCount--) { 97*5f757f3fSDimitry Andric support::endian::write(CB, (uint16_t)BinaryOpCode, 98*5f757f3fSDimitry Andric llvm::endianness::little); 990b57cec5SDimitry Andric BinaryOpCode >>= 16; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI, 1040b57cec5SDimitry Andric const MCOperand &MO, 1050b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1060b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1070b57cec5SDimitry Andric if (MO.isReg()) 1080b57cec5SDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric if (MO.isImm()) { 1110b57cec5SDimitry Andric Offset += 2; 1120b57cec5SDimitry Andric return MO.getImm(); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric assert(MO.isExpr() && "Expected expr operand"); 1160b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), 1170b57cec5SDimitry Andric static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc())); 1180b57cec5SDimitry Andric Offset += 2; 1190b57cec5SDimitry Andric return 0; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op, 1230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1250b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(Op); 1260b57cec5SDimitry Andric assert(MO1.isReg() && "Register operand expected"); 1270b57cec5SDimitry Andric unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg()); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(Op + 1); 1300b57cec5SDimitry Andric if (MO2.isImm()) { 1310b57cec5SDimitry Andric Offset += 2; 1320b57cec5SDimitry Andric return ((unsigned)MO2.getImm() << 4) | Reg; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric assert(MO2.isExpr() && "Expr operand expected"); 1360b57cec5SDimitry Andric MSP430::Fixups FixupKind; 1370b57cec5SDimitry Andric switch (Reg) { 1380b57cec5SDimitry Andric case 0: 1390b57cec5SDimitry Andric FixupKind = MSP430::fixup_16_pcrel_byte; 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric case 2: 1420b57cec5SDimitry Andric FixupKind = MSP430::fixup_16_byte; 1430b57cec5SDimitry Andric break; 1440b57cec5SDimitry Andric default: 1450b57cec5SDimitry Andric FixupKind = MSP430::fixup_16_byte; 1460b57cec5SDimitry Andric break; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(), 1490b57cec5SDimitry Andric static_cast<MCFixupKind>(FixupKind), MI.getLoc())); 1500b57cec5SDimitry Andric Offset += 2; 1510b57cec5SDimitry Andric return Reg; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op, 1550b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1560b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1570b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 1580b57cec5SDimitry Andric if (MO.isImm()) 1590b57cec5SDimitry Andric return MO.getImm(); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric assert(MO.isExpr() && "Expr operand expected"); 1620b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), 1630b57cec5SDimitry Andric static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc())); 1640b57cec5SDimitry Andric return 0; 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op, 1680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1700b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 1710b57cec5SDimitry Andric assert(MO.isImm() && "Expr operand expected"); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric int64_t Imm = MO.getImm(); 1740b57cec5SDimitry Andric switch (Imm) { 1750b57cec5SDimitry Andric default: 1760b57cec5SDimitry Andric llvm_unreachable("Invalid immediate value"); 1770b57cec5SDimitry Andric case 4: return 0x22; 1780b57cec5SDimitry Andric case 8: return 0x32; 1790b57cec5SDimitry Andric case 0: return 0x03; 1800b57cec5SDimitry Andric case 1: return 0x13; 1810b57cec5SDimitry Andric case 2: return 0x23; 1820b57cec5SDimitry Andric case -1: return 0x33; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op, 1870b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1880b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1890b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 1900b57cec5SDimitry Andric assert(MO.isImm() && "Immediate operand expected"); 1910b57cec5SDimitry Andric switch (MO.getImm()) { 1920b57cec5SDimitry Andric case MSP430CC::COND_NE: return 0; 1930b57cec5SDimitry Andric case MSP430CC::COND_E: return 1; 1940b57cec5SDimitry Andric case MSP430CC::COND_LO: return 2; 1950b57cec5SDimitry Andric case MSP430CC::COND_HS: return 3; 1960b57cec5SDimitry Andric case MSP430CC::COND_N: return 4; 1970b57cec5SDimitry Andric case MSP430CC::COND_GE: return 5; 1980b57cec5SDimitry Andric case MSP430CC::COND_L: return 6; 1990b57cec5SDimitry Andric default: 2000b57cec5SDimitry Andric llvm_unreachable("Unknown condition code"); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII, 2050b57cec5SDimitry Andric MCContext &Ctx) { 2060b57cec5SDimitry Andric return new MSP430MCCodeEmitter(Ctx, MCII); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric #include "MSP430GenMCCodeEmitter.inc" 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric } // end of namespace llvm 212