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; }
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; }
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; }