unsigned SparcMCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return MO.getImm(); assert(MO.isExpr()); const MCExpr *Expr = MO.getExpr(); if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); Fixups.push_back(MCFixup::create(0, Expr, Kind)); return 0; } int64_t Res; if (Expr->evaluateAsAbsolute(Res)) return Res; llvm_unreachable("Unhandled expression!"); return 0; }
uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) { if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags)) return MRI.getEncodingValue(MO.getReg()); return getHWReg(MO.getReg()); } if (MO.isExpr()) { const MCSymbolRefExpr *Expr = cast<MCSymbolRefExpr>(MO.getExpr()); // We put rodata at the end of code section, then map the entire // code secetion as vtx buf. Thus the section relative address is the // correct one. // Each R600 literal instruction has two operands // We can't easily get the order of the current one, so compare against // the first one and adjust offset. const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4; Fixups.push_back(MCFixup::create(offset, Expr, FK_SecRel_4, MI.getLoc())); return 0; } assert(MO.isImm()); return MO.getImm(); }
// Expand PseudoCALL and PseudoTAIL to AUIPC and JALR with relocation types. // We expand PseudoCALL and PseudoTAIL while encoding, meaning AUIPC and JALR // won't go through RISCV MC to MC compressed instruction transformation. This // is acceptable because AUIPC has no 16-bit form and C_JALR have no immediate // operand field. We let linker relaxation deal with it. When linker // relaxation enabled, AUIPC and JALR have chance relax to JAL. If C extension // is enabled, JAL has chance relax to C_JAL. void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { MCInst TmpInst; MCOperand Func = MI.getOperand(0); unsigned Ra = (MI.getOpcode() == RISCV::PseudoTAIL) ? RISCV::X6 : RISCV::X1; uint32_t Binary; assert(Func.isExpr() && "Expected expression"); const MCExpr *CallExpr = Func.getExpr(); // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type. TmpInst = MCInstBuilder(RISCV::AUIPC) .addReg(Ra) .addOperand(MCOperand::createExpr(CallExpr)); Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); support::endian::write(OS, Binary, support::little); if (MI.getOpcode() == RISCV::PseudoTAIL) // Emit JALR X0, X6, 0 TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0); else // Emit JALR X1, X1, 0 TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0); Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); support::endian::write(OS, Binary, support::little); }
void SystemZInstPrinter::printOperand(const MCOperand &MO, raw_ostream &O) { if (MO.isReg()) O << '%' << getRegisterName(MO.getReg()); else if (MO.isImm()) O << MO.getImm(); else if (MO.isExpr()) O << *MO.getExpr(); else llvm_unreachable("Invalid operand"); }
void ARM64InstPrinter::printAMIndexed(const MCInst *MI, unsigned OpNum, unsigned Scale, raw_ostream &O) { const MCOperand MO1 = MI->getOperand(OpNum + 1); O << '[' << getRegisterName(MI->getOperand(OpNum).getReg()); if (MO1.isImm()) { if (MO1.getImm() != 0) O << ", #" << (MO1.getImm() * Scale); } else { assert (MO1.isExpr() && "Unexpected operand type!"); O << ", " << *MO1.getExpr(); } O << ']'; }
MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst, MCOperand const &MO) { assert(HexagonMCInstrInfo::isExtendable(MCII, Inst) || HexagonMCInstrInfo::isExtended(MCII, Inst)); MCInst XMI; XMI.setOpcode(Hexagon::A4_ext); if (MO.isImm()) XMI.addOperand(MCOperand::createImm(MO.getImm() & (~0x3f))); else if (MO.isExpr()) XMI.addOperand(MCOperand::createExpr(MO.getExpr())); else llvm_unreachable("invalid extendable operand"); return XMI; }
// @LOCALMOD-BEGIN // Unlike LowerARMMachineInstrToMCInst, the opcode has already been set. // Otherwise, this is like LowerARMMachineInstrToMCInst, but with special // handling where the "immediate" is PC Relative // (used for MOVi16PIC / MOVTi16PIC, etc. -- see .td file) void llvm::LowerARMMachineInstrToMCInstPCRel(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP, unsigned ImmIndex, unsigned PCIndex, MCSymbol *PCLabel, unsigned PCAdjustment) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { if (i == ImmIndex) { MCContext &Ctx = AP.OutContext; const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, Ctx); if (PCAdjustment) { const MCExpr *AdjExpr = MCConstantExpr::Create(PCAdjustment, Ctx); PCRelExpr = MCBinaryExpr::CreateAdd(PCRelExpr, AdjExpr, Ctx); } // Get the usual symbol operand, then subtract the PCRelExpr. const MachineOperand &MOImm = MI->getOperand(ImmIndex); MCOperand SymOp; bool DidLower = AP.lowerOperand(MOImm, SymOp); assert (DidLower && "Immediate-like operand should have been lowered"); const MCExpr *Expr = SymOp.getExpr(); ARMMCExpr::VariantKind TargetKind = ARMMCExpr::VK_ARM_None; /* Unwrap and rewrap the ARMMCExpr */ if (Expr->getKind() == MCExpr::Target) { const ARMMCExpr *TargetExpr = cast<ARMMCExpr>(Expr); TargetKind = TargetExpr->getKind(); Expr = TargetExpr->getSubExpr(); } Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, Ctx); if (TargetKind != ARMMCExpr::VK_ARM_None) { Expr = ARMMCExpr::Create(TargetKind, Expr, Ctx); } MCOperand MCOp = MCOperand::CreateExpr(Expr); OutMI.addOperand(MCOp); } else if (i == PCIndex) { // dummy index already handled as PCLabel continue; } else { MCOperand MCOp; if (AP.lowerOperand(MI->getOperand(i), MCOp)) { OutMI.addOperand(MCOp); } } } }
/// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned Cpu0MCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) { unsigned Reg = MO.getReg(); unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); return RegNo; } else if (MO.isImm()) { return static_cast<unsigned>(MO.getImm()); } else if (MO.isFPImm()) { return static_cast<unsigned>(APFloat(MO.getFPImm()) .bitcastToAPInt().getHiBits(32).getLimitedValue()); } // MO must be an Expr. assert(MO.isExpr()); return getExprOpValue(MO.getExpr(),Fixups, STI); }
void SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCOperand MCRegOp = Inst.getOperand(0); MCOperand MCValOp = Inst.getOperand(1); assert(MCRegOp.isReg()); assert(MCValOp.isImm() || MCValOp.isExpr()); // the imm operand can be either an expression or an immediate. bool IsImm = Inst.getOperand(1).isImm(); uint64_t ImmValue = IsImm ? MCValOp.getImm() : 0; const MCExpr *ValExpr; if (IsImm) ValExpr = MCConstantExpr::Create(ImmValue, getContext()); else ValExpr = MCValOp.getExpr(); MCOperand PrevReg = MCOperand::createReg(Sparc::G0); if (!IsImm || (ImmValue & ~0x1fff)) { MCInst TmpInst; const MCExpr *Expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_HI, ValExpr, getContext()); TmpInst.setLoc(IDLoc); TmpInst.setOpcode(SP::SETHIi); TmpInst.addOperand(MCRegOp); TmpInst.addOperand(MCOperand::createExpr(Expr)); Instructions.push_back(TmpInst); PrevReg = MCRegOp; } if (!IsImm || ((ImmValue & 0x1fff) != 0 || ImmValue == 0)) { MCInst TmpInst; const MCExpr *Expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_LO, ValExpr, getContext()); TmpInst.setLoc(IDLoc); TmpInst.setOpcode(SP::ORri); TmpInst.addOperand(MCRegOp); TmpInst.addOperand(PrevReg); TmpInst.addOperand(MCOperand::createExpr(Expr)); Instructions.push_back(TmpInst); } }
// Expand PseudoAddTPRel to a simple ADD with the correct relocation. void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { MCOperand DestReg = MI.getOperand(0); MCOperand SrcReg = MI.getOperand(1); MCOperand TPReg = MI.getOperand(2); assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 && "Expected thread pointer as second input to TP-relative add"); MCOperand SrcSymbol = MI.getOperand(3); assert(SrcSymbol.isExpr() && "Expected expression as third input to TP-relative add"); const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr()); assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD && "Expected tprel_add relocation on TP-relative symbol"); // Emit the correct tprel_add relocation for the symbol. Fixups.push_back(MCFixup::create( 0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc())); // Emit fixup_riscv_relax for tprel_add where the relax feature is enabled. if (STI.getFeatureBits()[RISCV::FeatureRelax]) { const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); Fixups.push_back(MCFixup::create( 0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc())); } // Emit a normal ADD instruction with the given operands. MCInst TmpInst = MCInstBuilder(RISCV::ADD) .addOperand(DestReg) .addOperand(SrcReg) .addOperand(TPReg); uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); support::endian::write(OS, Binary, support::little); }
bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { MCOperand MCRegOp = Inst.getOperand(0); MCOperand MCValOp = Inst.getOperand(1); assert(MCRegOp.isReg()); assert(MCValOp.isImm() || MCValOp.isExpr()); // the imm operand can be either an expression or an immediate. bool IsImm = Inst.getOperand(1).isImm(); int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0; // Allow either a signed or unsigned 32-bit immediate. if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) { return Error(IDLoc, "set: argument must be between -2147483648 and 4294967295"); } // If the value was expressed as a large unsigned number, that's ok. // We want to see if it "looks like" a small signed number. int32_t ImmValue = RawImmValue; // For 'set' you can't use 'or' with a negative operand on V9 because // that would splat the sign bit across the upper half of the destination // register, whereas 'set' is defined to zero the high 32 bits. bool IsEffectivelyImm13 = IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096); const MCExpr *ValExpr; if (IsImm) ValExpr = MCConstantExpr::create(ImmValue, getContext()); else ValExpr = MCValOp.getExpr(); MCOperand PrevReg = MCOperand::createReg(Sparc::G0); // If not just a signed imm13 value, then either we use a 'sethi' with a // following 'or', or a 'sethi' by itself if there are no more 1 bits. // In either case, start with the 'sethi'. if (!IsEffectivelyImm13) { MCInst TmpInst; const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr); TmpInst.setLoc(IDLoc); TmpInst.setOpcode(SP::SETHIi); TmpInst.addOperand(MCRegOp); TmpInst.addOperand(MCOperand::createExpr(Expr)); Instructions.push_back(TmpInst); PrevReg = MCRegOp; } // The low bits require touching in 3 cases: // * A non-immediate value will always require both instructions. // * An effectively imm13 value needs only an 'or' instruction. // * Otherwise, an immediate that is not effectively imm13 requires the // 'or' only if bits remain after clearing the 22 bits that 'sethi' set. // If the low bits are known zeros, there's nothing to do. // In the second case, and only in that case, must we NOT clear // bits of the immediate value via the %lo() assembler function. // Note also, the 'or' instruction doesn't mind a large value in the case // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean. if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) { MCInst TmpInst; const MCExpr *Expr; if (IsEffectivelyImm13) Expr = ValExpr; else Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr); TmpInst.setLoc(IDLoc); TmpInst.setOpcode(SP::ORri); TmpInst.addOperand(MCRegOp); TmpInst.addOperand(PrevReg); TmpInst.addOperand(MCOperand::createExpr(Expr)); Instructions.push_back(TmpInst); } return false; }