1135 lines · cpp
1//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the MipsMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MipsMCCodeEmitter.h"14#include "MCTargetDesc/MipsBaseInfo.h"15#include "MCTargetDesc/MipsFixupKinds.h"16#include "MCTargetDesc/MipsMCAsmInfo.h"17#include "MCTargetDesc/MipsMCTargetDesc.h"18#include "llvm/ADT/APFloat.h"19#include "llvm/ADT/APInt.h"20#include "llvm/ADT/SmallVector.h"21#include "llvm/MC/MCContext.h"22#include "llvm/MC/MCExpr.h"23#include "llvm/MC/MCFixup.h"24#include "llvm/MC/MCInst.h"25#include "llvm/MC/MCInstrDesc.h"26#include "llvm/MC/MCInstrInfo.h"27#include "llvm/MC/MCRegisterInfo.h"28#include "llvm/MC/MCSubtargetInfo.h"29#include "llvm/Support/Casting.h"30#include "llvm/Support/EndianStream.h"31#include "llvm/Support/raw_ostream.h"32#include <cassert>33#include <cstdint>34 35using namespace llvm;36 37#define DEBUG_TYPE "mccodeemitter"38 39#define GET_INSTRMAP_INFO40#include "MipsGenInstrInfo.inc"41#undef GET_INSTRMAP_INFO42 43namespace llvm {44 45MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,46 MCContext &Ctx) {47 return new MipsMCCodeEmitter(MCII, Ctx, false);48}49 50MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,51 MCContext &Ctx) {52 return new MipsMCCodeEmitter(MCII, Ctx, true);53}54 55} // end namespace llvm56 57static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,58 const MCExpr *Value, uint16_t Kind) {59 bool PCRel = false;60 switch (Kind) {61 case Mips::fixup_Mips_PC16:62 case Mips::fixup_Mips_Branch_PCRel:63 case Mips::fixup_MIPS_PC18_S3:64 case Mips::fixup_MIPS_PC19_S2:65 case Mips::fixup_MIPS_PC21_S2:66 case Mips::fixup_MIPS_PC26_S2:67 case Mips::fixup_MIPS_PCHI16:68 case Mips::fixup_MIPS_PCLO16:69 case Mips::fixup_MICROMIPS_PC7_S1:70 case Mips::fixup_MICROMIPS_PC10_S1:71 case Mips::fixup_MICROMIPS_PC16_S1:72 case Mips::fixup_MICROMIPS_PC26_S1:73 case Mips::fixup_MICROMIPS_PC19_S2:74 case Mips::fixup_MICROMIPS_PC18_S3:75 case Mips::fixup_MICROMIPS_PC21_S1:76 PCRel = true;77 }78 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));79}80 81// If the D<shift> instruction has a shift amount that is greater82// than 31 (checked in calling routine), lower it to a D<shift>32 instruction83static void LowerLargeShift(MCInst& Inst) {84 assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");85 assert(Inst.getOperand(2).isImm());86 87 int64_t Shift = Inst.getOperand(2).getImm();88 if (Shift <= 31)89 return; // Do nothing90 Shift -= 32;91 92 // saminus3293 Inst.getOperand(2).setImm(Shift);94 95 switch (Inst.getOpcode()) {96 default:97 // Calling function is not synchronized98 llvm_unreachable("Unexpected shift instruction");99 case Mips::DSLL:100 Inst.setOpcode(Mips::DSLL32);101 return;102 case Mips::DSRL:103 Inst.setOpcode(Mips::DSRL32);104 return;105 case Mips::DSRA:106 Inst.setOpcode(Mips::DSRA32);107 return;108 case Mips::DROTR:109 Inst.setOpcode(Mips::DROTR32);110 return;111 }112}113 114// Fix a bad compact branch encoding for beqc/bnec.115void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {116 // Encoding may be illegal !(rs < rt), but this situation is117 // easily fixed.118 MCRegister RegOp0 = Inst.getOperand(0).getReg();119 MCRegister RegOp1 = Inst.getOperand(1).getReg();120 121 unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0);122 unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1);123 124 if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC ||125 Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) {126 assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");127 if (Reg0 < Reg1)128 return;129 } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) {130 if (Reg0 >= Reg1)131 return;132 } else if (Inst.getOpcode() == Mips::BNVC_MMR6 ||133 Inst.getOpcode() == Mips::BOVC_MMR6) {134 if (Reg1 >= Reg0)135 return;136 } else137 llvm_unreachable("Cannot rewrite unknown branch!");138 139 Inst.getOperand(0).setReg(RegOp1);140 Inst.getOperand(1).setReg(RegOp0);141}142 143bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {144 return STI.hasFeature(Mips::FeatureMicroMips);145}146 147bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {148 return STI.hasFeature(Mips::FeatureMips32r6);149}150 151void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {152 OS << (char)C;153}154 155/// encodeInstruction - Emit the instruction.156/// Size the instruction with Desc.getSize().157void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI,158 SmallVectorImpl<char> &CB,159 SmallVectorImpl<MCFixup> &Fixups,160 const MCSubtargetInfo &STI) const {161 // Non-pseudo instructions that get changed for direct object162 // only based on operand values.163 // If this list of instructions get much longer we will move164 // the check to a function call. Until then, this is more efficient.165 MCInst TmpInst = MI;166 switch (MI.getOpcode()) {167 // If shift amount is >= 32 it the inst needs to be lowered further168 case Mips::DSLL:169 case Mips::DSRL:170 case Mips::DSRA:171 case Mips::DROTR:172 LowerLargeShift(TmpInst);173 break;174 // Compact branches, enforce encoding restrictions.175 case Mips::BEQC:176 case Mips::BNEC:177 case Mips::BEQC64:178 case Mips::BNEC64:179 case Mips::BOVC:180 case Mips::BOVC_MMR6:181 case Mips::BNVC:182 case Mips::BNVC_MMR6:183 LowerCompactBranch(TmpInst);184 }185 186 size_t N = Fixups.size();187 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);188 189 // Check for unimplemented opcodes.190 // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0191 // so we have to special check for them.192 const unsigned Opcode = TmpInst.getOpcode();193 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&194 (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary)195 llvm_unreachable("unimplemented opcode in encodeInstruction()");196 197 int NewOpcode = -1;198 if (isMicroMips(STI)) {199 if (isMips32r6(STI)) {200 NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6);201 if (NewOpcode == -1)202 NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6);203 }204 else205 NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips);206 207 // Check whether it is Dsp instruction.208 if (NewOpcode == -1)209 NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp);210 211 if (NewOpcode != -1) {212 if (Fixups.size() > N)213 Fixups.pop_back();214 215 TmpInst.setOpcode (NewOpcode);216 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);217 }218 219 if (((MI.getOpcode() == Mips::MOVEP_MM) ||220 (MI.getOpcode() == Mips::MOVEP_MMR6))) {221 unsigned RegPair = getMovePRegPairOpValue(MI, 0, Fixups, STI);222 Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7);223 }224 }225 226 const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());227 228 // Get byte count of instruction229 unsigned Size = Desc.getSize();230 if (!Size)231 llvm_unreachable("Desc.getSize() returns 0");232 233 auto Endian =234 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;235 if (Size == 2) {236 support::endian::write<uint16_t>(CB, Binary, Endian);237 } else if (IsLittleEndian && isMicroMips(STI)) {238 support::endian::write<uint16_t>(CB, Binary >> 16, Endian);239 support::endian::write<uint16_t>(CB, Binary & 0xffff, Endian);240 } else {241 support::endian::write<uint32_t>(CB, Binary, Endian);242 }243}244 245/// getBranchTargetOpValue - Return binary encoding of the branch246/// target operand. If the machine operand requires relocation,247/// record the relocation and return zero.248unsigned MipsMCCodeEmitter::249getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,250 SmallVectorImpl<MCFixup> &Fixups,251 const MCSubtargetInfo &STI) const {252 const MCOperand &MO = MI.getOperand(OpNo);253 254 // If the destination is an immediate, divide by 4.255 if (MO.isImm()) return MO.getImm() >> 2;256 257 assert(MO.isExpr() &&258 "getBranchTargetOpValue expects only expressions or immediates");259 260 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(261 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);262 addFixup(Fixups, 0, FixupExpression, Mips::fixup_Mips_PC16);263 return 0;264}265 266/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch267/// target operand. If the machine operand requires relocation,268/// record the relocation and return zero.269unsigned MipsMCCodeEmitter::270getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,271 SmallVectorImpl<MCFixup> &Fixups,272 const MCSubtargetInfo &STI) const {273 const MCOperand &MO = MI.getOperand(OpNo);274 275 // If the destination is an immediate, divide by 2.276 if (MO.isImm()) return MO.getImm() >> 1;277 278 assert(MO.isExpr() &&279 "getBranchTargetOpValue expects only expressions or immediates");280 281 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(282 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);283 addFixup(Fixups, 0, FixupExpression, Mips::fixup_Mips_PC16);284 return 0;285}286 287/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch288/// target operand. If the machine operand requires relocation,289/// record the relocation and return zero.290unsigned MipsMCCodeEmitter::291getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,292 SmallVectorImpl<MCFixup> &Fixups,293 const MCSubtargetInfo &STI) const {294 const MCOperand &MO = MI.getOperand(OpNo);295 296 // If the destination is an immediate, divide by 2.297 if (MO.isImm())298 return MO.getImm() >> 1;299 300 assert(MO.isExpr() &&301 "getBranchTargetOpValueMMR6 expects only expressions or immediates");302 303 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(304 MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx);305 addFixup(Fixups, 0, FixupExpression, Mips::fixup_Mips_PC16);306 return 0;307}308 309/// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch310/// target operand. If the machine operand requires relocation,311/// record the relocation and return zero.312unsigned MipsMCCodeEmitter::313getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo,314 SmallVectorImpl<MCFixup> &Fixups,315 const MCSubtargetInfo &STI) const {316 const MCOperand &MO = MI.getOperand(OpNo);317 318 // If the destination is an immediate, divide by 4.319 if (MO.isImm())320 return MO.getImm() >> 2;321 322 assert(MO.isExpr() &&323 "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates");324 325 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(326 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);327 addFixup(Fixups, 0, FixupExpression, Mips::fixup_Mips_PC16);328 return 0;329}330 331/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch332/// target operand. If the machine operand requires relocation,333/// record the relocation and return zero.334unsigned MipsMCCodeEmitter::335getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,336 SmallVectorImpl<MCFixup> &Fixups,337 const MCSubtargetInfo &STI) const {338 const MCOperand &MO = MI.getOperand(OpNo);339 340 // If the destination is an immediate, divide by 2.341 if (MO.isImm()) return MO.getImm() >> 1;342 343 assert(MO.isExpr() &&344 "getBranchTargetOpValueMM expects only expressions or immediates");345 346 const MCExpr *Expr = MO.getExpr();347 addFixup(Fixups, 0, Expr, Mips::fixup_MICROMIPS_PC7_S1);348 return 0;349}350 351/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS352/// 10-bit branch target operand. If the machine operand requires relocation,353/// record the relocation and return zero.354unsigned MipsMCCodeEmitter::355getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,356 SmallVectorImpl<MCFixup> &Fixups,357 const MCSubtargetInfo &STI) const {358 const MCOperand &MO = MI.getOperand(OpNo);359 360 // If the destination is an immediate, divide by 2.361 if (MO.isImm()) return MO.getImm() >> 1;362 363 assert(MO.isExpr() &&364 "getBranchTargetOpValuePC10 expects only expressions or immediates");365 366 const MCExpr *Expr = MO.getExpr();367 addFixup(Fixups, 0, Expr, Mips::fixup_MICROMIPS_PC10_S1);368 return 0;369}370 371/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch372/// target operand. If the machine operand requires relocation,373/// record the relocation and return zero.374unsigned MipsMCCodeEmitter::375getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,376 SmallVectorImpl<MCFixup> &Fixups,377 const MCSubtargetInfo &STI) const {378 const MCOperand &MO = MI.getOperand(OpNo);379 380 // If the destination is an immediate, divide by 2.381 if (MO.isImm()) return MO.getImm() >> 1;382 383 assert(MO.isExpr() &&384 "getBranchTargetOpValueMM expects only expressions or immediates");385 386 const MCExpr *Expr = MO.getExpr();387 addFixup(Fixups, 0, Expr, Mips::fixup_MICROMIPS_PC16_S1);388 return 0;389}390 391/// getBranchTarget21OpValue - Return binary encoding of the branch392/// target operand. If the machine operand requires relocation,393/// record the relocation and return zero.394unsigned MipsMCCodeEmitter::395getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,396 SmallVectorImpl<MCFixup> &Fixups,397 const MCSubtargetInfo &STI) const {398 const MCOperand &MO = MI.getOperand(OpNo);399 400 // If the destination is an immediate, divide by 4.401 if (MO.isImm()) return MO.getImm() >> 2;402 403 assert(MO.isExpr() &&404 "getBranchTarget21OpValue expects only expressions or immediates");405 406 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(407 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);408 addFixup(Fixups, 0, FixupExpression, Mips::fixup_MIPS_PC21_S2);409 return 0;410}411 412/// getBranchTarget21OpValueMM - Return binary encoding of the branch413/// target operand for microMIPS. If the machine operand requires414/// relocation, record the relocation and return zero.415unsigned MipsMCCodeEmitter::416getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,417 SmallVectorImpl<MCFixup> &Fixups,418 const MCSubtargetInfo &STI) const {419 const MCOperand &MO = MI.getOperand(OpNo);420 421 // If the destination is an immediate, divide by 4.422 if (MO.isImm()) return MO.getImm() >> 2;423 424 assert(MO.isExpr() &&425 "getBranchTarget21OpValueMM expects only expressions or immediates");426 427 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(428 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);429 addFixup(Fixups, 0, FixupExpression, Mips::fixup_MICROMIPS_PC21_S1);430 return 0;431}432 433/// getBranchTarget26OpValue - Return binary encoding of the branch434/// target operand. If the machine operand requires relocation,435/// record the relocation and return zero.436unsigned MipsMCCodeEmitter::437getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,438 SmallVectorImpl<MCFixup> &Fixups,439 const MCSubtargetInfo &STI) const {440 const MCOperand &MO = MI.getOperand(OpNo);441 442 // If the destination is an immediate, divide by 4.443 if (MO.isImm()) return MO.getImm() >> 2;444 445 assert(MO.isExpr() &&446 "getBranchTarget26OpValue expects only expressions or immediates");447 448 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(449 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);450 addFixup(Fixups, 0, FixupExpression, Mips::fixup_MIPS_PC26_S2);451 return 0;452}453 454/// getBranchTarget26OpValueMM - Return binary encoding of the branch455/// target operand. If the machine operand requires relocation,456/// record the relocation and return zero.457unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(458 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,459 const MCSubtargetInfo &STI) const {460 const MCOperand &MO = MI.getOperand(OpNo);461 462 // If the destination is an immediate, divide by 2.463 if (MO.isImm())464 return MO.getImm() >> 1;465 466 assert(MO.isExpr() &&467 "getBranchTarget26OpValueMM expects only expressions or immediates");468 469 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(470 MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);471 addFixup(Fixups, 0, FixupExpression, Mips::fixup_MICROMIPS_PC26_S1);472 return 0;473}474 475/// getJumpOffset16OpValue - Return binary encoding of the jump476/// target operand. If the machine operand requires relocation,477/// record the relocation and return zero.478unsigned MipsMCCodeEmitter::479getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,480 SmallVectorImpl<MCFixup> &Fixups,481 const MCSubtargetInfo &STI) const {482 const MCOperand &MO = MI.getOperand(OpNo);483 484 if (MO.isImm()) return MO.getImm();485 486 assert(MO.isExpr() &&487 "getJumpOffset16OpValue expects only expressions or an immediate");488 489 const MCExpr *Expr = MO.getExpr();490 Mips::Fixups FixupKind =491 isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16;492 addFixup(Fixups, 0, Expr, MCFixupKind(FixupKind));493 return 0;494}495 496/// getJumpTargetOpValue - Return binary encoding of the jump497/// target operand. If the machine operand requires relocation,498/// record the relocation and return zero.499unsigned MipsMCCodeEmitter::500getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,501 SmallVectorImpl<MCFixup> &Fixups,502 const MCSubtargetInfo &STI) const {503 const MCOperand &MO = MI.getOperand(OpNo);504 // If the destination is an immediate, divide by 4.505 if (MO.isImm()) return MO.getImm()>>2;506 507 assert(MO.isExpr() &&508 "getJumpTargetOpValue expects only expressions or an immediate");509 510 const MCExpr *Expr = MO.getExpr();511 addFixup(Fixups, 0, Expr, Mips::fixup_Mips_26);512 return 0;513}514 515unsigned MipsMCCodeEmitter::516getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,517 SmallVectorImpl<MCFixup> &Fixups,518 const MCSubtargetInfo &STI) const {519 const MCOperand &MO = MI.getOperand(OpNo);520 // If the destination is an immediate, divide by 2.521 if (MO.isImm()) return MO.getImm() >> 1;522 523 assert(MO.isExpr() &&524 "getJumpTargetOpValueMM expects only expressions or an immediate");525 526 const MCExpr *Expr = MO.getExpr();527 addFixup(Fixups, 0, Expr, Mips::fixup_MICROMIPS_26_S1);528 return 0;529}530 531unsigned MipsMCCodeEmitter::532getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,533 SmallVectorImpl<MCFixup> &Fixups,534 const MCSubtargetInfo &STI) const {535 const MCOperand &MO = MI.getOperand(OpNo);536 if (MO.isImm()) {537 // The immediate is encoded as 'immediate << 2'.538 unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);539 assert((Res & 3) == 0);540 return Res >> 2;541 }542 543 assert(MO.isExpr() &&544 "getUImm5Lsl2Encoding expects only expressions or an immediate");545 546 return 0;547}548 549unsigned MipsMCCodeEmitter::550getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,551 SmallVectorImpl<MCFixup> &Fixups,552 const MCSubtargetInfo &STI) const {553 const MCOperand &MO = MI.getOperand(OpNo);554 if (MO.isImm()) {555 int Value = MO.getImm();556 return Value >> 2;557 }558 559 return 0;560}561 562unsigned MipsMCCodeEmitter::563getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,564 SmallVectorImpl<MCFixup> &Fixups,565 const MCSubtargetInfo &STI) const {566 const MCOperand &MO = MI.getOperand(OpNo);567 if (MO.isImm()) {568 unsigned Value = MO.getImm();569 return Value >> 2;570 }571 572 return 0;573}574 575unsigned MipsMCCodeEmitter::576getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,577 SmallVectorImpl<MCFixup> &Fixups,578 const MCSubtargetInfo &STI) const {579 const MCOperand &MO = MI.getOperand(OpNo);580 if (MO.isImm()) {581 unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;582 return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));583 }584 585 return 0;586}587 588unsigned MipsMCCodeEmitter::589getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,590 const MCSubtargetInfo &STI) const {591 MCExpr::ExprKind Kind = Expr->getKind();592 if (Kind == MCExpr::Specifier) {593 const auto *MipsExpr = cast<MCSpecifierExpr>(Expr);594 595 Mips::Fixups FixupKind = Mips::Fixups(0);596 switch (MipsExpr->getSpecifier()) {597 case Mips::S_None:598 case Mips::S_Special:599 llvm_unreachable("Unhandled fixup kind!");600 break;601 case Mips::S_DTPREL:602 // MEK_DTPREL is used for marking TLS DIEExpr only603 // and contains a regular sub-expression.604 return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI);605 case Mips::S_CALL_HI16:606 FixupKind = Mips::fixup_Mips_CALL_HI16;607 break;608 case Mips::S_CALL_LO16:609 FixupKind = Mips::fixup_Mips_CALL_LO16;610 break;611 case Mips::S_DTPREL_HI:612 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16613 : Mips::fixup_Mips_DTPREL_HI;614 break;615 case Mips::S_DTPREL_LO:616 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16617 : Mips::fixup_Mips_DTPREL_LO;618 break;619 case Mips::S_GOTTPREL:620 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL621 : Mips::fixup_Mips_GOTTPREL;622 break;623 case Mips::S_GOT:624 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16625 : Mips::fixup_Mips_GOT;626 break;627 case Mips::S_GOT_CALL:628 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16629 : Mips::fixup_Mips_CALL16;630 break;631 case Mips::S_GOT_DISP:632 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP633 : Mips::fixup_Mips_GOT_DISP;634 break;635 case Mips::S_GOT_HI16:636 FixupKind = Mips::fixup_Mips_GOT_HI16;637 break;638 case Mips::S_GOT_LO16:639 FixupKind = Mips::fixup_Mips_GOT_LO16;640 break;641 case Mips::S_GOT_PAGE:642 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE643 : Mips::fixup_Mips_GOT_PAGE;644 break;645 case Mips::S_GOT_OFST:646 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST647 : Mips::fixup_Mips_GOT_OFST;648 break;649 case Mips::S_GPREL:650 FixupKind = Mips::fixup_Mips_GPREL16;651 break;652 case Mips::S_LO:653 // Check for %lo(%neg(%gp_rel(X)))654 if (Mips::isGpOff(*MipsExpr))655 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO656 : Mips::fixup_Mips_GPOFF_LO;657 else658 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16659 : Mips::fixup_Mips_LO16;660 break;661 case Mips::S_HIGHEST:662 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST663 : Mips::fixup_Mips_HIGHEST;664 break;665 case Mips::S_HIGHER:666 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER667 : Mips::fixup_Mips_HIGHER;668 break;669 case Mips::S_HI:670 // Check for %hi(%neg(%gp_rel(X)))671 if (Mips::isGpOff(*MipsExpr))672 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI673 : Mips::fixup_Mips_GPOFF_HI;674 else675 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16676 : Mips::fixup_Mips_HI16;677 break;678 case Mips::S_PCREL_HI16:679 FixupKind = Mips::fixup_MIPS_PCHI16;680 break;681 case Mips::S_PCREL_LO16:682 FixupKind = Mips::fixup_MIPS_PCLO16;683 break;684 case Mips::S_TLSGD:685 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD686 : Mips::fixup_Mips_TLSGD;687 break;688 case Mips::S_TLSLDM:689 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM690 : Mips::fixup_Mips_TLSLDM;691 break;692 case Mips::S_TPREL_HI:693 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16694 : Mips::fixup_Mips_TPREL_HI;695 break;696 case Mips::S_TPREL_LO:697 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16698 : Mips::fixup_Mips_TPREL_LO;699 break;700 case Mips::S_NEG:701 FixupKind =702 isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB;703 break;704 }705 addFixup(Fixups, 0, MipsExpr, MCFixupKind(FixupKind));706 return 0;707 }708 709 Ctx.reportError(Expr->getLoc(), "expected an immediate");710 return 0;711}712 713/// getMachineOpValue - Return binary encoding of operand. If the machine714/// operand requires relocation, record the relocation and return zero.715unsigned MipsMCCodeEmitter::716getMachineOpValue(const MCInst &MI, const MCOperand &MO,717 SmallVectorImpl<MCFixup> &Fixups,718 const MCSubtargetInfo &STI) const {719 if (MO.isReg()) {720 MCRegister Reg = MO.getReg();721 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);722 return RegNo;723 } else if (MO.isImm()) {724 return static_cast<unsigned>(MO.getImm());725 } else if (MO.isDFPImm()) {726 return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm()));727 }728 // TODO: Set EncoderMethod to "getImmOpValue" for imm Operand so that729 // getMachineOpValue will not be called for isExpr code paths.730 assert(MO.isExpr());731 return getImmOpValue(MI, MO, Fixups, STI);732}733 734unsigned MipsMCCodeEmitter::getImmOpValue(const MCInst &MI, const MCOperand &MO,735 SmallVectorImpl<MCFixup> &Fixups,736 const MCSubtargetInfo &STI) const {737 if (MO.isImm())738 return MO.getImm();739 assert(MO.isExpr() && "getImmOpValue expects only expressions or immediates");740 const MCExpr *Expr = MO.getExpr();741 int64_t Res;742 if (Expr->evaluateAsAbsolute(Res))743 return Res;744 unsigned MIFrm = MipsII::getFormat(MCII.get(MI.getOpcode()).TSFlags);745 if (!isa<MCSpecifierExpr>(Expr) && MIFrm == MipsII::FrmI) {746 addFixup(Fixups, 0, Expr, Mips::fixup_Mips_AnyImm16);747 return 0;748 }749 return getExprOpValue(Expr, Fixups, STI);750}751 752/// Return binary encoding of memory related operand.753/// If the offset operand requires relocation, record the relocation.754template <unsigned ShiftAmount>755unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,756 SmallVectorImpl<MCFixup> &Fixups,757 const MCSubtargetInfo &STI) const {758 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.759 assert(MI.getOperand(OpNo).isReg());760 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)761 << 16;762 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);763 764 // Apply the scale factor if there is one.765 OffBits >>= ShiftAmount;766 767 return (OffBits & 0xFFFF) | RegBits;768}769 770unsigned MipsMCCodeEmitter::771getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,772 SmallVectorImpl<MCFixup> &Fixups,773 const MCSubtargetInfo &STI) const {774 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.775 assert(MI.getOperand(OpNo).isReg());776 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),777 Fixups, STI) << 4;778 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),779 Fixups, STI);780 781 return (OffBits & 0xF) | RegBits;782}783 784unsigned MipsMCCodeEmitter::785getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,786 SmallVectorImpl<MCFixup> &Fixups,787 const MCSubtargetInfo &STI) const {788 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.789 assert(MI.getOperand(OpNo).isReg());790 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),791 Fixups, STI) << 4;792 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),793 Fixups, STI) >> 1;794 795 return (OffBits & 0xF) | RegBits;796}797 798unsigned MipsMCCodeEmitter::799getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,800 SmallVectorImpl<MCFixup> &Fixups,801 const MCSubtargetInfo &STI) const {802 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.803 assert(MI.getOperand(OpNo).isReg());804 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),805 Fixups, STI) << 4;806 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),807 Fixups, STI) >> 2;808 809 return (OffBits & 0xF) | RegBits;810}811 812unsigned MipsMCCodeEmitter::813getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,814 SmallVectorImpl<MCFixup> &Fixups,815 const MCSubtargetInfo &STI) const {816 // Register is encoded in bits 9-5, offset is encoded in bits 4-0.817 assert(MI.getOperand(OpNo).isReg() &&818 (MI.getOperand(OpNo).getReg() == Mips::SP ||819 MI.getOperand(OpNo).getReg() == Mips::SP_64) &&820 "Unexpected base register!");821 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),822 Fixups, STI) >> 2;823 824 return OffBits & 0x1F;825}826 827unsigned MipsMCCodeEmitter::828getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,829 SmallVectorImpl<MCFixup> &Fixups,830 const MCSubtargetInfo &STI) const {831 // Register is encoded in bits 9-7, offset is encoded in bits 6-0.832 assert(MI.getOperand(OpNo).isReg() &&833 MI.getOperand(OpNo).getReg() == Mips::GP &&834 "Unexpected base register!");835 836 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),837 Fixups, STI) >> 2;838 839 return OffBits & 0x7F;840}841 842unsigned MipsMCCodeEmitter::843getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,844 SmallVectorImpl<MCFixup> &Fixups,845 const MCSubtargetInfo &STI) const {846 // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.847 assert(MI.getOperand(OpNo).isReg());848 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,849 STI) << 16;850 unsigned OffBits =851 getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);852 853 return (OffBits & 0x1FF) | RegBits;854}855 856unsigned MipsMCCodeEmitter::857getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,858 SmallVectorImpl<MCFixup> &Fixups,859 const MCSubtargetInfo &STI) const {860 // Base register is encoded in bits 20-16, offset is encoded in bits 10-0.861 assert(MI.getOperand(OpNo).isReg());862 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,863 STI) << 16;864 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);865 866 return (OffBits & 0x07FF) | RegBits;867}868 869unsigned MipsMCCodeEmitter::870getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,871 SmallVectorImpl<MCFixup> &Fixups,872 const MCSubtargetInfo &STI) const {873 // opNum can be invalid if instruction had reglist as operand.874 // MemOperand is always last operand of instruction (base + offset).875 switch (MI.getOpcode()) {876 default:877 break;878 case Mips::SWM32_MM:879 case Mips::LWM32_MM:880 OpNo = MI.getNumOperands() - 2;881 break;882 }883 884 // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.885 assert(MI.getOperand(OpNo).isReg());886 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI)887 << 16;888 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);889 890 return (OffBits & 0x0FFF) | RegBits;891}892 893unsigned MipsMCCodeEmitter::894getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,895 SmallVectorImpl<MCFixup> &Fixups,896 const MCSubtargetInfo &STI) const {897 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.898 assert(MI.getOperand(OpNo).isReg());899 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,900 STI) << 16;901 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);902 903 return (OffBits & 0xFFFF) | RegBits;904}905 906unsigned MipsMCCodeEmitter::907getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,908 SmallVectorImpl<MCFixup> &Fixups,909 const MCSubtargetInfo &STI) const {910 // opNum can be invalid if instruction had reglist as operand911 // MemOperand is always last operand of instruction (base + offset)912 switch (MI.getOpcode()) {913 default:914 break;915 case Mips::SWM16_MM:916 case Mips::SWM16_MMR6:917 case Mips::LWM16_MM:918 case Mips::LWM16_MMR6:919 OpNo = MI.getNumOperands() - 2;920 break;921 }922 923 // Offset is encoded in bits 4-0.924 assert(MI.getOperand(OpNo).isReg());925 // Base register is always SP - thus it is not encoded.926 assert(MI.getOperand(OpNo+1).isImm());927 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);928 929 return ((OffBits >> 2) & 0x0F);930}931 932// FIXME: should be called getMSBEncoding933//934unsigned935MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,936 SmallVectorImpl<MCFixup> &Fixups,937 const MCSubtargetInfo &STI) const {938 assert(MI.getOperand(OpNo-1).isImm());939 assert(MI.getOperand(OpNo).isImm());940 unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);941 unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);942 943 return Position + Size - 1;944}945 946template <unsigned Bits, int Offset>947unsigned948MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,949 SmallVectorImpl<MCFixup> &Fixups,950 const MCSubtargetInfo &STI) const {951 assert(MI.getOperand(OpNo).isImm());952 unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);953 Value -= Offset;954 return Value;955}956 957unsigned958MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,959 SmallVectorImpl<MCFixup> &Fixups,960 const MCSubtargetInfo &STI) const {961 const MCOperand &MO = MI.getOperand(OpNo);962 if (MO.isImm()) {963 // The immediate is encoded as 'immediate << 2'.964 unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);965 assert((Res & 3) == 0);966 return Res >> 2;967 }968 969 assert(MO.isExpr() &&970 "getSimm19Lsl2Encoding expects only expressions or an immediate");971 972 const MCExpr *Expr = MO.getExpr();973 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2974 : Mips::fixup_MIPS_PC19_S2;975 addFixup(Fixups, 0, Expr, MCFixupKind(FixupKind));976 return 0;977}978 979unsigned980MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,981 SmallVectorImpl<MCFixup> &Fixups,982 const MCSubtargetInfo &STI) const {983 const MCOperand &MO = MI.getOperand(OpNo);984 if (MO.isImm()) {985 // The immediate is encoded as 'immediate << 3'.986 unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);987 assert((Res & 7) == 0);988 return Res >> 3;989 }990 991 assert(MO.isExpr() &&992 "getSimm18Lsl2Encoding expects only expressions or an immediate");993 994 const MCExpr *Expr = MO.getExpr();995 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3996 : Mips::fixup_MIPS_PC18_S3;997 addFixup(Fixups, 0, Expr, MCFixupKind(FixupKind));998 return 0;999}1000 1001unsigned1002MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,1003 SmallVectorImpl<MCFixup> &Fixups,1004 const MCSubtargetInfo &STI) const {1005 assert(MI.getOperand(OpNo).isImm());1006 const MCOperand &MO = MI.getOperand(OpNo);1007 return MO.getImm() % 8;1008}1009 1010unsigned1011MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,1012 SmallVectorImpl<MCFixup> &Fixups,1013 const MCSubtargetInfo &STI) const {1014 assert(MI.getOperand(OpNo).isImm());1015 const MCOperand &MO = MI.getOperand(OpNo);1016 unsigned Value = MO.getImm();1017 switch (Value) {1018 case 128: return 0x0;1019 case 1: return 0x1;1020 case 2: return 0x2;1021 case 3: return 0x3;1022 case 4: return 0x4;1023 case 7: return 0x5;1024 case 8: return 0x6;1025 case 15: return 0x7;1026 case 16: return 0x8;1027 case 31: return 0x9;1028 case 32: return 0xa;1029 case 63: return 0xb;1030 case 64: return 0xc;1031 case 255: return 0xd;1032 case 32768: return 0xe;1033 case 65535: return 0xf;1034 }1035 llvm_unreachable("Unexpected value");1036}1037 1038unsigned1039MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,1040 SmallVectorImpl<MCFixup> &Fixups,1041 const MCSubtargetInfo &STI) const {1042 unsigned res = 0;1043 1044 // Register list operand is always first operand of instruction and it is1045 // placed before memory operand (register + imm).1046 1047 for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {1048 MCRegister Reg = MI.getOperand(I).getReg();1049 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);1050 if (RegNo != 31)1051 res++;1052 else1053 res |= 0x10;1054 }1055 return res;1056}1057 1058unsigned1059MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,1060 SmallVectorImpl<MCFixup> &Fixups,1061 const MCSubtargetInfo &STI) const {1062 return (MI.getNumOperands() - 4);1063}1064 1065unsigned1066MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,1067 SmallVectorImpl<MCFixup> &Fixups,1068 const MCSubtargetInfo &STI) const {1069 unsigned res = 0;1070 1071 if (MI.getOperand(0).getReg() == Mips::A1 &&1072 MI.getOperand(1).getReg() == Mips::A2)1073 res = 0;1074 else if (MI.getOperand(0).getReg() == Mips::A1 &&1075 MI.getOperand(1).getReg() == Mips::A3)1076 res = 1;1077 else if (MI.getOperand(0).getReg() == Mips::A2 &&1078 MI.getOperand(1).getReg() == Mips::A3)1079 res = 2;1080 else if (MI.getOperand(0).getReg() == Mips::A0 &&1081 MI.getOperand(1).getReg() == Mips::S5)1082 res = 3;1083 else if (MI.getOperand(0).getReg() == Mips::A0 &&1084 MI.getOperand(1).getReg() == Mips::S6)1085 res = 4;1086 else if (MI.getOperand(0).getReg() == Mips::A0 &&1087 MI.getOperand(1).getReg() == Mips::A1)1088 res = 5;1089 else if (MI.getOperand(0).getReg() == Mips::A0 &&1090 MI.getOperand(1).getReg() == Mips::A2)1091 res = 6;1092 else if (MI.getOperand(0).getReg() == Mips::A0 &&1093 MI.getOperand(1).getReg() == Mips::A3)1094 res = 7;1095 1096 return res;1097}1098 1099unsigned1100MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo,1101 SmallVectorImpl<MCFixup> &Fixups,1102 const MCSubtargetInfo &STI) const {1103 assert(((OpNo == 2) || (OpNo == 3)) &&1104 "Unexpected OpNo for movep operand encoding!");1105 1106 MCOperand Op = MI.getOperand(OpNo);1107 assert(Op.isReg() && "Operand of movep is not a register!");1108 switch (Op.getReg().id()) {1109 default:1110 llvm_unreachable("Unknown register for movep!");1111 case Mips::ZERO: return 0;1112 case Mips::S1: return 1;1113 case Mips::V0: return 2;1114 case Mips::V1: return 3;1115 case Mips::S0: return 4;1116 case Mips::S2: return 5;1117 case Mips::S3: return 6;1118 case Mips::S4: return 7;1119 }1120}1121 1122unsigned1123MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,1124 SmallVectorImpl<MCFixup> &Fixups,1125 const MCSubtargetInfo &STI) const {1126 const MCOperand &MO = MI.getOperand(OpNo);1127 assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");1128 // The immediate is encoded as 'immediate >> 2'.1129 unsigned Res = static_cast<unsigned>(MO.getImm());1130 assert((Res & 3) == 0);1131 return Res >> 2;1132}1133 1134#include "MipsGenMCCodeEmitter.inc"1135