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; }
/// 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; }
unsigned Disassembler::decodeInstruction(unsigned Address, MachineBasicBlock *Block) { // Disassemble instruction const MCDisassembler *DA = MC->getMCDisassembler(); uint64_t InstSize; MCInst *Inst = new MCInst(); StringRef Bytes; if (!(DA->getInstruction(*Inst, InstSize, *CurSectionMemory, Address, nulls(), nulls()))) { printError("Unknown instruction encountered, instruction decode failed!"); return 1; // Instructions[Address] = NULL; // Block->push_back(NULL); // TODO: Replace with default size for each target. // return 1; // outs() << format("%8" PRIx64 ":\t", SectAddr + Index); // Dism->rawBytesToString(StringRef(Bytes.data() + Index, Size)); // outs() << " unkn\n"; } Instructions[Address] = Inst; // Recover Instruction information const MCInstrInfo *MII = MC->getMCInstrInfo(); MCInstrDesc *MCID = new MCInstrDesc(MII->get(Inst->getOpcode())); MCID->Size = InstSize; // Check if the instruction can load to program counter and mark it as a Ret // FIXME: Better analysis would be to see if the PC value references memory // sent as a parameter or set locally in the function, but that would need to // happen after decompilation. In either case, this is definitely a BB // terminator or branch! if (MCID->mayLoad() && MCID->mayAffectControlFlow(*Inst, *MC->getMCRegisterInfo())) { MCID->Flags |= (1 << MCID::Return); MCID->Flags |= (1 << MCID::Terminator); } // Recover MachineInstr representation DebugLoc *Location = setDebugLoc(Address); MachineInstrBuilder MIB = BuildMI(Block, *Location, *MCID); unsigned int numDefs = MCID->getNumDefs(); for (unsigned int i = 0; i < Inst->getNumOperands(); i++) { MCOperand MCO = Inst->getOperand(i); // FIXME: This hack is a workaround for the assert in MachineInstr.cpp:653, // where OpNo >= MCID->getNumOperands()... if (i >= MCID->getNumOperands() && !(MCID->isVariadic())) break; if (MCO.isReg()) { unsigned flags = 0; // Defs always start at the beginning of the operands list, // unfortunately BuildMI doesn't set default define flags so we have // to do it manually here. // NOTE: This should always be true, but might not be if operands list // is not populated correctly by the MC Backend for the target. if (i < numDefs) { flags |= RegState::Define; } // NOTE: No need to worry about imp defs and uses, as these are already // specificed in the MCID attached to the MachineInst object. MIB.addReg(MCO.getReg(), flags); continue; } if (MCO.isImm()) { MIB.addImm(MCO.getImm()); continue; } //else if (MCO.isFPImm()) MIB.addFPImm(MCO.getFPImm()); if (MCO.isExpr()) { MCOperandInfo MCOpInfo = MCID->OpInfo[i]; switch (MCOpInfo.OperandType) { case MCOI::OPERAND_MEMORY: case MCOI::OPERAND_PCREL: case MCOI::OPERAND_UNKNOWN: default: printError("Unknown how to handle this Expression at this time."); } } printError("Unknown how to handle Operand!"); } // NOTE: I tried MCOpInfo here, and it appearst o be NULL // ... at least for ARM. unsigned flags = 0; if (MCID->mayLoad()) flags |= MachineMemOperand::MOLoad; if (MCID->mayStore()) flags |= MachineMemOperand::MOStore; if (flags != 0) { // Constant* cInt = ConstantInt::get(Type::getInt64Ty(ctx), MCO.getImm()); // Value *Val = ConstantExpr::getIntToPtr(cInt, // PointerType::getUnqual(Type::getInt32Ty(ctx))); // FIXME: note size of 4 is known to be bad for // some targets //Copy & paste set getImm to zero MachineMemOperand* MMO = new MachineMemOperand( MachinePointerInfo(), flags, 4, 0); //MCO.getImm() MIB.addMemOperand(MMO); //outs() << "Name: " << MII->getName(Inst->getOpcode()) << " Flags: " << flags << "\n"; } // Note: I don't know why they decided instruction size needed to be 64 bits, // but the following conversion shouldn't be an issue. return ((unsigned)InstSize); }