Esempio n. 1
0
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;
  }
}