static InstTransResult doIMulR(InstPtr ip, BasicBlock *&b, const MCOperand &src) { NASSERT(src.isReg()); Value *res = doIMulV<width>(ip, b, R_READ<width>(b, src.getReg())); Type *t = Type::getIntNTy(b->getContext(), width); Value *res_sh = BinaryOperator::Create(Instruction::LShr, res, CONST_V<width*2>(b, width), "", b); Value *wrAX = new TruncInst(res, t, "", b); Value *wrDX = new TruncInst(res_sh, t, "", b); switch(width) { case 8: R_WRITE<width>(b, X86::AH, wrDX); R_WRITE<width>(b, X86::AL, wrAX); break; case 16: R_WRITE<width>(b, X86::DX, wrDX); R_WRITE<width>(b, X86::AX, wrAX); break; case 32: R_WRITE<width>(b, X86::EDX, wrDX); R_WRITE<width>(b, X86::EAX, wrAX); break; default: throw TErr(__LINE__, __FILE__, "Not supported width"); } return ContinueBlock; }
static InstTransResult doMovZXRM(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *src) { NASSERT(dst.isReg()); NASSERT(src != NULL); if( dstWidth == 32 && srcWidth == 8 && ip->has_jump_index_table()) { doJumpIndexTableViaSwitch(b, ip); return ContinueBlock; } //do a read from src of the appropriate width Value *fromSrc = M_READ<srcWidth>(ip, b, src); //extend Type *toT = Type::getIntNTy(b->getContext(), dstWidth); Value *xt = new ZExtInst(fromSrc, toT, "", b); //write into dst R_WRITE<dstWidth>(b, dst.getReg(), xt); return ContinueBlock; }
// 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); }
// assume the immediate references code if: // * we are dealing with a fully linked ELF // * The immediate is in the range of a valid code or data section static bool setHeuristicRef(ExecutableContainer *c, InstPtr I, int opnum, stack<VA> &funcs, raw_ostream &out, const std::string whichInst) { MCOperand op; std::string imp_name; ElfTarget *elft = dynamic_cast<ElfTarget*>(c); op = I->get_inst().getOperand(opnum); LASSERT(op.isImm(), "No immediate operand for " + whichInst); VA imm = op.getImm(); if(elft && elft->isLinked()) { if (elft->is_in_code(imm)) { // this instruction references code I->set_call_tgt(imm); // make sure we disassemble at this new address funcs.push(imm); out << "Found new function entry from " << whichInst << ": " << to_string<VA>(imm, hex) << "\n"; return true; } else if (elft->is_in_data(imm)) { out << "Adding local data ref to: " << to_string<VA>(imm, hex) << "\n"; I->set_data_offset(imm); } else if (c->find_import_name(imm, imp_name)) { out << "Import name is: " << imp_name << "\n"; } } return false; }
static InstTransResult MOVAndZextRR(BasicBlock *& block, const MCOperand &dst, const MCOperand &src) { NASSERT(src.isReg()); Value *src_val = R_READ<width>(block, src.getReg()); return MOVAndZextRV<width>(block, dst, src_val); }
static InstTransResult doXaddRM(InstPtr ip, BasicBlock *&b, const MCOperand &srcReg, Value *dstAddr) { NASSERT(srcReg.isReg()); NASSERT(dstAddr != NULL); Value *reg_v = R_READ<width>(b, srcReg.getReg()); Value *mem_v = M_READ<width>(ip, b, dstAddr); Value *res = BinaryOperator::CreateAdd(reg_v, mem_v, "", b); M_WRITE<width>(ip, b, dstAddr, res); R_WRITE<width>(b, srcReg.getReg(), mem_v); //write the flag updates //compute AF WriteAFAddSub<width>(b, res, mem_v, reg_v); //compute SF WriteSF<width>(b, res); //compute ZF WriteZF<width>(b, res); //compute OF WriteOFAdd<width>(b, res, mem_v, reg_v); //compute PF WritePF<width>(b, res); //compute CF*/ WriteCFAdd<width>(b, res, mem_v); return ContinueBlock; }
static InstTransResult doBswapR(InstPtr ip, BasicBlock *&b, const MCOperand ®) { TASSERT(reg.isReg(), ""); if(width != 32) { throw TErr(__LINE__, __FILE__, "Width not supported"); } Value *tmp = R_READ<width>(b, reg.getReg()); // Create the new bytes from the original value Value *newByte1 = BinaryOperator::CreateShl(tmp, CONST_V<width>(b, 24), "", b); Value *newByte2 = BinaryOperator::CreateShl(BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x0000FF00), "", b), CONST_V<width>(b, 8), "", b); Value *newByte3 = BinaryOperator::CreateLShr(BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x00FF0000), "", b), CONST_V<width>(b, 8), "", b); Value *newByte4 = BinaryOperator::CreateLShr(tmp, CONST_V<width>(b, 24), "", b); // Add the bytes together to make the resulting DWORD Value *res = BinaryOperator::CreateAdd(newByte1, newByte2, "", b); res = BinaryOperator::CreateAdd(res, newByte3, "", b); res = BinaryOperator::CreateAdd(res, newByte4, "", b); R_WRITE<width>(b, reg.getReg(), res); return ContinueBlock; }
static InstTransResult doCmpxchgRR(InstPtr ip, BasicBlock *&b, const MCOperand &dstReg, const MCOperand &srcReg) { NASSERT(dstReg.isReg()); NASSERT(srcReg.isReg()); Value *acc; switch(width) { case 8: acc = R_READ<width>(b, X86::AL); break; case 16: acc = R_READ<width>(b, X86::AX); break; case 32: acc = R_READ<width>(b, X86::EAX); break; default: throw TErr(__LINE__, __FILE__, "Width not supported"); } Value *dstReg_v = R_READ<width>(b, dstReg.getReg()); Value *srcReg_v = R_READ<width>(b, srcReg.getReg()); doCmpVV<width>(ip, b, acc, dstReg_v); Value *Cmp = new ICmpInst(*b, CmpInst::ICMP_EQ, acc, dstReg_v); F_WRITE(b, ZF, Cmp); /// // ZF = Acc == DST // acc = select(ZF, acc, dst) // dst = select(ZF, src, dst) Value *new_acc = SelectInst::Create(Cmp, acc, dstReg_v, "", b); Value *new_dst = SelectInst::Create(Cmp, srcReg_v, dstReg_v, "", b); R_WRITE<width>(b, dstReg.getReg(), new_dst); switch(width) { case 8: R_WRITE<width>(b, X86::AL, new_acc); break; case 16: R_WRITE<width>(b, X86::AX, new_acc); break; case 32: R_WRITE<width>(b, X86::EAX, new_acc); break; default: throw TErr(__LINE__, __FILE__, "Width not supported"); } return ContinueBlock; }
static InstTransResult doPSLLri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(src.isImm()); Value *shift_count = CONST_V<128>(b, src.getImm()); return doNewShift<width, Instruction::Shl>(b, dst, shift_count, CONST_V<128>(b, 0)); }
static InstTransResult doPSRArr(BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(src.isReg()); Value *shift_count = R_READ<128>(b, src.getReg()); return doNewShift<width, Instruction::AShr>(b, dst, shift_count, nullptr); }
static InstTransResult doMulR(InstPtr ip, BasicBlock *&b, const MCOperand &src) { NASSERT(src.isReg()); doMulV<width>(ip, b, R_READ<width>(b, src.getReg())); return ContinueBlock; }
static InstTransResult doCMOV(BasicBlock *b, MCOperand &dst, Value *condition, Value *newval) { Value *orig = R_READ<width>(b, dst.getReg()); Value *to_write = CHOOSE_IF(b, condition, newval, orig); R_WRITE<width>(b, dst.getReg(), to_write); return ContinueBlock; }
/// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); assert(MO.isImm() && "did not expect relocated expression"); return static_cast<unsigned>(MO.getImm()); }
static InstTransResult doMIMov(InstPtr ip, BasicBlock *&b, Value *dstAddr, const MCOperand &src) { //MOV <m>, <imm> //store the constant in src into dstAddr NASSERT(dstAddr != NULL); NASSERT(src.isImm()); return doMIMovV<width>(ip, b, dstAddr, CONST_V<width>(b, src.getImm())); }
static InstTransResult do_SSE_RM(InstPtr ip, BasicBlock *& block, const MCOperand &o1, Value *addr) { NASSERT(o1.isReg()); Value *opVal1 = R_READ<fpwidth>(block, o1.getReg()); Value *opVal2 = M_READ<fpwidth>(ip, block, addr); return do_SSE_VV<fpwidth, bin_op>(o1.getReg(), block, opVal1, opVal2); }
void XCoreMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); MCOperand MCOp = LowerOperand(MO); if (MCOp.isValid()) OutMI.addOperand(MCOp); } }
static InstTransResult doRSMov(InstPtr ip, BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(dst.isReg()); NASSERT(src.isReg()); Value *seg_val = getSegmentValue<width>(b, src.getReg()); R_WRITE<width>(b, dst.getReg(), seg_val); return ContinueBlock; }
static InstTransResult doDivR(InstPtr ip, BasicBlock *&b, const MCOperand &div) { NASSERT(div.isReg()); Value *reg_v = R_READ<width>(b, div.getReg()); doDivV<width>(ip, b, reg_v, Instruction::UDiv); return ContinueBlock; }
static InstTransResult MOVAndZextRV(BasicBlock *& block, const MCOperand &dst, Value *src) { NASSERT(dst.isReg()); Value *zext = new llvm::ZExtInst(src, llvm::Type::getIntNTy(block->getContext(), 128), "", block); R_WRITE<128>(block, dst.getReg(), zext); return ContinueBlock; }
static InstTransResult do_SSE_INT_RR(InstPtr ip, BasicBlock *& block, const MCOperand &o1, const MCOperand &o2) { NASSERT(o1.isReg()); NASSERT(o2.isReg()); Value *opVal1 = R_READ<width>(block, o1.getReg()); Value *opVal2 = R_READ<width>(block, o2.getReg()); return do_SSE_INT_VV<width, bin_op>(o1.getReg(), block, opVal1, opVal2); }
static InstTransResult doUCOMISrm(InstPtr ip, BasicBlock *&b, const MCOperand &op1, Value *memAddr) { NASSERT(op1.isReg()); Value *op1_val = R_READ<width>(b, op1.getReg()); Value *op2_val = M_READ<width>(ip, b, memAddr); Value *fp1_val = INT_AS_FP<width>(b, op1_val); Value *fp2_val = INT_AS_FP<width>(b, op2_val); return doUCOMISvv(b, fp1_val, fp2_val); }
static InstTransResult doPEXTRWmr(InstPtr ip, BasicBlock *&b, Value *memAddr, const MCOperand &src, const MCOperand &order) { NASSERT(src.isReg()); NASSERT(order.isImm()); Value *vec = R_READ<128>(b, src.getReg()); Value *item = doExtraction<128,16>(b, vec, order.getImm()); M_WRITE<16>(ip, b, memAddr, item); return ContinueBlock; }
static InstTransResult doMRMov(InstPtr ip, BasicBlock *&b, Value *dstAddr, const MCOperand &src) { //MOV <mem>, <r> NASSERT(src.isReg()); NASSERT(dstAddr != NULL); M_WRITE<width>(ip, b, dstAddr, R_READ<width>(b, src.getReg())); return ContinueBlock; }
static InstTransResult doNotR(InstPtr ip, BasicBlock *&b, const MCOperand &o) { TASSERT(o.isReg(), ""); Value *r = R_READ<width>(b, o.getReg()); Value *res = doNotV<width>(ip, b, r); R_WRITE<width>(b, o.getReg(), res); return ContinueBlock; }
static InstTransResult doMovSXRM(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *src) { NASSERT(dst.isReg()); NASSERT(src != NULL); Value *r = doMovSXV<dstWidth>(ip, b, M_READ<srcWidth>(ip, b, src)); R_WRITE<dstWidth>(b, dst.getReg(), r); return ContinueBlock; }
void SampleMCInstLower:: Lower(const MachineInstr *MI, MCInst &OutMI) const { DEBUG(dbgs() << ">> SampleMCInstLower::Lower <<\n"); OutMI.setOpcode(MI->getOpcode()); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); MCOperand MCOp = LowerOperand(MO); if (MCOp.isValid()) OutMI.addOperand(MCOp); } }
static InstTransResult doPSHUFDmi(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *mem_addr, const MCOperand &order) { NASSERT(dst.isReg()); NASSERT(order.isImm()); Value *input = M_READ<128>(ip, b, mem_addr); Value *shuffled = doShuffle<128,32>(b, input, order.getImm()); R_WRITE<128>(b, dst.getReg(), shuffled); return ContinueBlock; }
static InstTransResult doRIMov(InstPtr ip, BasicBlock *&b, const MCOperand &src, const MCOperand &dst) { //MOV <r>, <imm> NASSERT(src.isImm()); NASSERT(dst.isReg()); //write the constant into the supplied register R_WRITE<width>(b, dst.getReg(), CONST_V<width>(b, src.getImm())); return ContinueBlock; }
static InstTransResult doPUNPCKrr( BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(dst.isReg()); NASSERT(src.isReg()); Value *srcVal = R_READ<width>(b, src.getReg()); Value *dstVal = R_READ<width>(b, dst.getReg()); return doPUNPCKVV<width, slice_width>(b, dst, srcVal, dstVal); }
static InstTransResult doMSMov(InstPtr ip, BasicBlock *&b, Value *dstAddr, const MCOperand &src) { NASSERT(dstAddr != NULL); NASSERT(src.isReg()); Value *seg_val = getSegmentValue<width>(b, src.getReg()); M_WRITE<width>(ip, b, dstAddr, seg_val); return ContinueBlock; }