static InstTransResult doSubRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst, const MCOperand &src1, const MCOperand &src2) { NASSERT(src1.isReg()); NASSERT(src2.isImm()); NASSERT(dst.isReg()); // Read from src1. Value *srcReg = R_READ<dstWidth>(b, src1.getReg()); // Create the constant value. Value *c = CONST_V<srcWidth>(b, src2.getImm()); CastInst *cInst = CastInst::CreateIntegerCast(c, srcReg->getType(), true, "", b); // Do the operation. Value *subRes = doSubVV<dstWidth>(ip, b, srcReg, cInst); // Store the result in dst. R_WRITE<dstWidth>(b, dst.getReg(), subRes); return ContinueBlock; }
static InstTransResult doXaddRR(InstPtr ip, BasicBlock *&b, const MCOperand &dstReg, const MCOperand &srcReg) { NASSERT(dstReg.isReg()); NASSERT(srcReg.isReg()); Value *dstReg_v = R_READ<width>(b, dstReg.getReg()); Value *srcReg_v = R_READ<width>(b, srcReg.getReg()); Value *res = BinaryOperator::CreateAdd(dstReg_v, srcReg_v, "", b); R_WRITE<width>(b, dstReg.getReg(), res); R_WRITE<width>(b, srcReg.getReg(), dstReg_v); //write the flag updates //compute AF WriteAFAddSub<width>(b, res, dstReg_v, srcReg_v); //compute SF WriteSF<width>(b, res); //compute ZF WriteZF<width>(b, res); //compute OF WriteOFAdd<width>(b, res, dstReg_v, srcReg_v); //compute PF WritePF<width>(b, res); //compute CF*/ WriteCFAdd<width>(b, res, dstReg_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; }
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(); }
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 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; }
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 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); }
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 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 doPSHUFDri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src, const MCOperand &order) { NASSERT(dst.isReg()); NASSERT(src.isReg()); NASSERT(order.isImm()); Value *input = R_READ<128>(b, src.getReg()); Value *shuffled = doShuffle<128,32>(b, input, order.getImm()); R_WRITE<128>(b, dst.getReg(), shuffled); 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 doMovSXRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(dst.isReg()); NASSERT(src.isReg()); Value *r = doMovSXV<dstWidth>(ip, b, R_READ<srcWidth>(b, src.getReg())); R_WRITE<dstWidth>(b, dst.getReg(), r); return ContinueBlock; }
static InstTransResult doPINSRWrri(BasicBlock *&b, const MCOperand &dst, const MCOperand &src, const MCOperand &order) { NASSERT(dst.isReg()); NASSERT(src.isReg()); NASSERT(order.isImm()); Value *vec = R_READ<128>(b, dst.getReg()); Value *elem = R_READ<16>(b, src.getReg()); Value *new_vec = doInsertion<128,16>(b, vec, elem, order.getImm()); R_WRITE<128>(b, dst.getReg(), new_vec); return ContinueBlock; }
static InstTransResult doBsrr( BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { TASSERT(dst.isReg(), "operand must be register"); TASSERT(src.isReg(), "operand must be register"); Value *src_val = R_READ<width>(b, src.getReg()); Type *s[1] = { Type::getIntNTy(b->getContext(), width) }; Function *ctlzFn = Intrinsic::getDeclaration(b->getParent()->getParent(), Intrinsic::ctlz, s); TASSERT(ctlzFn != NULL, "Could not find ctlz intrinsic"); vector<Value*> ctlzArgs; ctlzArgs.push_back(src_val); ctlzArgs.push_back(CONST_V<1>(b, 0)); Value *ctlz = CallInst::Create(ctlzFn, ctlzArgs, "", b); Value *index_of_first_1 = BinaryOperator::CreateSub( CONST_V<width>(b, width), ctlz, "", b); Value *is_zero = new ICmpInst( *b, CmpInst::ICMP_EQ, CONST_V<width>(b, 0), index_of_first_1); F_WRITE(b, ZF, is_zero); Value *fix_index = BinaryOperator::CreateSub( index_of_first_1, CONST_V<width>(b, 1), "", b); // See if we write to register Value *save_index = SelectInst::Create( is_zero, // check if the source was zero src_val, // if it was, do not change contents fix_index, // if it was not, set index "", b); R_WRITE<width>(b, dst.getReg(), save_index); return ContinueBlock; }
static InstTransResult doPINSRWrmi(InstPtr ip, BasicBlock *&b, const MCOperand &dst, Value *memAddr, const MCOperand &order) { NASSERT(dst.isReg()); NASSERT(order.isImm()); Value *vec = R_READ<128>(b, dst.getReg()); Value *elem = M_READ<16>(ip, b, memAddr); Value *new_vec = doInsertion<128,16>(b, vec, elem, order.getImm()); R_WRITE<128>(b, dst.getReg(), new_vec); return ContinueBlock; }
static InstTransResult doUCOMISrr(BasicBlock *&b, const MCOperand &op1, const MCOperand &op2) { NASSERT(op1.isReg()); NASSERT(op2.isReg()); Value *op1_val = R_READ<width>(b, op1.getReg()); Value *op2_val = R_READ<width>(b, op2.getReg()); 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 doXchgRM(InstPtr ip, BasicBlock *&b, const MCOperand &r, Value *mem) { NASSERT(mem != NULL); NASSERT(r.isReg()); Value *t1 = R_READ<width>(b, r.getReg()); Value *t2 = M_READ<width>(ip, b, mem); R_WRITE<width>(b, r.getReg(), t2); M_WRITE<width>(ip, b, mem, t1); return ContinueBlock; }
static InstTransResult doXchgRR(InstPtr ip, BasicBlock *&b, const MCOperand &o1, const MCOperand &o2) { NASSERT(o1.isReg()); NASSERT(o2.isReg()); Value *t1 = R_READ<width>(b, o1.getReg()); Value *t2 = R_READ<width>(b, o2.getReg()); R_WRITE<width>(b, o2.getReg(), t1); R_WRITE<width>(b, o1.getReg(), t2); return ContinueBlock; }
static InstTransResult doXorRM(InstPtr ip, BasicBlock *&b, const MCOperand &dst, const MCOperand &src1, Value *mem) { TASSERT(mem != NULL, ""); TASSERT(dst.isReg(), ""); TASSERT(src1.isReg(), ""); Value *fromMem = M_READ<width>(ip, b, mem); Value *fromReg = R_READ<width>(b, src1.getReg()); Value *res = doXorVV<width>(ip, b, fromMem, fromReg); R_WRITE<width>(b, dst.getReg(), res); return ContinueBlock; }
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; }
static InstTransResult do_SSE_VECTOR_OP(const MCOperand &dst, BasicBlock *&b, Value *v1, Value *v2) { NASSERT(width % elemwidth == 0); int elem_count = width/elemwidth; Type *elem_ty; VectorType *vt; std::tie(vt, elem_ty) = getIntVectorTypes(b, elemwidth, elem_count); Value *vecInput1 = INT_AS_VECTOR<width,elemwidth>(b, v1); Value *vecInput2 = INT_AS_VECTOR<width,elemwidth>(b, v2); Value *op_out = BinaryOperator::Create( bin_op, vecInput1, vecInput2, "", b); // convert the output back to an integer Value *intOutput = CastInst::Create( Instruction::BitCast, op_out, Type::getIntNTy(b->getContext(), width), "", b); R_WRITE<width>(b, dst.getReg(), intOutput); return ContinueBlock; }
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 doCVTSD2SSrV(NativeModulePtr natM, BasicBlock *& block, InstPtr ip, MCInst &inst, Value *src, const MCOperand &dst) { // convert the 64-bits we are reading into an FPU double //TODO: Check rounding modes! Value *to_double = CastInst::Create( Instruction::BitCast, src, Type::getDoubleTy(block->getContext()), "", block); // Truncate double to a single Value *fp_single = new FPTruncInst(to_double, Type::getFloatTy(block->getContext()), "", block); // treat the bits as a 32-bit int Value *to_int = CastInst::Create( Instruction::BitCast, fp_single, Type::getIntNTy(block->getContext(), 32), "", block); // write them to destination R_WRITE<width>(block, dst.getReg(), to_int); return ContinueBlock; }
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; }
static InstTransResult doXorRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst, const MCOperand &o1, const MCOperand &o2) { TASSERT(dst.isReg(), ""); TASSERT(o1.isReg(), ""); TASSERT(o2.isImm(), ""); Value *o1_v = R_READ<width>(b, o1.getReg()); Value *o2_v = CONST_V<width>(b, o2.getImm()); R_WRITE<width>(b, dst.getReg(), doXorVV<width>(ip, b, o1_v, o2_v)); return ContinueBlock; }
static InstTransResult doOrRM(InstPtr ip, BasicBlock *&b, Value *addr, const MCOperand &o1, const MCOperand &dst) { TASSERT(addr != NULL, ""); TASSERT(o1.isReg(), ""); TASSERT(dst.isReg(), ""); Value *addr_v = M_READ<width>(ip, b, addr); Value *o1_v = R_READ<width>(b, o1.getReg()); R_WRITE<width>(b, dst.getReg(), doOrVV<width>(ip, b, addr_v, o1_v)); return ContinueBlock; }
static InstTransResult doCVTSS2SDrV(NativeModulePtr natM, BasicBlock *& block, InstPtr ip, MCInst &inst, Value *src, const MCOperand &dst) { // convert the 32 bits we read into an fpu single Value *to_single = CastInst::Create( Instruction::BitCast, src, Type::getFloatTy(block->getContext()), "", block); // extend to a double Value *fp_double = new FPExtInst(to_single, Type::getDoubleTy(block->getContext()), "", block); // treat the bits as a 64-bit int Value *to_int = CastInst::Create( Instruction::BitCast, fp_double, Type::getIntNTy(block->getContext(), 64), "", block); // write them to destination R_WRITE<width>(block, dst.getReg(), to_int); return ContinueBlock; }
static InstTransResult doPSLLrr(BasicBlock *&b, const MCOperand &dst, const MCOperand &src) { NASSERT(src.isReg()); Value *shift_count = R_READ<128>(b, src.getReg()); return doNewShift<width, Instruction::Shl>(b, dst, shift_count, CONST_V<128>(b, 0)); }