Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
35294 views
//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the MipsMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "MipsMCCodeEmitter.h"13#include "MCTargetDesc/MipsFixupKinds.h"14#include "MCTargetDesc/MipsMCExpr.h"15#include "MCTargetDesc/MipsMCTargetDesc.h"16#include "llvm/ADT/APFloat.h"17#include "llvm/ADT/APInt.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCExpr.h"21#include "llvm/MC/MCFixup.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstrDesc.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCRegisterInfo.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/EndianStream.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/raw_ostream.h"31#include <cassert>32#include <cstdint>3334using namespace llvm;3536#define DEBUG_TYPE "mccodeemitter"3738#define GET_INSTRMAP_INFO39#include "MipsGenInstrInfo.inc"40#undef GET_INSTRMAP_INFO4142namespace llvm {4344MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,45MCContext &Ctx) {46return new MipsMCCodeEmitter(MCII, Ctx, false);47}4849MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,50MCContext &Ctx) {51return new MipsMCCodeEmitter(MCII, Ctx, true);52}5354} // end namespace llvm5556// If the D<shift> instruction has a shift amount that is greater57// than 31 (checked in calling routine), lower it to a D<shift>32 instruction58static void LowerLargeShift(MCInst& Inst) {59assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");60assert(Inst.getOperand(2).isImm());6162int64_t Shift = Inst.getOperand(2).getImm();63if (Shift <= 31)64return; // Do nothing65Shift -= 32;6667// saminus3268Inst.getOperand(2).setImm(Shift);6970switch (Inst.getOpcode()) {71default:72// Calling function is not synchronized73llvm_unreachable("Unexpected shift instruction");74case Mips::DSLL:75Inst.setOpcode(Mips::DSLL32);76return;77case Mips::DSRL:78Inst.setOpcode(Mips::DSRL32);79return;80case Mips::DSRA:81Inst.setOpcode(Mips::DSRA32);82return;83case Mips::DROTR:84Inst.setOpcode(Mips::DROTR32);85return;86}87}8889// Fix a bad compact branch encoding for beqc/bnec.90void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {91// Encoding may be illegal !(rs < rt), but this situation is92// easily fixed.93unsigned RegOp0 = Inst.getOperand(0).getReg();94unsigned RegOp1 = Inst.getOperand(1).getReg();9596unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0);97unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1);9899if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC ||100Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) {101assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");102if (Reg0 < Reg1)103return;104} else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) {105if (Reg0 >= Reg1)106return;107} else if (Inst.getOpcode() == Mips::BNVC_MMR6 ||108Inst.getOpcode() == Mips::BOVC_MMR6) {109if (Reg1 >= Reg0)110return;111} else112llvm_unreachable("Cannot rewrite unknown branch!");113114Inst.getOperand(0).setReg(RegOp1);115Inst.getOperand(1).setReg(RegOp0);116}117118bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {119return STI.hasFeature(Mips::FeatureMicroMips);120}121122bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {123return STI.hasFeature(Mips::FeatureMips32r6);124}125126void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {127OS << (char)C;128}129130/// encodeInstruction - Emit the instruction.131/// Size the instruction with Desc.getSize().132void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI,133SmallVectorImpl<char> &CB,134SmallVectorImpl<MCFixup> &Fixups,135const MCSubtargetInfo &STI) const {136// Non-pseudo instructions that get changed for direct object137// only based on operand values.138// If this list of instructions get much longer we will move139// the check to a function call. Until then, this is more efficient.140MCInst TmpInst = MI;141switch (MI.getOpcode()) {142// If shift amount is >= 32 it the inst needs to be lowered further143case Mips::DSLL:144case Mips::DSRL:145case Mips::DSRA:146case Mips::DROTR:147LowerLargeShift(TmpInst);148break;149// Compact branches, enforce encoding restrictions.150case Mips::BEQC:151case Mips::BNEC:152case Mips::BEQC64:153case Mips::BNEC64:154case Mips::BOVC:155case Mips::BOVC_MMR6:156case Mips::BNVC:157case Mips::BNVC_MMR6:158LowerCompactBranch(TmpInst);159}160161size_t N = Fixups.size();162uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);163164// Check for unimplemented opcodes.165// Unfortunately in MIPS both NOP and SLL will come in with Binary == 0166// so we have to special check for them.167const unsigned Opcode = TmpInst.getOpcode();168if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&169(Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary)170llvm_unreachable("unimplemented opcode in encodeInstruction()");171172int NewOpcode = -1;173if (isMicroMips(STI)) {174if (isMips32r6(STI)) {175NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6);176if (NewOpcode == -1)177NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6);178}179else180NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips);181182// Check whether it is Dsp instruction.183if (NewOpcode == -1)184NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp);185186if (NewOpcode != -1) {187if (Fixups.size() > N)188Fixups.pop_back();189190TmpInst.setOpcode (NewOpcode);191Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);192}193194if (((MI.getOpcode() == Mips::MOVEP_MM) ||195(MI.getOpcode() == Mips::MOVEP_MMR6))) {196unsigned RegPair = getMovePRegPairOpValue(MI, 0, Fixups, STI);197Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7);198}199}200201const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());202203// Get byte count of instruction204unsigned Size = Desc.getSize();205if (!Size)206llvm_unreachable("Desc.getSize() returns 0");207208auto Endian =209IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;210if (Size == 2) {211support::endian::write<uint16_t>(CB, Binary, Endian);212} else if (IsLittleEndian && isMicroMips(STI)) {213support::endian::write<uint16_t>(CB, Binary >> 16, Endian);214support::endian::write<uint16_t>(CB, Binary & 0xffff, Endian);215} else {216support::endian::write<uint32_t>(CB, Binary, Endian);217}218}219220/// getBranchTargetOpValue - Return binary encoding of the branch221/// target operand. If the machine operand requires relocation,222/// record the relocation and return zero.223unsigned MipsMCCodeEmitter::224getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,225SmallVectorImpl<MCFixup> &Fixups,226const MCSubtargetInfo &STI) const {227const MCOperand &MO = MI.getOperand(OpNo);228229// If the destination is an immediate, divide by 4.230if (MO.isImm()) return MO.getImm() >> 2;231232assert(MO.isExpr() &&233"getBranchTargetOpValue expects only expressions or immediates");234235const MCExpr *FixupExpression = MCBinaryExpr::createAdd(236MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);237Fixups.push_back(MCFixup::create(0, FixupExpression,238MCFixupKind(Mips::fixup_Mips_PC16)));239return 0;240}241242/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch243/// target operand. If the machine operand requires relocation,244/// record the relocation and return zero.245unsigned MipsMCCodeEmitter::246getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,247SmallVectorImpl<MCFixup> &Fixups,248const MCSubtargetInfo &STI) const {249const MCOperand &MO = MI.getOperand(OpNo);250251// If the destination is an immediate, divide by 2.252if (MO.isImm()) return MO.getImm() >> 1;253254assert(MO.isExpr() &&255"getBranchTargetOpValue expects only expressions or immediates");256257const MCExpr *FixupExpression = MCBinaryExpr::createAdd(258MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);259Fixups.push_back(MCFixup::create(0, FixupExpression,260MCFixupKind(Mips::fixup_Mips_PC16)));261return 0;262}263264/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch265/// target operand. If the machine operand requires relocation,266/// record the relocation and return zero.267unsigned MipsMCCodeEmitter::268getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,269SmallVectorImpl<MCFixup> &Fixups,270const MCSubtargetInfo &STI) const {271const MCOperand &MO = MI.getOperand(OpNo);272273// If the destination is an immediate, divide by 2.274if (MO.isImm())275return MO.getImm() >> 1;276277assert(MO.isExpr() &&278"getBranchTargetOpValueMMR6 expects only expressions or immediates");279280const MCExpr *FixupExpression = MCBinaryExpr::createAdd(281MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx);282Fixups.push_back(MCFixup::create(0, FixupExpression,283MCFixupKind(Mips::fixup_Mips_PC16)));284return 0;285}286287/// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch288/// target operand. If the machine operand requires relocation,289/// record the relocation and return zero.290unsigned MipsMCCodeEmitter::291getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo,292SmallVectorImpl<MCFixup> &Fixups,293const MCSubtargetInfo &STI) const {294const MCOperand &MO = MI.getOperand(OpNo);295296// If the destination is an immediate, divide by 4.297if (MO.isImm())298return MO.getImm() >> 2;299300assert(MO.isExpr() &&301"getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates");302303const MCExpr *FixupExpression = MCBinaryExpr::createAdd(304MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);305Fixups.push_back(MCFixup::create(0, FixupExpression,306MCFixupKind(Mips::fixup_Mips_PC16)));307return 0;308}309310/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch311/// target operand. If the machine operand requires relocation,312/// record the relocation and return zero.313unsigned MipsMCCodeEmitter::314getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,315SmallVectorImpl<MCFixup> &Fixups,316const MCSubtargetInfo &STI) const {317const MCOperand &MO = MI.getOperand(OpNo);318319// If the destination is an immediate, divide by 2.320if (MO.isImm()) return MO.getImm() >> 1;321322assert(MO.isExpr() &&323"getBranchTargetOpValueMM expects only expressions or immediates");324325const MCExpr *Expr = MO.getExpr();326Fixups.push_back(MCFixup::create(0, Expr,327MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1)));328return 0;329}330331/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS332/// 10-bit branch target operand. If the machine operand requires relocation,333/// record the relocation and return zero.334unsigned MipsMCCodeEmitter::335getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,336SmallVectorImpl<MCFixup> &Fixups,337const MCSubtargetInfo &STI) const {338const MCOperand &MO = MI.getOperand(OpNo);339340// If the destination is an immediate, divide by 2.341if (MO.isImm()) return MO.getImm() >> 1;342343assert(MO.isExpr() &&344"getBranchTargetOpValuePC10 expects only expressions or immediates");345346const MCExpr *Expr = MO.getExpr();347Fixups.push_back(MCFixup::create(0, Expr,348MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1)));349return 0;350}351352/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch353/// target operand. If the machine operand requires relocation,354/// record the relocation and return zero.355unsigned MipsMCCodeEmitter::356getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,357SmallVectorImpl<MCFixup> &Fixups,358const MCSubtargetInfo &STI) const {359const MCOperand &MO = MI.getOperand(OpNo);360361// If the destination is an immediate, divide by 2.362if (MO.isImm()) return MO.getImm() >> 1;363364assert(MO.isExpr() &&365"getBranchTargetOpValueMM expects only expressions or immediates");366367const MCExpr *Expr = MO.getExpr();368Fixups.push_back(MCFixup::create(0, Expr,369MCFixupKind(Mips::370fixup_MICROMIPS_PC16_S1)));371return 0;372}373374/// getBranchTarget21OpValue - Return binary encoding of the branch375/// target operand. If the machine operand requires relocation,376/// record the relocation and return zero.377unsigned MipsMCCodeEmitter::378getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,379SmallVectorImpl<MCFixup> &Fixups,380const MCSubtargetInfo &STI) const {381const MCOperand &MO = MI.getOperand(OpNo);382383// If the destination is an immediate, divide by 4.384if (MO.isImm()) return MO.getImm() >> 2;385386assert(MO.isExpr() &&387"getBranchTarget21OpValue expects only expressions or immediates");388389const MCExpr *FixupExpression = MCBinaryExpr::createAdd(390MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);391Fixups.push_back(MCFixup::create(0, FixupExpression,392MCFixupKind(Mips::fixup_MIPS_PC21_S2)));393return 0;394}395396/// getBranchTarget21OpValueMM - Return binary encoding of the branch397/// target operand for microMIPS. If the machine operand requires398/// relocation, record the relocation and return zero.399unsigned MipsMCCodeEmitter::400getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,401SmallVectorImpl<MCFixup> &Fixups,402const MCSubtargetInfo &STI) const {403const MCOperand &MO = MI.getOperand(OpNo);404405// If the destination is an immediate, divide by 4.406if (MO.isImm()) return MO.getImm() >> 2;407408assert(MO.isExpr() &&409"getBranchTarget21OpValueMM expects only expressions or immediates");410411const MCExpr *FixupExpression = MCBinaryExpr::createAdd(412MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);413Fixups.push_back(MCFixup::create(0, FixupExpression,414MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1)));415return 0;416}417418/// getBranchTarget26OpValue - Return binary encoding of the branch419/// target operand. If the machine operand requires relocation,420/// record the relocation and return zero.421unsigned MipsMCCodeEmitter::422getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,423SmallVectorImpl<MCFixup> &Fixups,424const MCSubtargetInfo &STI) const {425const MCOperand &MO = MI.getOperand(OpNo);426427// If the destination is an immediate, divide by 4.428if (MO.isImm()) return MO.getImm() >> 2;429430assert(MO.isExpr() &&431"getBranchTarget26OpValue expects only expressions or immediates");432433const MCExpr *FixupExpression = MCBinaryExpr::createAdd(434MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);435Fixups.push_back(MCFixup::create(0, FixupExpression,436MCFixupKind(Mips::fixup_MIPS_PC26_S2)));437return 0;438}439440/// getBranchTarget26OpValueMM - Return binary encoding of the branch441/// target operand. If the machine operand requires relocation,442/// record the relocation and return zero.443unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(444const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,445const MCSubtargetInfo &STI) const {446const MCOperand &MO = MI.getOperand(OpNo);447448// If the destination is an immediate, divide by 2.449if (MO.isImm())450return MO.getImm() >> 1;451452assert(MO.isExpr() &&453"getBranchTarget26OpValueMM expects only expressions or immediates");454455const MCExpr *FixupExpression = MCBinaryExpr::createAdd(456MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);457Fixups.push_back(MCFixup::create(0, FixupExpression,458MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1)));459return 0;460}461462/// getJumpOffset16OpValue - Return binary encoding of the jump463/// target operand. If the machine operand requires relocation,464/// record the relocation and return zero.465unsigned MipsMCCodeEmitter::466getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,467SmallVectorImpl<MCFixup> &Fixups,468const MCSubtargetInfo &STI) const {469const MCOperand &MO = MI.getOperand(OpNo);470471if (MO.isImm()) return MO.getImm();472473assert(MO.isExpr() &&474"getJumpOffset16OpValue expects only expressions or an immediate");475476const MCExpr *Expr = MO.getExpr();477Mips::Fixups FixupKind =478isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16;479Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));480return 0;481}482483/// getJumpTargetOpValue - Return binary encoding of the jump484/// target operand. If the machine operand requires relocation,485/// record the relocation and return zero.486unsigned MipsMCCodeEmitter::487getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,488SmallVectorImpl<MCFixup> &Fixups,489const MCSubtargetInfo &STI) const {490const MCOperand &MO = MI.getOperand(OpNo);491// If the destination is an immediate, divide by 4.492if (MO.isImm()) return MO.getImm()>>2;493494assert(MO.isExpr() &&495"getJumpTargetOpValue expects only expressions or an immediate");496497const MCExpr *Expr = MO.getExpr();498Fixups.push_back(MCFixup::create(0, Expr,499MCFixupKind(Mips::fixup_Mips_26)));500return 0;501}502503unsigned MipsMCCodeEmitter::504getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,505SmallVectorImpl<MCFixup> &Fixups,506const MCSubtargetInfo &STI) const {507const MCOperand &MO = MI.getOperand(OpNo);508// If the destination is an immediate, divide by 2.509if (MO.isImm()) return MO.getImm() >> 1;510511assert(MO.isExpr() &&512"getJumpTargetOpValueMM expects only expressions or an immediate");513514const MCExpr *Expr = MO.getExpr();515Fixups.push_back(MCFixup::create(0, Expr,516MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));517return 0;518}519520unsigned MipsMCCodeEmitter::521getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,522SmallVectorImpl<MCFixup> &Fixups,523const MCSubtargetInfo &STI) const {524const MCOperand &MO = MI.getOperand(OpNo);525if (MO.isImm()) {526// The immediate is encoded as 'immediate << 2'.527unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);528assert((Res & 3) == 0);529return Res >> 2;530}531532assert(MO.isExpr() &&533"getUImm5Lsl2Encoding expects only expressions or an immediate");534535return 0;536}537538unsigned MipsMCCodeEmitter::539getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,540SmallVectorImpl<MCFixup> &Fixups,541const MCSubtargetInfo &STI) const {542const MCOperand &MO = MI.getOperand(OpNo);543if (MO.isImm()) {544int Value = MO.getImm();545return Value >> 2;546}547548return 0;549}550551unsigned MipsMCCodeEmitter::552getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,553SmallVectorImpl<MCFixup> &Fixups,554const MCSubtargetInfo &STI) const {555const MCOperand &MO = MI.getOperand(OpNo);556if (MO.isImm()) {557unsigned Value = MO.getImm();558return Value >> 2;559}560561return 0;562}563564unsigned MipsMCCodeEmitter::565getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,566SmallVectorImpl<MCFixup> &Fixups,567const MCSubtargetInfo &STI) const {568const MCOperand &MO = MI.getOperand(OpNo);569if (MO.isImm()) {570unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;571return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));572}573574return 0;575}576577unsigned MipsMCCodeEmitter::578getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,579const MCSubtargetInfo &STI) const {580int64_t Res;581582if (Expr->evaluateAsAbsolute(Res))583return Res;584585MCExpr::ExprKind Kind = Expr->getKind();586if (Kind == MCExpr::Constant) {587return cast<MCConstantExpr>(Expr)->getValue();588}589590if (Kind == MCExpr::Binary) {591unsigned Res =592getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);593Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);594return Res;595}596597if (Kind == MCExpr::Target) {598const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);599600Mips::Fixups FixupKind = Mips::Fixups(0);601switch (MipsExpr->getKind()) {602case MipsMCExpr::MEK_None:603case MipsMCExpr::MEK_Special:604llvm_unreachable("Unhandled fixup kind!");605break;606case MipsMCExpr::MEK_DTPREL:607// MEK_DTPREL is used for marking TLS DIEExpr only608// and contains a regular sub-expression.609return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI);610case MipsMCExpr::MEK_CALL_HI16:611FixupKind = Mips::fixup_Mips_CALL_HI16;612break;613case MipsMCExpr::MEK_CALL_LO16:614FixupKind = Mips::fixup_Mips_CALL_LO16;615break;616case MipsMCExpr::MEK_DTPREL_HI:617FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16618: Mips::fixup_Mips_DTPREL_HI;619break;620case MipsMCExpr::MEK_DTPREL_LO:621FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16622: Mips::fixup_Mips_DTPREL_LO;623break;624case MipsMCExpr::MEK_GOTTPREL:625FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL626: Mips::fixup_Mips_GOTTPREL;627break;628case MipsMCExpr::MEK_GOT:629FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16630: Mips::fixup_Mips_GOT;631break;632case MipsMCExpr::MEK_GOT_CALL:633FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16634: Mips::fixup_Mips_CALL16;635break;636case MipsMCExpr::MEK_GOT_DISP:637FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP638: Mips::fixup_Mips_GOT_DISP;639break;640case MipsMCExpr::MEK_GOT_HI16:641FixupKind = Mips::fixup_Mips_GOT_HI16;642break;643case MipsMCExpr::MEK_GOT_LO16:644FixupKind = Mips::fixup_Mips_GOT_LO16;645break;646case MipsMCExpr::MEK_GOT_PAGE:647FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE648: Mips::fixup_Mips_GOT_PAGE;649break;650case MipsMCExpr::MEK_GOT_OFST:651FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST652: Mips::fixup_Mips_GOT_OFST;653break;654case MipsMCExpr::MEK_GPREL:655FixupKind = Mips::fixup_Mips_GPREL16;656break;657case MipsMCExpr::MEK_LO:658// Check for %lo(%neg(%gp_rel(X)))659if (MipsExpr->isGpOff())660FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO661: Mips::fixup_Mips_GPOFF_LO;662else663FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16664: Mips::fixup_Mips_LO16;665break;666case MipsMCExpr::MEK_HIGHEST:667FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST668: Mips::fixup_Mips_HIGHEST;669break;670case MipsMCExpr::MEK_HIGHER:671FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER672: Mips::fixup_Mips_HIGHER;673break;674case MipsMCExpr::MEK_HI:675// Check for %hi(%neg(%gp_rel(X)))676if (MipsExpr->isGpOff())677FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI678: Mips::fixup_Mips_GPOFF_HI;679else680FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16681: Mips::fixup_Mips_HI16;682break;683case MipsMCExpr::MEK_PCREL_HI16:684FixupKind = Mips::fixup_MIPS_PCHI16;685break;686case MipsMCExpr::MEK_PCREL_LO16:687FixupKind = Mips::fixup_MIPS_PCLO16;688break;689case MipsMCExpr::MEK_TLSGD:690FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD691: Mips::fixup_Mips_TLSGD;692break;693case MipsMCExpr::MEK_TLSLDM:694FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM695: Mips::fixup_Mips_TLSLDM;696break;697case MipsMCExpr::MEK_TPREL_HI:698FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16699: Mips::fixup_Mips_TPREL_HI;700break;701case MipsMCExpr::MEK_TPREL_LO:702FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16703: Mips::fixup_Mips_TPREL_LO;704break;705case MipsMCExpr::MEK_NEG:706FixupKind =707isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB;708break;709}710Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));711return 0;712}713714if (Kind == MCExpr::SymbolRef)715Ctx.reportError(Expr->getLoc(), "expected an immediate");716return 0;717}718719/// getMachineOpValue - Return binary encoding of operand. If the machine720/// operand requires relocation, record the relocation and return zero.721unsigned MipsMCCodeEmitter::722getMachineOpValue(const MCInst &MI, const MCOperand &MO,723SmallVectorImpl<MCFixup> &Fixups,724const MCSubtargetInfo &STI) const {725if (MO.isReg()) {726unsigned Reg = MO.getReg();727unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);728return RegNo;729} else if (MO.isImm()) {730return static_cast<unsigned>(MO.getImm());731} else if (MO.isDFPImm()) {732return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm()));733}734// MO must be an Expr.735assert(MO.isExpr());736return getExprOpValue(MO.getExpr(),Fixups, STI);737}738739/// Return binary encoding of memory related operand.740/// If the offset operand requires relocation, record the relocation.741template <unsigned ShiftAmount>742unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,743SmallVectorImpl<MCFixup> &Fixups,744const MCSubtargetInfo &STI) const {745// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.746assert(MI.getOperand(OpNo).isReg());747unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)748<< 16;749unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);750751// Apply the scale factor if there is one.752OffBits >>= ShiftAmount;753754return (OffBits & 0xFFFF) | RegBits;755}756757unsigned MipsMCCodeEmitter::758getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,759SmallVectorImpl<MCFixup> &Fixups,760const MCSubtargetInfo &STI) const {761// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.762assert(MI.getOperand(OpNo).isReg());763unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),764Fixups, STI) << 4;765unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),766Fixups, STI);767768return (OffBits & 0xF) | RegBits;769}770771unsigned MipsMCCodeEmitter::772getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,773SmallVectorImpl<MCFixup> &Fixups,774const MCSubtargetInfo &STI) const {775// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.776assert(MI.getOperand(OpNo).isReg());777unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),778Fixups, STI) << 4;779unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),780Fixups, STI) >> 1;781782return (OffBits & 0xF) | RegBits;783}784785unsigned MipsMCCodeEmitter::786getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,787SmallVectorImpl<MCFixup> &Fixups,788const MCSubtargetInfo &STI) const {789// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.790assert(MI.getOperand(OpNo).isReg());791unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),792Fixups, STI) << 4;793unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),794Fixups, STI) >> 2;795796return (OffBits & 0xF) | RegBits;797}798799unsigned MipsMCCodeEmitter::800getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,801SmallVectorImpl<MCFixup> &Fixups,802const MCSubtargetInfo &STI) const {803// Register is encoded in bits 9-5, offset is encoded in bits 4-0.804assert(MI.getOperand(OpNo).isReg() &&805(MI.getOperand(OpNo).getReg() == Mips::SP ||806MI.getOperand(OpNo).getReg() == Mips::SP_64) &&807"Unexpected base register!");808unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),809Fixups, STI) >> 2;810811return OffBits & 0x1F;812}813814unsigned MipsMCCodeEmitter::815getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,816SmallVectorImpl<MCFixup> &Fixups,817const MCSubtargetInfo &STI) const {818// Register is encoded in bits 9-7, offset is encoded in bits 6-0.819assert(MI.getOperand(OpNo).isReg() &&820MI.getOperand(OpNo).getReg() == Mips::GP &&821"Unexpected base register!");822823unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),824Fixups, STI) >> 2;825826return OffBits & 0x7F;827}828829unsigned MipsMCCodeEmitter::830getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,831SmallVectorImpl<MCFixup> &Fixups,832const MCSubtargetInfo &STI) const {833// Base register is encoded in bits 20-16, offset is encoded in bits 8-0.834assert(MI.getOperand(OpNo).isReg());835unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,836STI) << 16;837unsigned OffBits =838getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);839840return (OffBits & 0x1FF) | RegBits;841}842843unsigned MipsMCCodeEmitter::844getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,845SmallVectorImpl<MCFixup> &Fixups,846const MCSubtargetInfo &STI) const {847// Base register is encoded in bits 20-16, offset is encoded in bits 10-0.848assert(MI.getOperand(OpNo).isReg());849unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,850STI) << 16;851unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);852853return (OffBits & 0x07FF) | RegBits;854}855856unsigned MipsMCCodeEmitter::857getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,858SmallVectorImpl<MCFixup> &Fixups,859const MCSubtargetInfo &STI) const {860// opNum can be invalid if instruction had reglist as operand.861// MemOperand is always last operand of instruction (base + offset).862switch (MI.getOpcode()) {863default:864break;865case Mips::SWM32_MM:866case Mips::LWM32_MM:867OpNo = MI.getNumOperands() - 2;868break;869}870871// Base register is encoded in bits 20-16, offset is encoded in bits 11-0.872assert(MI.getOperand(OpNo).isReg());873unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)874<< 16;875unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);876877return (OffBits & 0x0FFF) | RegBits;878}879880unsigned MipsMCCodeEmitter::881getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,882SmallVectorImpl<MCFixup> &Fixups,883const MCSubtargetInfo &STI) const {884// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.885assert(MI.getOperand(OpNo).isReg());886unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,887STI) << 16;888unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);889890return (OffBits & 0xFFFF) | RegBits;891}892893unsigned MipsMCCodeEmitter::894getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,895SmallVectorImpl<MCFixup> &Fixups,896const MCSubtargetInfo &STI) const {897// opNum can be invalid if instruction had reglist as operand898// MemOperand is always last operand of instruction (base + offset)899switch (MI.getOpcode()) {900default:901break;902case Mips::SWM16_MM:903case Mips::SWM16_MMR6:904case Mips::LWM16_MM:905case Mips::LWM16_MMR6:906OpNo = MI.getNumOperands() - 2;907break;908}909910// Offset is encoded in bits 4-0.911assert(MI.getOperand(OpNo).isReg());912// Base register is always SP - thus it is not encoded.913assert(MI.getOperand(OpNo+1).isImm());914unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);915916return ((OffBits >> 2) & 0x0F);917}918919// FIXME: should be called getMSBEncoding920//921unsigned922MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,923SmallVectorImpl<MCFixup> &Fixups,924const MCSubtargetInfo &STI) const {925assert(MI.getOperand(OpNo-1).isImm());926assert(MI.getOperand(OpNo).isImm());927unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);928unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);929930return Position + Size - 1;931}932933template <unsigned Bits, int Offset>934unsigned935MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,936SmallVectorImpl<MCFixup> &Fixups,937const MCSubtargetInfo &STI) const {938assert(MI.getOperand(OpNo).isImm());939unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);940Value -= Offset;941return Value;942}943944unsigned945MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,946SmallVectorImpl<MCFixup> &Fixups,947const MCSubtargetInfo &STI) const {948const MCOperand &MO = MI.getOperand(OpNo);949if (MO.isImm()) {950// The immediate is encoded as 'immediate << 2'.951unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);952assert((Res & 3) == 0);953return Res >> 2;954}955956assert(MO.isExpr() &&957"getSimm19Lsl2Encoding expects only expressions or an immediate");958959const MCExpr *Expr = MO.getExpr();960Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2961: Mips::fixup_MIPS_PC19_S2;962Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));963return 0;964}965966unsigned967MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,968SmallVectorImpl<MCFixup> &Fixups,969const MCSubtargetInfo &STI) const {970const MCOperand &MO = MI.getOperand(OpNo);971if (MO.isImm()) {972// The immediate is encoded as 'immediate << 3'.973unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);974assert((Res & 7) == 0);975return Res >> 3;976}977978assert(MO.isExpr() &&979"getSimm18Lsl2Encoding expects only expressions or an immediate");980981const MCExpr *Expr = MO.getExpr();982Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3983: Mips::fixup_MIPS_PC18_S3;984Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));985return 0;986}987988unsigned989MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,990SmallVectorImpl<MCFixup> &Fixups,991const MCSubtargetInfo &STI) const {992assert(MI.getOperand(OpNo).isImm());993const MCOperand &MO = MI.getOperand(OpNo);994return MO.getImm() % 8;995}996997unsigned998MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,999SmallVectorImpl<MCFixup> &Fixups,1000const MCSubtargetInfo &STI) const {1001assert(MI.getOperand(OpNo).isImm());1002const MCOperand &MO = MI.getOperand(OpNo);1003unsigned Value = MO.getImm();1004switch (Value) {1005case 128: return 0x0;1006case 1: return 0x1;1007case 2: return 0x2;1008case 3: return 0x3;1009case 4: return 0x4;1010case 7: return 0x5;1011case 8: return 0x6;1012case 15: return 0x7;1013case 16: return 0x8;1014case 31: return 0x9;1015case 32: return 0xa;1016case 63: return 0xb;1017case 64: return 0xc;1018case 255: return 0xd;1019case 32768: return 0xe;1020case 65535: return 0xf;1021}1022llvm_unreachable("Unexpected value");1023}10241025unsigned1026MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,1027SmallVectorImpl<MCFixup> &Fixups,1028const MCSubtargetInfo &STI) const {1029unsigned res = 0;10301031// Register list operand is always first operand of instruction and it is1032// placed before memory operand (register + imm).10331034for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {1035unsigned Reg = MI.getOperand(I).getReg();1036unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);1037if (RegNo != 31)1038res++;1039else1040res |= 0x10;1041}1042return res;1043}10441045unsigned1046MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,1047SmallVectorImpl<MCFixup> &Fixups,1048const MCSubtargetInfo &STI) const {1049return (MI.getNumOperands() - 4);1050}10511052unsigned1053MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,1054SmallVectorImpl<MCFixup> &Fixups,1055const MCSubtargetInfo &STI) const {1056unsigned res = 0;10571058if (MI.getOperand(0).getReg() == Mips::A1 &&1059MI.getOperand(1).getReg() == Mips::A2)1060res = 0;1061else if (MI.getOperand(0).getReg() == Mips::A1 &&1062MI.getOperand(1).getReg() == Mips::A3)1063res = 1;1064else if (MI.getOperand(0).getReg() == Mips::A2 &&1065MI.getOperand(1).getReg() == Mips::A3)1066res = 2;1067else if (MI.getOperand(0).getReg() == Mips::A0 &&1068MI.getOperand(1).getReg() == Mips::S5)1069res = 3;1070else if (MI.getOperand(0).getReg() == Mips::A0 &&1071MI.getOperand(1).getReg() == Mips::S6)1072res = 4;1073else if (MI.getOperand(0).getReg() == Mips::A0 &&1074MI.getOperand(1).getReg() == Mips::A1)1075res = 5;1076else if (MI.getOperand(0).getReg() == Mips::A0 &&1077MI.getOperand(1).getReg() == Mips::A2)1078res = 6;1079else if (MI.getOperand(0).getReg() == Mips::A0 &&1080MI.getOperand(1).getReg() == Mips::A3)1081res = 7;10821083return res;1084}10851086unsigned1087MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo,1088SmallVectorImpl<MCFixup> &Fixups,1089const MCSubtargetInfo &STI) const {1090assert(((OpNo == 2) || (OpNo == 3)) &&1091"Unexpected OpNo for movep operand encoding!");10921093MCOperand Op = MI.getOperand(OpNo);1094assert(Op.isReg() && "Operand of movep is not a register!");1095switch (Op.getReg()) {1096default:1097llvm_unreachable("Unknown register for movep!");1098case Mips::ZERO: return 0;1099case Mips::S1: return 1;1100case Mips::V0: return 2;1101case Mips::V1: return 3;1102case Mips::S0: return 4;1103case Mips::S2: return 5;1104case Mips::S3: return 6;1105case Mips::S4: return 7;1106}1107}11081109unsigned1110MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,1111SmallVectorImpl<MCFixup> &Fixups,1112const MCSubtargetInfo &STI) const {1113const MCOperand &MO = MI.getOperand(OpNo);1114assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");1115// The immediate is encoded as 'immediate >> 2'.1116unsigned Res = static_cast<unsigned>(MO.getImm());1117assert((Res & 3) == 0);1118return Res >> 2;1119}11201121#include "MipsGenMCCodeEmitter.inc"112211231124