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
//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)); }
//_________________________________________________________________________________________________ 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()); }
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; }
// 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