예제 #1
0
static InstTransResult doFstM(InstPtr ip, BasicBlock *&b, Value *memAddr)
{
    NASSERT(memAddr != NULL);

    Value *regVal = FPUR_READ(b, X86::ST0);
    llvm::Type *destType;
    llvm::Type *ptrType;
    unsigned addrspace = ip->get_addr_space();

    switch (width)
    {
        case 32:
            destType = llvm::Type::getFloatTy(b->getContext());
            ptrType = llvm::Type::getFloatPtrTy(b->getContext(), addrspace);
            break;
        case 64:
            destType = llvm::Type::getDoubleTy(b->getContext());
            ptrType = llvm::Type::getDoublePtrTy(b->getContext(), addrspace);
            break;
        case 80:
            //destType = llvm::Type::getX86_FP80Ty(b->getContext());
            ptrType = llvm::Type::getX86_FP80PtrTy(b->getContext(), addrspace);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Invalid width specified for FST");
            break;
    }

    // do not truncate 80-bit to 80-bit, causes a truncation error
    if(width < 80)
    {
        Value *trunc = new FPTruncInst(regVal, destType, "", b);
        M_WRITE_T(ip, b, memAddr, trunc, ptrType);
    }
    else if(width == 80)
    {
        M_WRITE_T(ip, b, memAddr, regVal, ptrType);
    }
    else
    {
        throw TErr(__LINE__, __FILE__, "FPU Registers >80 bits not implemented for FST");
    }

    // Next instruction.
    return ContinueBlock;
}
예제 #2
0
static InstTransResult doCmpxchgRM(InstPtr ip,    BasicBlock      *&b,
                            Value           *dstAddr,
                            const MCOperand &srcReg) 
{
    NASSERT(dstAddr != NULL);
    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   *mem_v = M_READ<width>(ip, b, dstAddr);
    Value   *m_addr = NULL;

    unsigned addrspace = ip->get_addr_space();

    if( dstAddr->getType()->isPointerTy() == false ) {
		llvm::Type    *ptrTy = 
            Type::getIntNPtrTy(b->getContext(), width, addrspace);
        m_addr = new llvm::IntToPtrInst(dstAddr, ptrTy, "", b); 
	} 
    else if( dstAddr->getType() != Type::getIntNPtrTy(
                b->getContext(), width, addrspace) ) 
    {
		//we need to bitcast the pointer value to a pointer type of the appropriate width
		m_addr = CastInst::CreatePointerCast(dstAddr, 
                Type::getIntNPtrTy(b->getContext(), width, addrspace), "", b);
	} else {
        m_addr = dstAddr;
    }

    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());


    AtomicCmpXchgInst *cmpx = new AtomicCmpXchgInst(
            m_addr, 
            acc, 
            srcReg_v, 
            llvm::SequentiallyConsistent,
            llvm::SequentiallyConsistent,
            llvm::CrossThread, 
            b);
    cmpx->setVolatile(true);

    Value *cmpx_val = ExtractValueInst::Create(cmpx, 0, "cmpxchg_cmpx_val", b);
    Value *was_eq = ExtractValueInst::Create(cmpx, 1, "cmpxchg_was_eq", b);

    doCmpVV<width>(ip, b, acc, cmpx_val);


    F_WRITE(b, ZF, was_eq);

    Value *new_acc = SelectInst::Create(was_eq, acc, cmpx_val, "", b);

    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;
}
예제 #3
0
static InstTransResult doCmpxchgRM(InstPtr ip,    BasicBlock      *&b,
                            Value           *dstAddr,
                            const MCOperand &srcReg) 
{
    NASSERT(dstAddr != NULL);
    NASSERT(srcReg.isReg());

    Function    *F = b->getParent();
    BasicBlock  *AccEQDest = 
        BasicBlock::Create(b->getContext(), "AccEQDest", F);
    BasicBlock  *AccNEDest = 
        BasicBlock::Create(b->getContext(), "AccNEDest", F);
    BasicBlock  *done = 
        BasicBlock::Create(b->getContext(), "done", F);

    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   *mem_v = M_READ<width>(ip, b, dstAddr);
    Value   *m_addr = NULL;

    unsigned addrspace = ip->get_addr_space();

    if( dstAddr->getType()->isPointerTy() == false ) {
		llvm::Type    *ptrTy = 
            Type::getIntNPtrTy(b->getContext(), width, addrspace);
        m_addr = new llvm::IntToPtrInst(dstAddr, ptrTy, "", b); 
	} 
    else if( dstAddr->getType() != Type::getIntNPtrTy(
                b->getContext(), width, addrspace) ) 
    {
		//we need to bitcast the pointer value to a pointer type of the appropriate width
		m_addr = CastInst::CreatePointerCast(dstAddr, 
                Type::getIntNPtrTy(b->getContext(), width, addrspace), "", b);
	} else {
        m_addr = dstAddr;
    }

    Value   *srcReg_v = R_READ<width>(b, srcReg.getReg());


    AtomicCmpXchgInst *cmpx = new AtomicCmpXchgInst(
            m_addr, 
            acc, 
            srcReg_v, 
            llvm::SequentiallyConsistent,
            llvm::CrossThread, 
            b);
    cmpx->setVolatile(true);

    // needed for flags settings
    doCmpVV<width>(ip, b, acc, cmpx);

    Value   *Cmp = new ICmpInst(*b, CmpInst::ICMP_EQ, cmpx, acc);
    BranchInst::Create(AccEQDest, AccNEDest, Cmp, b);

    // Acc == Dst
    F_SET(AccEQDest, "ZF");
    //M_WRITE<width>(ip, AccEQDest, dstAddr, srcReg_v);
    BranchInst::Create(done, AccEQDest);

    // Acc != Dst
    F_CLEAR(AccNEDest, "ZF");
    switch(width) {
        case 8:
            R_WRITE<width>(AccNEDest, X86::AL, cmpx);
            break;
        case 16:
            R_WRITE<width>(AccNEDest, X86::AX, cmpx);
            break;
        case 32:
            R_WRITE<width>(AccNEDest, X86::EAX, cmpx);
            break;
        default:
            throw TErr(__LINE__, __FILE__, "Width not supported");
    }
    BranchInst::Create(done, AccNEDest);

    b = done;

    return ContinueBlock;
}