예제 #1
0
void SEMAPHORE::cXADD(INS &ins)
{
    // pointeur vers fonction à appeler
    void (*callback)() = nullptr;

    // XADD : opérande 0 est soit mémoire, soit registre, opérande 1 tjs registre
    REG regSrc = INS_OperandReg(ins, 1);
    UINT32 regSrcSize = getRegSize(regSrc);

    if (!regSrcSize) return;    // registre non géré en marquage
    else if (INS_OperandIsMemory(ins, 0)) // XADD_M (opérande 0 = mémoire)
    {
        switch (regSrcSize) 
        {	
        case 1:	callback = (AFUNPTR) sXADD_M<8>;  break;
        case 2:	callback = (AFUNPTR) sXADD_M<16>;  break;
        case 4:	callback = (AFUNPTR) sXADD_M<32>;  break;
        #if TARGET_IA32E
        case 8: callback = (AFUNPTR) sXADD_M<64>;  break;
        #endif
        }
        INS_InsertCall (ins, IPOINT_BEFORE, callback,
            IARG_THREAD_ID,
            IARG_UINT32,    regSrc,
            IARG_REG_VALUE, regSrc,
            IARG_MEMORYWRITE_EA, 
            IARG_INST_PTR, IARG_END); 
    }
    else  // XADD_R (opérande 0 = registre)
    {
        REG regDest = INS_OperandReg(ins, 0);
        switch (getRegSize(regDest)) 
        {	
        case 1:	callback = (AFUNPTR) sXADD_R<8>;  break;
        case 2:	callback = (AFUNPTR) sXADD_R<16>;  break;
        case 4:	callback = (AFUNPTR) sXADD_R<32>;  break;
        #if TARGET_IA32E
        case 8: callback = (AFUNPTR) sXADD_R<64>;  break;
        #endif
        }
        INS_InsertCall (ins, IPOINT_BEFORE, callback,
            IARG_THREAD_ID,
            IARG_UINT32,    regSrc,
            IARG_REG_VALUE, regSrc,
            IARG_UINT32,    regDest,
            IARG_REG_VALUE, regDest,
            IARG_INST_PTR, IARG_END); 
    }
} // cXADD
예제 #2
0
//getRegSize, getAliasReg:
//OpndSize, RegName, OpndExt: enum enc_defs.h
inline void add_r(EncoderBase::Operands & args, int physicalReg, OpndSize sz, OpndExt ext = OpndExt_None) {
    RegName reg = map_of_regno_2_regname[physicalReg];
    if (sz != getRegSize(reg)) {
       reg = getAliasReg(reg, sz);
    }
    args.add(EncoderBase::Operand(reg, ext));
}
예제 #3
0
//_________________________________________________________________________________________________
void CallingConventionClient::layoutAuxilaryOpnds(Inst::OpndRole role, OpndKind kindForStackArgs)
{
    StlVector<CallingConvention::OpndInfo> & infos = getInfos(role);
    StlVector<StackOpndInfo> & stackOpndInfos = getStackOpndInfos(role);
    U_32 slotSize=sizeof(POINTER_SIZE_INT);
    U_32 regArgCount=0, stackArgCount=0;
    Inst::Opnds opnds(ownerInst, Inst::OpndRole_Auxilary|role);
    Inst::Opnds::iterator handledOpnds=opnds.begin();
    for (U_32 i=0, n=(U_32)infos.size(); i<n; i++){
        const CallingConvention::OpndInfo& info=infos[i];
#ifdef _DEBUG
        bool eachSlotRequiresOpnd=false;
#endif
        U_32 offset=0;
        for (U_32 j=0, cbCurrent=0; j<info.slotCount; j++){
            Opnd * opnd=opnds.getOpnd(handledOpnds);
            OpndSize sz=opnd->getSize();
            U_32 cb=getByteSize(sz);
            RegName r=(RegName)info.slots[j];
            if (info.isReg) {
                r=Constraint::getAliasRegName(r,sz);
                assert(r!=RegName_Null);
#ifdef _DEBUG
                eachSlotRequiresOpnd=true;
#endif
                cbCurrent+=getByteSize(getRegSize(r));
            }else{
                if (cbCurrent==0)
                    offset=(info.slots[j] & 0xffff)*slotSize;
                cbCurrent+=slotSize;  
            }

            if (cbCurrent>=cb){
                if (info.isReg){
                    ownerInst->setConstraint(handledOpnds, r);
                    regArgCount++;
                }else{
                    ownerInst->setConstraint(handledOpnds, Constraint(kindForStackArgs, sz));
                    stackArgCount++;
                    StackOpndInfo sainfo={ handledOpnds, offset };
                    stackOpndInfos.push_back(sainfo);
                }
                handledOpnds = opnds.next(handledOpnds);
#ifdef _DEBUG
                eachSlotRequiresOpnd=false;
#endif
                cbCurrent=0;
            }
#ifdef _DEBUG
            assert(!eachSlotRequiresOpnd); 
#endif
        }
    }
    if (stackArgCount>0)
        sort(stackOpndInfos.begin(), stackOpndInfos.end());
    assert(handledOpnds == opnds.end());
    assert(stackArgCount==stackOpndInfos.size());
}
예제 #4
0
Opnd* OpndUtils::convertToXmmReg64(Opnd* xmmReg)
{
    assert(isXmmReg(xmmReg));
    RegName regName = xmmReg->getRegName();
    OpndSize size = getRegSize(regName);
    if (size == OpndSize_64) {
        return xmmReg;
    }
    TypeManager& typeMan = m_irManager->getTypeManager();
    Type* doubleType = typeMan.getDoubleType();
    unsigned regIndex = getRegIndex(regName);
    RegName regName64 = getRegName(OpndKind_XMMReg, OpndSize_64, regIndex);
    Opnd* xmm64 = m_irManager->newRegOpnd(doubleType, regName64);
    return xmm64;
}
예제 #5
0
// CALLBACKS
void SEMAPHORE::cCMPXCHG(INS &ins)
{
    // CMPXCHG : d'abord une comparaison destination (R ou M) avec 
    // puis 1 MOV selon le resultat de la comparaison
    // Opérande 0 : ModRM:r/m (si reg : regDest)
    // Opérande 1 : reg (dénommé regSrc)
    // CMPXCHG compare opérande 0 avec AL/AX/EAX/RAX
    // Si égal,       ZF = 1 (comme une vraie comparaison) et opérande 1 -> opérande 0 
    // Si différent : ZF = 0 (comme une vraie comparaison) et opérande 0 -> AL/AX/EAX/RAX
    // Dans les arguments des callbacks, il vaut ajouter la valeur de AL/AX/EAX/RAX
    // Et celle du registre dest (cas RR) pour faire la comparaison.
    
    // opérande 1 : regSrc
    REG regSrc = INS_OperandReg(ins, 1);
    UINT32 regSrcSize = getRegSize(regSrc);
    if (!regSrcSize) return;	// registre non suivi
    
    // registre de comparasion avec la destination
    REG cmpReg = REG_INVALID(); // selon la taille, AL/AX/EAX/RAX

    // pointeur vers fonction à appeler
    void (*callback)() = nullptr;
    if (INS_IsMemoryRead(ins)) // CMPXCHG_RM (source 0 = mémoire)
    {
        switch (regSrcSize) 
        {	
        case 1:	callback = (AFUNPTR) sCMPXCHG_RM<8>;  cmpReg = REG_AL; break;
        case 2:	callback = (AFUNPTR) sCMPXCHG_RM<16>; cmpReg = REG_AX; break;
        case 4:	callback = (AFUNPTR) sCMPXCHG_RM<32>; cmpReg = REG_EAX; break;
        #if TARGET_IA32E
        case 8: callback = (AFUNPTR) sCMPXCHG_RM<64>; cmpReg = REG_RAX; break;
        #endif
        }
        INS_InsertCall (ins, IPOINT_BEFORE, callback,
            IARG_THREAD_ID,
            IARG_UINT32, regSrc, // pas besoin de la valeur du registre, le déplacement se fera octet par octet
            IARG_MEMORYREAD_EA, 
            IARG_UINT32,    cmpReg,
            IARG_REG_VALUE, cmpReg,
            IARG_INST_PTR, IARG_END);      
    }
    else // CMPXCHG_RR (source 0 = registre)
    {
        REG regDest = INS_OperandReg(ins, 0); // registre de destination (comparé à AL/AX/EAX/RAX)
        switch (getRegSize(regDest)) 
        {	
        case 0: return; // non suivi en instrumentation
        case 1:	callback = (AFUNPTR) sCMPXCHG_RR<8>;  cmpReg = REG_AL; break;
        case 2:	callback = (AFUNPTR) sCMPXCHG_RR<16>; cmpReg = REG_AX; break;
        case 4:	callback = (AFUNPTR) sCMPXCHG_RR<32>; cmpReg = REG_EAX; break;
        #if TARGET_IA32E
        case 8: callback = (AFUNPTR) sCMPXCHG_RR<64>; cmpReg = REG_RAX; break;
        #endif
        }
        INS_InsertCall (ins, IPOINT_BEFORE, callback,
            IARG_THREAD_ID,
            IARG_UINT32, regSrc, 
            IARG_UINT32, regDest, 
            IARG_REG_VALUE, regDest,// valeur indispendable pour comparaison à RAX
            IARG_UINT32,    cmpReg,
            IARG_REG_VALUE, cmpReg,
            IARG_INST_PTR, IARG_END);     
    }
} // cCMPXCHG