Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
35295 views
//===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===//1//2// The LLVM Compiler Infrastructure3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9//10// This file implements the XtensaMCCodeEmitter class.11//12//===----------------------------------------------------------------------===//1314#include "MCTargetDesc/XtensaFixupKinds.h"15#include "MCTargetDesc/XtensaMCExpr.h"16#include "MCTargetDesc/XtensaMCTargetDesc.h"17#include "llvm/MC/MCCodeEmitter.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCExpr.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCRegisterInfo.h"2324#define GET_INSTRMAP_INFO25#include "XtensaGenInstrInfo.inc"26#undef GET_INSTRMAP_INFO2728using namespace llvm;2930#define DEBUG_TYPE "mccodeemitter"3132namespace {33class XtensaMCCodeEmitter : public MCCodeEmitter {34const MCInstrInfo &MCII;35MCContext &Ctx;36bool IsLittleEndian;3738public:39XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE)40: MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {}4142~XtensaMCCodeEmitter() {}4344// OVerride MCCodeEmitter.45void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,46SmallVectorImpl<MCFixup> &Fixups,47const MCSubtargetInfo &STI) const override;4849private:50// Automatically generated by TableGen.51uint64_t getBinaryCodeForInstr(const MCInst &MI,52SmallVectorImpl<MCFixup> &Fixups,53const MCSubtargetInfo &STI) const;5455// Called by the TableGen code to get the binary encoding of operand56// MO in MI. Fixups is the list of fixups against MI.57uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,58SmallVectorImpl<MCFixup> &Fixups,59const MCSubtargetInfo &STI) const;6061uint32_t getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,62SmallVectorImpl<MCFixup> &Fixups,63const MCSubtargetInfo &STI) const;6465uint32_t getBranchTargetEncoding(const MCInst &MI, unsigned int OpNum,66SmallVectorImpl<MCFixup> &Fixups,67const MCSubtargetInfo &STI) const;6869uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,70SmallVectorImpl<MCFixup> &Fixups,71const MCSubtargetInfo &STI) const;7273uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,74SmallVectorImpl<MCFixup> &Fixups,75const MCSubtargetInfo &STI) const;7677uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,78SmallVectorImpl<MCFixup> &Fixups,79const MCSubtargetInfo &STI) const;8081uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,82SmallVectorImpl<MCFixup> &Fixups,83const MCSubtargetInfo &STI) const;8485uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,86SmallVectorImpl<MCFixup> &Fixups,87const MCSubtargetInfo &STI) const;8889uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,90SmallVectorImpl<MCFixup> &Fixups,91const MCSubtargetInfo &STI) const;9293uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,94SmallVectorImpl<MCFixup> &Fixups,95const MCSubtargetInfo &STI) const;9697uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,98SmallVectorImpl<MCFixup> &Fixups,99const MCSubtargetInfo &STI) const;100101uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo,102SmallVectorImpl<MCFixup> &Fixups,103const MCSubtargetInfo &STI) const;104105uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,106SmallVectorImpl<MCFixup> &Fixups,107const MCSubtargetInfo &STI) const;108109uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,110SmallVectorImpl<MCFixup> &Fixups,111const MCSubtargetInfo &STI) const;112113uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,114SmallVectorImpl<MCFixup> &Fixups,115const MCSubtargetInfo &STI) const;116};117} // namespace118119MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII,120MCContext &Ctx) {121return new XtensaMCCodeEmitter(MCII, Ctx, true);122}123124void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,125SmallVectorImpl<char> &CB,126SmallVectorImpl<MCFixup> &Fixups,127const MCSubtargetInfo &STI) const {128uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);129unsigned Size = MCII.get(MI.getOpcode()).getSize();130131if (IsLittleEndian) {132// Little-endian insertion of Size bytes.133unsigned ShiftValue = 0;134for (unsigned I = 0; I != Size; ++I) {135CB.push_back(char(Bits >> ShiftValue));136ShiftValue += 8;137}138} else {139// TODO Big-endian insertion of Size bytes.140report_fatal_error("Big-endian mode currently is not supported!");141}142}143144uint32_t145XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,146SmallVectorImpl<MCFixup> &Fixups,147const MCSubtargetInfo &STI) const {148if (MO.isReg())149return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());150if (MO.isImm()) {151uint32_t Res = static_cast<uint32_t>(MO.getImm());152return Res;153}154155report_fatal_error("Unhandled expression!");156return 0;157}158159uint32_t160XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,161SmallVectorImpl<MCFixup> &Fixups,162const MCSubtargetInfo &STI) const {163const MCOperand &MO = MI.getOperand(OpNum);164165if (MO.isImm())166return MO.getImm();167168const MCExpr *Expr = MO.getExpr();169Fixups.push_back(MCFixup::create(1700, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));171return 0;172}173174uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(175const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,176const MCSubtargetInfo &STI) const {177const MCOperand &MO = MI.getOperand(OpNum);178if (MO.isImm())179return static_cast<uint32_t>(MO.getImm());180181const MCExpr *Expr = MO.getExpr();182switch (MI.getOpcode()) {183case Xtensa::BEQZ:184case Xtensa::BGEZ:185case Xtensa::BLTZ:186case Xtensa::BNEZ:187Fixups.push_back(MCFixup::create(1880, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));189return 0;190default:191Fixups.push_back(MCFixup::create(1920, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));193return 0;194}195}196197uint32_t198XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,199SmallVectorImpl<MCFixup> &Fixups,200const MCSubtargetInfo &STI) const {201const MCOperand &MO = MI.getOperand(OpNum);202if (MO.isImm()) {203int32_t Res = MO.getImm();204if (Res & 0x3) {205llvm_unreachable("Unexpected operand value!");206}207Res >>= 2;208return Res;209}210211assert((MO.isExpr()) && "Unexpected operand value!");212const MCExpr *Expr = MO.getExpr();213Fixups.push_back(MCFixup::create(2140, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));215return 0;216}217218uint32_t219XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,220SmallVectorImpl<MCFixup> &Fixups,221const MCSubtargetInfo &STI) const {222const MCOperand &MO = MI.getOperand(OpNum);223if (MO.isImm()) {224int32_t Res = MO.getImm();225// We don't check first 2 bits, because in these bits we could store first 2226// bits of instruction address227Res >>= 2;228return Res;229}230231assert((MO.isExpr()) && "Unexpected operand value!");232233Fixups.push_back(MCFixup::create(2340, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc()));235return 0;236}237238uint32_t239XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,240SmallVectorImpl<MCFixup> &Fixups,241const MCSubtargetInfo &STI) const {242assert(MI.getOperand(OpNo + 1).isImm());243244uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());245246switch (MI.getOpcode()) {247case Xtensa::S16I:248case Xtensa::L16SI:249case Xtensa::L16UI:250if (Res & 0x1) {251report_fatal_error("Unexpected operand value!");252}253Res >>= 1;254break;255case Xtensa::S32I:256case Xtensa::L32I:257if (Res & 0x3) {258report_fatal_error("Unexpected operand value!");259}260Res >>= 2;261break;262}263264assert((isUInt<8>(Res)) && "Unexpected operand value!");265266uint32_t OffBits = Res << 4;267uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);268269return ((OffBits & 0xFF0) | RegBits);270}271272uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,273SmallVectorImpl<MCFixup> &Fixups,274const MCSubtargetInfo &STI) const {275const MCOperand &MO = MI.getOperand(OpNo);276int32_t Res = MO.getImm();277278assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");279280return (Res & 0xff);281}282283uint32_t284XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,285SmallVectorImpl<MCFixup> &Fixups,286const MCSubtargetInfo &STI) const {287const MCOperand &MO = MI.getOperand(OpNo);288int32_t Res = MO.getImm();289290assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&291"Unexpected operand value!");292293return (Res & 0xffff);294}295296uint32_t297XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,298SmallVectorImpl<MCFixup> &Fixups,299const MCSubtargetInfo &STI) const {300const MCOperand &MO = MI.getOperand(OpNo);301int32_t Res = MO.getImm();302303assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");304305return (Res & 0xfff);306}307308uint32_t309XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,310SmallVectorImpl<MCFixup> &Fixups,311const MCSubtargetInfo &STI) const {312const MCOperand &MO = MI.getOperand(OpNo);313uint32_t Res = static_cast<uint32_t>(MO.getImm());314315assert((Res <= 15) && "Unexpected operand value!");316317return Res & 0xf;318}319320uint32_t321XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,322SmallVectorImpl<MCFixup> &Fixups,323const MCSubtargetInfo &STI) const {324const MCOperand &MO = MI.getOperand(OpNo);325uint32_t Res = static_cast<uint32_t>(MO.getImm());326327assert((Res <= 31) && "Unexpected operand value!");328329return (Res & 0x1f);330}331332uint32_t333XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,334SmallVectorImpl<MCFixup> &Fixups,335const MCSubtargetInfo &STI) const {336const MCOperand &MO = MI.getOperand(OpNo);337uint32_t Res = static_cast<uint32_t>(MO.getImm());338339assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");340341return ((32 - Res) & 0x1f);342}343344uint32_t345XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,346SmallVectorImpl<MCFixup> &Fixups,347const MCSubtargetInfo &STI) const {348const MCOperand &MO = MI.getOperand(OpNo);349uint32_t Res = static_cast<uint32_t>(MO.getImm());350351assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");352353return (Res - 1);354}355356uint32_t357XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,358SmallVectorImpl<MCFixup> &Fixups,359const MCSubtargetInfo &STI) const {360const MCOperand &MO = MI.getOperand(OpNo);361uint32_t Res = static_cast<uint32_t>(MO.getImm());362363switch (Res) {364case 0xffffffff:365Res = 0;366break;367case 1:368case 2:369case 3:370case 4:371case 5:372case 6:373case 7:374case 8:375break;376case 10:377Res = 9;378break;379case 12:380Res = 10;381break;382case 16:383Res = 11;384break;385case 32:386Res = 12;387break;388case 64:389Res = 13;390break;391case 128:392Res = 14;393break;394case 256:395Res = 15;396break;397default:398llvm_unreachable("Unexpected operand value!");399}400401return Res;402}403404uint32_t405XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,406SmallVectorImpl<MCFixup> &Fixups,407const MCSubtargetInfo &STI) const {408const MCOperand &MO = MI.getOperand(OpNo);409uint32_t Res = static_cast<uint32_t>(MO.getImm());410411switch (Res) {412case 32768:413Res = 0;414break;415case 65536:416Res = 1;417break;418case 2:419case 3:420case 4:421case 5:422case 6:423case 7:424case 8:425break;426case 10:427Res = 9;428break;429case 12:430Res = 10;431break;432case 16:433Res = 11;434break;435case 32:436Res = 12;437break;438case 64:439Res = 13;440break;441case 128:442Res = 14;443break;444case 256:445Res = 15;446break;447default:448llvm_unreachable("Unexpected operand value!");449}450451return Res;452}453#include "XtensaGenMCCodeEmitter.inc"454455456