void X86InstrSema::translateTargetOpcode() { switch(Opcode) { default: llvm_unreachable( ("Unknown X86 opcode found in semantics: " + utostr(Opcode)).c_str()); case X86ISD::CMOV: { Value *Op1 = getNextOperand(), *Op2 = getNextOperand(), *Op3 = getNextOperand(), *Op4 = getNextOperand(); assert(Op4 == getReg(X86::EFLAGS) && "Conditional mov predicate register isn't EFLAGS!"); (void)Op4; unsigned CC = cast<ConstantInt>(Op3)->getValue().getZExtValue(); Value *Pred = X86DRS.testCondCode(CC); registerResult(Builder->CreateSelect(Pred, Op2, Op1)); break; } case X86ISD::RET_FLAG: { // FIXME: Handle ret arg. /* unsigned Op1 = */ Next(); setReg(X86::RIP, translatePop(8)); Builder->CreateBr(ExitBB); break; } case X86ISD::CMP: { Value *Op1 = getNextOperand(), *Op2 = getNextOperand(); registerResult(X86DRS.getEFLAGSforCMP(Op1, Op2)); break; } case X86ISD::BRCOND: { Value *Op1 = getNextOperand(), *Op2 = getNextOperand(), *Op3 = getNextOperand(); assert(Op3 == getReg(X86::EFLAGS) && "Conditional branch predicate register isn't EFLAGS!"); (void)Op3; uint64_t Target = cast<ConstantInt>(Op1)->getValue().getZExtValue(); unsigned CC = cast<ConstantInt>(Op2)->getValue().getZExtValue(); setReg(X86::RIP, Op1); Builder->CreateCondBr(X86DRS.testCondCode(CC), getOrCreateBasicBlock(Target), getOrCreateBasicBlock(getBasicBlockEndAddress())); break; } case X86ISD::CALL: { Value *Op1 = getNextOperand(); translatePush(Builder->getInt64(CurrentInst->Address + CurrentInst->Size)); insertCall(Op1); break; } case X86ISD::SETCC: { Value *Op1 = getNextOperand(), *Op2 = getNextOperand(); assert(Op2 == getReg(X86::EFLAGS) && "SetCC predicate register isn't EFLAGS!"); (void)Op2; unsigned CC = cast<ConstantInt>(Op1)->getValue().getZExtValue(); Value *Pred = X86DRS.testCondCode(CC); registerResult(Builder->CreateZExt(Pred, Builder->getInt8Ty())); break; } case X86ISD::SBB: { (void)NextVT(); Value *Op1 = getNextOperand(), *Op2 = getNextOperand(), *Op3 = getNextOperand(); assert(Op3 == getReg(X86::EFLAGS) && "SBB borrow register isn't EFLAGS!"); (void)Op3; Value *Borrow = Builder->CreateZExt(X86DRS.testCondCode(X86::CF), Op1->getType()); Value *Res = Builder->CreateSub(Op1, Op2); registerResult(Builder->CreateSub(Res, Borrow)); registerResult(getReg(X86::EFLAGS)); break; } case X86ISD::BT: { Value *Base = getNextOperand(); Value *Op2 = getNextOperand(); Value *Offset = Builder->CreateZExtOrBitCast(Op2, Base->getType()); Value *Bit = Builder->CreateTrunc(Builder->CreateShl(Base, Offset), Builder->getInt1Ty()); Value *OldEFLAGS = getReg(X86::EFLAGS); Type *EFLAGSTy = OldEFLAGS->getType(); APInt Mask = APInt::getAllOnesValue(EFLAGSTy->getPrimitiveSizeInBits()); Mask.clearBit(X86::CF); OldEFLAGS = Builder->CreateAnd(OldEFLAGS, ConstantInt::get(*Ctx, Mask)); Bit = Builder->CreateZExt(Bit, EFLAGSTy); Bit = Builder->CreateLShr(Bit, X86::CF); registerResult(Builder->CreateOr(OldEFLAGS, Bit)); break; } case X86ISD::BSF: { (void)NextVT(); Value *Src = getNextOperand(); // If the source is zero, it is undefined behavior as per Intel SDM, but // most implementations I'm aware of just leave the destination unchanged. assert((CurrentInst->Inst.getOpcode() >= X86::BSF16rm && CurrentInst->Inst.getOpcode() <= X86::BSF64rr) && "Unexpected instruction with X86ISD::BSR node!"); Value *IsSrcZero = Builder->CreateIsNull(Src); Value *PrevDstVal = getReg(CurrentInst->Inst.getOperand(0).getReg()); Type *ArgTys[] = { PrevDstVal->getType(), Builder->getInt1Ty() }; Value *Cttz = Builder->CreateCall2( Intrinsic::getDeclaration(TheModule, Intrinsic::cttz, ArgTys), Src, /*is_zero_undef:*/ Builder->getInt1(true)); registerResult(Builder->CreateSelect(IsSrcZero, PrevDstVal, Cttz)); // We also need to update ZF in EFLAGS. Value *OldEFLAGS = getReg(X86::EFLAGS); registerResult(DRS.insertBitsInValue(OldEFLAGS, IsSrcZero, X86::ZF)); break; } case X86ISD::BSR: { (void)NextVT(); Value *Src = getNextOperand(); // If the source is zero, it is undefined behavior as per Intel SDM, but // most implementations I'm aware of just leave the destination unchanged. assert((CurrentInst->Inst.getOpcode() >= X86::BSR16rm && CurrentInst->Inst.getOpcode() <= X86::BSR64rr) && "Unexpected instruction with X86ISD::BSR node!"); Value *IsSrcZero = Builder->CreateIsNull(Src); Value *PrevDstVal = getReg(CurrentInst->Inst.getOperand(0).getReg()); Type *ArgTys[] = { PrevDstVal->getType(), Builder->getInt1Ty() }; Value *Ctlz = Builder->CreateCall2( Intrinsic::getDeclaration(TheModule, Intrinsic::ctlz, ArgTys), Src, /*is_zero_undef:*/ Builder->getInt1(true)); registerResult(Builder->CreateSelect(IsSrcZero, PrevDstVal, Ctlz)); // We also need to update ZF in EFLAGS. Value *OldEFLAGS = getReg(X86::EFLAGS); registerResult(DRS.insertBitsInValue(OldEFLAGS, IsSrcZero, X86::ZF)); break; } case X86DCISD::DIV8: translateDivRem(/* isThreeOperand= */ false, /* isSigned= */ false); break; case X86DCISD::IDIV8: translateDivRem(/* isThreeOperand= */ false, /* isSigned= */ true); break; case X86DCISD::DIV: translateDivRem(/* isThreeOperand= */ true, /* isSigned= */ false); break; case X86DCISD::IDIV: translateDivRem(/* isThreeOperand= */ true, /* isSigned= */ true); break; case X86ISD::FMIN: case X86ISD::FMAX: { // FIXME: Ok this is an interesting one. The short version is: we don't // care about sNaN, since it's really missing from LLVM. // The result defaults to the second operand, so we do a backwards // fcmp+select. Value *Src1 = getNextOperand(); Value *Src2 = getNextOperand(); CmpInst::Predicate Pred; if (Opcode == X86ISD::FMAX) Pred = CmpInst::FCMP_ULE; else Pred = CmpInst::FCMP_UGE; registerResult(Builder->CreateSelect(Builder->CreateFCmp(Pred, Src1, Src2), Src2, Src1)); break; } case X86ISD::MOVLHPD: case X86ISD::MOVLPS: case X86ISD::MOVLPD: case X86ISD::MOVSD: case X86ISD::MOVSS: { Value *Src1 = getNextOperand(); Value *Src2 = getNextOperand(); Type *VecTy = ResEVT.getTypeForEVT(*Ctx); assert(VecTy->isVectorTy() && VecTy == Src1->getType() && VecTy == Src2->getType() && "Operands to MOV/UNPCK shuffle aren't vectors!"); unsigned NumElt = VecTy->getVectorNumElements(); SmallVector<Constant *, 16> Mask; for (int i = 0, e = NumElt; i != e; ++i) Mask.push_back(Builder->getInt32(i)); switch (Opcode) { case X86ISD::MOVLPD: // LPD and SD are equivalent. case X86ISD::MOVLPS: // LPS is just SS*2. case X86ISD::MOVSD: case X86ISD::MOVSS: { Mask[0] = Builder->getInt32(NumElt); if (Opcode == X86ISD::MOVLPS) Mask[1] = Builder->getInt32(NumElt + 1); break; } case X86ISD::MOVLHPD: { assert(NumElt == 2); Mask[1] = Builder->getInt32(NumElt); break; } } registerResult( Builder->CreateShuffleVector(Src1, Src2, ConstantVector::get(Mask))); break; } case X86ISD::UNPCKL: case X86ISD::UNPCKH: case X86ISD::MOVLHPS: case X86ISD::MOVHLPS: { Value *Src1 = getNextOperand(); Value *Src2 = getNextOperand(); SmallVector<int, 8> Mask; switch (Opcode) { case X86ISD::MOVLHPS: DecodeMOVLHPSMask(ResEVT.getVectorNumElements(), Mask); break; case X86ISD::MOVHLPS: DecodeMOVHLPSMask(ResEVT.getVectorNumElements(), Mask); break; case X86ISD::UNPCKL: DecodeUNPCKLMask(ResEVT.getSimpleVT(), Mask); break; case X86ISD::UNPCKH: DecodeUNPCKHMask(ResEVT.getSimpleVT(), Mask); break; }; translateShuffle(Mask, Src1, Src2); break; } case X86ISD::PSHUFD: case X86ISD::PSHUFHW: case X86ISD::PSHUFLW: { Value *Src = getNextOperand(); unsigned MaskImm = cast<ConstantInt>(getNextOperand())->getZExtValue(); SmallVector<int, 8> Mask; switch (Opcode) { case X86ISD::PSHUFD: DecodePSHUFMask(ResEVT.getSimpleVT(), MaskImm, Mask); break; case X86ISD::PSHUFHW: DecodePSHUFHWMask(ResEVT.getSimpleVT(), MaskImm, Mask); break; case X86ISD::PSHUFLW: DecodePSHUFLWMask(ResEVT.getSimpleVT(), MaskImm, Mask); break; }; translateShuffle(Mask, Src); break; } case X86ISD::SHUFP: case X86ISD::PALIGNR: { Value *Src1 = getNextOperand(); Value *Src2 = getNextOperand(); unsigned MaskImm = cast<ConstantInt>(getNextOperand())->getZExtValue(); SmallVector<int, 8> Mask; DecodePSHUFMask(ResEVT.getSimpleVT(), MaskImm, Mask); switch (Opcode) { case X86ISD::SHUFP: DecodeSHUFPMask(ResEVT.getSimpleVT(), MaskImm, Mask); break; case X86ISD::PALIGNR: DecodePALIGNRMask(ResEVT.getSimpleVT(), MaskImm, Mask); break; }; translateShuffle(Mask, Src1, Src2); break; } case X86ISD::HSUB: translateHorizontalBinop(Instruction::Sub); break; case X86ISD::HADD: translateHorizontalBinop(Instruction::Add); break; case X86ISD::FHSUB: translateHorizontalBinop(Instruction::FSub); break; case X86ISD::FHADD: translateHorizontalBinop(Instruction::FAdd); break; } }