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;
}
Exemple #2
0
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;
}
Exemple #3
0
// 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);
}
Exemple #4
0
// 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;
}
Exemple #7
0
static InstTransResult doBswapR(InstPtr ip,   BasicBlock *&b,
                            const MCOperand &reg) 
{
    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;
}
Exemple #12
0
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;
}
Exemple #13
0
/// 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());
}
Exemple #14
0
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);
}
Exemple #16
0
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);
  }
}
Exemple #17
0
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;
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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;
}
Exemple #28
0
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);
}
Exemple #30
0
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;
}