10b57cec5SDimitry Andric //===-- AVRMCCodeEmitter.cpp - Convert AVR 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 AVRMCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "AVRMCCodeEmitter.h" 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCExpr.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.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/Casting.h" 28480093f4SDimitry 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 #define GET_INSTRMAP_INFO 340b57cec5SDimitry Andric #include "AVRGenInstrInfo.inc" 350b57cec5SDimitry Andric #undef GET_INSTRMAP_INFO 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric namespace llvm { 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// Performs a post-encoding step on a `LD` or `ST` instruction. 400b57cec5SDimitry Andric /// 410b57cec5SDimitry Andric /// The encoding of the LD/ST family of instructions is inconsistent w.r.t 420b57cec5SDimitry Andric /// the pointer register and the addressing mode. 430b57cec5SDimitry Andric /// 440b57cec5SDimitry Andric /// The permutations of the format are as followed: 450b57cec5SDimitry Andric /// ld Rd, X `1001 000d dddd 1100` 460b57cec5SDimitry Andric /// ld Rd, X+ `1001 000d dddd 1101` 470b57cec5SDimitry Andric /// ld Rd, -X `1001 000d dddd 1110` 480b57cec5SDimitry Andric /// 490b57cec5SDimitry Andric /// ld Rd, Y `1000 000d dddd 1000` 500b57cec5SDimitry Andric /// ld Rd, Y+ `1001 000d dddd 1001` 510b57cec5SDimitry Andric /// ld Rd, -Y `1001 000d dddd 1010` 520b57cec5SDimitry Andric /// 530b57cec5SDimitry Andric /// ld Rd, Z `1000 000d dddd 0000` 540b57cec5SDimitry Andric /// ld Rd, Z+ `1001 000d dddd 0001` 550b57cec5SDimitry Andric /// ld Rd, -Z `1001 000d dddd 0010` 560b57cec5SDimitry Andric /// ^ 570b57cec5SDimitry Andric /// | 580b57cec5SDimitry Andric /// Note this one inconsistent bit - it is 1 sometimes and 0 at other times. 590b57cec5SDimitry Andric /// There is no logical pattern. Looking at a truth table, the following 600b57cec5SDimitry Andric /// formula can be derived to fit the pattern: 610b57cec5SDimitry Andric // 620b57cec5SDimitry Andric /// ``` 630b57cec5SDimitry Andric /// inconsistent_bit = is_predec OR is_postinc OR is_reg_x 640b57cec5SDimitry Andric /// ``` 650b57cec5SDimitry Andric // 660b57cec5SDimitry Andric /// We manually set this bit in this post encoder method. 670b57cec5SDimitry Andric unsigned 680b57cec5SDimitry Andric AVRMCCodeEmitter::loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue, 690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg() && 720b57cec5SDimitry Andric "the load/store operands must be registers"); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // check whether either of the registers are the X pointer register. 770b57cec5SDimitry Andric bool IsRegX = MI.getOperand(0).getReg() == AVR::R27R26 || 780b57cec5SDimitry Andric MI.getOperand(1).getReg() == AVR::R27R26; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric bool IsPredec = Opcode == AVR::LDRdPtrPd || Opcode == AVR::STPtrPdRr; 810b57cec5SDimitry Andric bool IsPostinc = Opcode == AVR::LDRdPtrPi || Opcode == AVR::STPtrPiRr; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // Check if we need to set the inconsistent bit 840b57cec5SDimitry Andric if (IsRegX || IsPredec || IsPostinc) { 850b57cec5SDimitry Andric EncodedValue |= (1 << 12); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric return EncodedValue; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric template <AVR::Fixups Fixup> 920b57cec5SDimitry Andric unsigned 930b57cec5SDimitry Andric AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo, 940b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 950b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 960b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric if (MO.isExpr()) { 99349cc55cSDimitry Andric Fixups.push_back( 100349cc55cSDimitry Andric MCFixup::create(0, MO.getExpr(), MCFixupKind(Fixup), MI.getLoc())); 1010b57cec5SDimitry Andric return 0; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric assert(MO.isImm()); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Take the size of the current instruction away. 1070b57cec5SDimitry Andric // With labels, this is implicitly done. 1080b57cec5SDimitry Andric auto target = MO.getImm(); 1090b57cec5SDimitry Andric AVR::fixups::adjustBranchTarget(target); 1100b57cec5SDimitry Andric return target; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo, 1140b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1150b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1160b57cec5SDimitry Andric auto MO = MI.getOperand(OpNo); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // The operand should be a pointer register. 1190b57cec5SDimitry Andric assert(MO.isReg()); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric switch (MO.getReg()) { 122349cc55cSDimitry Andric case AVR::R27R26: 123349cc55cSDimitry Andric return 0x03; // X: 0b11 124349cc55cSDimitry Andric case AVR::R29R28: 125349cc55cSDimitry Andric return 0x02; // Y: 0b10 126349cc55cSDimitry Andric case AVR::R31R30: 127349cc55cSDimitry Andric return 0x00; // Z: 0b00 1280b57cec5SDimitry Andric default: 1290b57cec5SDimitry Andric llvm_unreachable("invalid pointer register"); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric /// Encodes a `memri` operand. 1340b57cec5SDimitry Andric /// The operand is 7-bits. 1350b57cec5SDimitry Andric /// * The lower 6 bits is the immediate 1360b57cec5SDimitry Andric /// * The upper bit is the pointer register bit (Z=0,Y=1) 1370b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::encodeMemri(const MCInst &MI, unsigned OpNo, 1380b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1390b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1400b57cec5SDimitry Andric auto RegOp = MI.getOperand(OpNo); 1410b57cec5SDimitry Andric auto OffsetOp = MI.getOperand(OpNo + 1); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric assert(RegOp.isReg() && "Expected register operand"); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric uint8_t RegBit = 0; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric switch (RegOp.getReg()) { 1480b57cec5SDimitry Andric default: 14906c3fb27SDimitry Andric Ctx.reportError(MI.getLoc(), "Expected either Y or Z register"); 15006c3fb27SDimitry Andric return 0; 1510b57cec5SDimitry Andric case AVR::R31R30: 1520b57cec5SDimitry Andric RegBit = 0; 1530b57cec5SDimitry Andric break; // Z register 1540b57cec5SDimitry Andric case AVR::R29R28: 1550b57cec5SDimitry Andric RegBit = 1; 1560b57cec5SDimitry Andric break; // Y register 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric int8_t OffsetBits; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric if (OffsetOp.isImm()) { 1620b57cec5SDimitry Andric OffsetBits = OffsetOp.getImm(); 1630b57cec5SDimitry Andric } else if (OffsetOp.isExpr()) { 1640b57cec5SDimitry Andric OffsetBits = 0; 1650b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, OffsetOp.getExpr(), 1660b57cec5SDimitry Andric MCFixupKind(AVR::fixup_6), MI.getLoc())); 1670b57cec5SDimitry Andric } else { 16806c3fb27SDimitry Andric llvm_unreachable("Invalid value for offset"); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric return (RegBit << 6) | OffsetBits; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::encodeComplement(const MCInst &MI, unsigned OpNo, 1750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1760b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1770b57cec5SDimitry Andric // The operand should be an immediate. 1780b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isImm()); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric auto Imm = MI.getOperand(OpNo).getImm(); 1810b57cec5SDimitry Andric return (~0) - Imm; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric template <AVR::Fixups Fixup, unsigned Offset> 1850b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::encodeImm(const MCInst &MI, unsigned OpNo, 1860b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1870b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 1880b57cec5SDimitry Andric auto MO = MI.getOperand(OpNo); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric if (MO.isExpr()) { 1910b57cec5SDimitry Andric if (isa<AVRMCExpr>(MO.getExpr())) { 1920b57cec5SDimitry Andric // If the expression is already an AVRMCExpr (i.e. a lo8(symbol), 1930b57cec5SDimitry Andric // we shouldn't perform any more fixups. Without this check, we would 1940b57cec5SDimitry Andric // instead create a fixup to the symbol named 'lo8(symbol)' which 1950b57cec5SDimitry Andric // is not correct. 1960b57cec5SDimitry Andric return getExprOpValue(MO.getExpr(), Fixups, STI); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric MCFixupKind FixupKind = static_cast<MCFixupKind>(Fixup); 200349cc55cSDimitry Andric Fixups.push_back( 201349cc55cSDimitry Andric MCFixup::create(Offset, MO.getExpr(), FixupKind, MI.getLoc())); 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric return 0; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric assert(MO.isImm()); 2070b57cec5SDimitry Andric return MO.getImm(); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::encodeCallTarget(const MCInst &MI, unsigned OpNo, 2110b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2120b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2130b57cec5SDimitry Andric auto MO = MI.getOperand(OpNo); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric if (MO.isExpr()) { 2160b57cec5SDimitry Andric MCFixupKind FixupKind = static_cast<MCFixupKind>(AVR::fixup_call); 2170b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), FixupKind, MI.getLoc())); 2180b57cec5SDimitry Andric return 0; 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric assert(MO.isImm()); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric auto Target = MO.getImm(); 2240b57cec5SDimitry Andric AVR::fixups::adjustBranchTarget(Target); 2250b57cec5SDimitry Andric return Target; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::getExprOpValue(const MCExpr *Expr, 2290b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2300b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric MCExpr::ExprKind Kind = Expr->getKind(); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric if (Kind == MCExpr::Binary) { 2350b57cec5SDimitry Andric Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS(); 2360b57cec5SDimitry Andric Kind = Expr->getKind(); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric if (Kind == MCExpr::Target) { 2400b57cec5SDimitry Andric AVRMCExpr const *AVRExpr = cast<AVRMCExpr>(Expr); 2410b57cec5SDimitry Andric int64_t Result; 2420b57cec5SDimitry Andric if (AVRExpr->evaluateAsConstant(Result)) { 2430b57cec5SDimitry Andric return Result; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric MCFixupKind FixupKind = static_cast<MCFixupKind>(AVRExpr->getFixupKind()); 2470b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, AVRExpr, FixupKind)); 2480b57cec5SDimitry Andric return 0; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric assert(Kind == MCExpr::SymbolRef); 2520b57cec5SDimitry Andric return 0; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI, 2560b57cec5SDimitry Andric const MCOperand &MO, 2570b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2580b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 259349cc55cSDimitry Andric if (MO.isReg()) 260349cc55cSDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 261349cc55cSDimitry Andric if (MO.isImm()) 262349cc55cSDimitry Andric return static_cast<unsigned>(MO.getImm()); 2630b57cec5SDimitry Andric 264fe6060f1SDimitry Andric if (MO.isDFPImm()) 265fe6060f1SDimitry Andric return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm())); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric // MO must be an Expr. 2680b57cec5SDimitry Andric assert(MO.isExpr()); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric return getExprOpValue(MO.getExpr(), Fixups, STI); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 27306c3fb27SDimitry Andric void AVRMCCodeEmitter::encodeInstruction(const MCInst &MI, 27406c3fb27SDimitry Andric SmallVectorImpl<char> &CB, 2750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2760b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2770b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Get byte count of instruction 2800b57cec5SDimitry Andric unsigned Size = Desc.getSize(); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric assert(Size > 0 && "Instruction size cannot be zero"); 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI); 28506c3fb27SDimitry Andric 28606c3fb27SDimitry Andric for (int64_t i = Size / 2 - 1; i >= 0; --i) { 28706c3fb27SDimitry Andric uint16_t Word = (BinaryOpCode >> (i * 16)) & 0xFFFF; 288*5f757f3fSDimitry Andric support::endian::write(CB, Word, llvm::endianness::little); 28906c3fb27SDimitry Andric } 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII, 2930b57cec5SDimitry Andric MCContext &Ctx) { 2940b57cec5SDimitry Andric return new AVRMCCodeEmitter(MCII, Ctx); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric #include "AVRGenMCCodeEmitter.inc" 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric } // end of namespace llvm 300