#include #include "CodeGen.h" #include "PtrMacro.h" #include "CodeGen_StackPatterns.h" using namespace Framework; using namespace std; using namespace std::tr1; using namespace std::tr1::placeholders; CX86Assembler::REGISTER CCodeGen::g_nBaseRegister = CX86Assembler::rBP; uint32 ConstantConstantOp_NotImplemented(uint32 first, uint32 second) { throw runtime_error("Not Implemented."); } uint32 ConstantConstantOp_And(uint32 first, uint32 second) { return first & second; } uint32 ConstantConstantOp_Or(uint32 first, uint32 second) { return first | second; } uint32 ConstantConstantOp_Xor(uint32 first, uint32 second) { return first ^ second; } bool IsNullOp_Zero(uint32 constant) { return constant == 0; } bool IsNullOp_False(uint32 constant) { return false; } CCodeGen::GenericOp Op_Add(&CX86Assembler::AddEd, &CX86Assembler::AddId, &ConstantConstantOp_NotImplemented, &IsNullOp_False); CCodeGen::GenericOp Op_Adc(&CX86Assembler::AdcEd, &CX86Assembler::AdcId, &ConstantConstantOp_NotImplemented, &IsNullOp_False); CCodeGen::GenericOp Op_And(&CX86Assembler::AndEd, &CX86Assembler::AndId, &ConstantConstantOp_And, &IsNullOp_False); CCodeGen::GenericOp Op_Cmp(&CX86Assembler::CmpEd, &CX86Assembler::CmpId, &ConstantConstantOp_NotImplemented, &IsNullOp_False); CCodeGen::GenericOp Op_Or (&CX86Assembler::OrEd, &CX86Assembler::OrId, &ConstantConstantOp_Or, &IsNullOp_Zero); CCodeGen::GenericOp Op_Sub(&CX86Assembler::SubEd, &CX86Assembler::SubId, &ConstantConstantOp_NotImplemented, &IsNullOp_False); CCodeGen::GenericOp Op_Sbb(&CX86Assembler::SbbEd, &CX86Assembler::SbbId, &ConstantConstantOp_NotImplemented, &IsNullOp_False); CCodeGen::GenericOp Op_Xor(&CX86Assembler::XorEd, &CX86Assembler::XorId, &ConstantConstantOp_Xor, &IsNullOp_Zero); #ifdef AMD64 unsigned int CCodeGen::m_nRegisterLookup[MAX_REGISTER] = { 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }; CX86Assembler::REGISTER CCodeGen::m_nRegisterLookupEx[MAX_REGISTER] = { CX86Assembler::rAX, CX86Assembler::rCX, CX86Assembler::rDX, CX86Assembler::rBX, CX86Assembler::rSI, CX86Assembler::rDI, CX86Assembler::r8, CX86Assembler::r9, CX86Assembler::r10, CX86Assembler::r11, CX86Assembler::r12, CX86Assembler::r13, CX86Assembler::r14, CX86Assembler::r15, }; #else unsigned int CCodeGen::m_nRegisterLookup[MAX_REGISTER] = { 0, 1, 2, 3, 6, 7, }; CX86Assembler::REGISTER CCodeGen::m_nRegisterLookupEx[MAX_REGISTER] = { CX86Assembler::rAX, CX86Assembler::rCX, CX86Assembler::rDX, CX86Assembler::rBX, CX86Assembler::rSI, CX86Assembler::rDI, }; #endif CCodeGen::CCodeGen() : m_stream(NULL), m_nBlockStarted(false), m_Assembler( bind(&CCodeGen::StreamWriteByte, this, _1), bind(&CCodeGen::StreamWriteAt, this, _1, _2), bind(&CCodeGen::StreamTell, this) ) { } CCodeGen::~CCodeGen() { } void CCodeGen::SetStream(CStream* stream) { m_stream = stream; } void CCodeGen::Begin() { assert(m_nBlockStarted == false); m_nBlockStarted = true; m_Shadow.Reset(); for(unsigned int i = 0; i < MAX_REGISTER; i++) { m_nRegisterAllocated[i] = false; } for(unsigned int i = 0; i < MAX_XMM_REGISTER; i++) { m_xmmRegisterAllocated[i] = false; } } void CCodeGen::End() { assert(m_nBlockStarted == true); m_nBlockStarted = false; } bool CCodeGen::IsStackEmpty() { return m_Shadow.GetCount() == 0; } void CCodeGen::EndQuota() { m_Assembler.Ret(); } void CCodeGen::BeginIf(bool nCondition) { if(m_Shadow.GetAt(0) == REGISTER) { m_Shadow.Pull(); uint32 nRegister = m_Shadow.Pull(); //test reg, reg m_Assembler.TestEd(m_nRegisterLookupEx[nRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister])); if(!RegisterHasNextUse(nRegister)) { FreeRegister(nRegister); } CX86Assembler::LABEL ifLabel = m_Assembler.CreateLabel(); //jcc label if(nCondition) { m_Assembler.JeJb(ifLabel); } else { m_Assembler.JneJb(ifLabel); } m_IfStack.Push(ifLabel); m_IfStack.Push(IFBLOCK); } else { assert(0); } } void CCodeGen::EndIf() { assert(m_IfStack.GetAt(0) == IFBLOCK); m_IfStack.Pull(); CX86Assembler::LABEL ifLabel = static_cast(m_IfStack.Pull()); m_Assembler.MarkLabel(ifLabel); m_Assembler.ResolveLabelReferences(); } void CCodeGen::BeginIfElse(bool nCondition) { if(FitsPattern()) { SingleRegister::PatternValue valueRegister(GetPattern()); if(!RegisterHasNextUse(valueRegister)) { FreeRegister(valueRegister); } m_Assembler.TestEd(m_nRegisterLookupEx[valueRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[valueRegister])); CX86Assembler::LABEL ifLabel = m_Assembler.CreateLabel(); //jcc label if(nCondition) { m_Assembler.JeJb(ifLabel); } else { m_Assembler.JneJb(ifLabel); } m_IfStack.Push(ifLabel); m_IfStack.Push(IFELSEBLOCK); } else if(FitsPattern()) { SingleRegister::PatternValue value(GetPattern()); unsigned int registerId = AllocateRegister(); LoadRelativeInRegister(registerId, value); PushReg(registerId); CCodeGen::BeginIfElse(nCondition); } else if(FitsPattern()) { SingleConstant::PatternValue constant(GetPattern()); //Skip the if block only if we have a "false" value CX86Assembler::LABEL ifLabel = m_Assembler.CreateLabel(); if(!constant) { m_Assembler.JmpJb(ifLabel); } m_IfStack.Push(ifLabel); m_IfStack.Push(IFELSEBLOCK); } else { assert(0); } } void CCodeGen::BeginIfElseAlt() { assert(m_IfStack.GetAt(0) == IFELSEBLOCK); m_IfStack.Pull(); CX86Assembler::LABEL ifLabel = m_IfStack.Pull(); CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel(); //jmp label m_Assembler.JmpJb(doneLabel); m_Assembler.MarkLabel(ifLabel); m_IfStack.Push(doneLabel); m_IfStack.Push(IFBLOCK); } unsigned int CCodeGen::GetMinimumConstantSize(uint32 nConstant) { if(((int32)nConstant >= -128) && ((int32)nConstant <= 127)) { return 1; } return 4; } unsigned int CCodeGen::GetMinimumConstantSize64(uint64 nConstant) { if(((int64)nConstant >= -128) && ((int64)nConstant <= 127)) { return 1; } if(((int64)nConstant >= -2147483647) && ((int64)nConstant <= 2147483647)) { return 4; } return 8; } bool CCodeGen::RegisterHasNextUse(unsigned int nRegister) { unsigned int i, nCount; nCount = m_Shadow.GetCount(); for(i = 0; i < nCount; i += 2) { if(m_Shadow.GetAt(i) == REGISTER) { if(m_Shadow.GetAt(i + 1) == nRegister) return true; } } return false; } unsigned int CCodeGen::AllocateRegister(REGISTER_TYPE nPreference) { if(nPreference == REGISTER_NORMAL) { for(unsigned int i = 0; i < MAX_REGISTER; i++) { if(!m_nRegisterAllocated[i]) { m_nRegisterAllocated[i] = true; return i; } } } if(nPreference == REGISTER_SHIFTAMOUNT) { if(!m_nRegisterAllocated[1]) { m_nRegisterAllocated[1] = true; return 1; } } if(nPreference == REGISTER_HASLOW) { //Only four first registers (eax, ecx, edx, ebx) has low counter parts for(unsigned int i = 0; i < 4; i++) { if(!m_nRegisterAllocated[i]) { m_nRegisterAllocated[i] = true; return i; } } } if(nPreference == REGISTER_SAVED) { for(unsigned int i = 0; i < MAX_REGISTER; i++) { if(i == 0) continue; if(i == 1) continue; if(i == 2) continue; #ifdef AMD64 if(i == 8) continue; if(i == 9) continue; if(i == 10) continue; if(i == 11) continue; #endif if(!m_nRegisterAllocated[i]) { m_nRegisterAllocated[i] = true; return i; } } } assert(0); return 0; } void CCodeGen::FreeRegister(unsigned int nRegister) { assert(!RegisterHasNextUse(nRegister)); m_nRegisterAllocated[nRegister] = false; } CCodeGen::XMMREGISTER CCodeGen::AllocateXmmRegister() { for(unsigned int i = 0; i < MAX_XMM_REGISTER; i++) { if(!m_xmmRegisterAllocated[i]) { m_xmmRegisterAllocated[i] = true; return static_cast(i); } } throw runtime_error("All registers exhausted."); } void CCodeGen::FreeXmmRegister(XMMREGISTER registerId) { m_xmmRegisterAllocated[registerId] = false; } void CCodeGen::LoadRelativeInRegister(unsigned int nRegister, uint32 nOffset) { //mov reg, [base + rel] m_Assembler.MovEd( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, nOffset)); } void CCodeGen::LoadConstantInRegister(unsigned int nRegister, uint32 nConstant) { if(nConstant == 0) { m_Assembler.XorGd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), m_nRegisterLookupEx[nRegister]); } else { m_Assembler.MovId(m_nRegisterLookupEx[nRegister], nConstant); } } void CCodeGen::CopyRegister(unsigned int nDst, unsigned int nSrc) { m_Assembler.MovEd( m_nRegisterLookupEx[nDst], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nSrc])); } #ifdef AMD64 void CCodeGen::LoadRelativeInRegister64(unsigned int nRegister, uint32 nRelative) { m_Assembler.MovEq( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, nRelative)); } void CCodeGen::LoadConstantInRegister64(unsigned int nRegister, uint64 nConstant) { unsigned int nRegIndex; uint8 nRex; nRegIndex = m_nRegisterLookup[nRegister]; nRex = 0x48; if(nRegIndex > 7) { nRex |= 0x01; nRegIndex &= 0x07; } //mov reg, nConstant m_pBlock->StreamWrite(2, nRex, 0xB8 | nRegIndex); m_pBlock->StreamWriteWord((uint32)((nConstant >> 0) & 0xFFFFFFFF)); m_pBlock->StreamWriteWord((uint32)((nConstant >> 32) & 0xFFFFFFFF)); } #endif void CCodeGen::ReduceToRegister() { if(m_Shadow.GetAt(0) == RELATIVE) { uint32 nRelative; unsigned int nRegister; m_Shadow.Pull(); nRelative = m_Shadow.Pull(); nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative); PushReg(nRegister); } else if(m_Shadow.GetAt(0) == REGISTER) { //That's fine } else { assert(0); } } void CCodeGen::PushCst(uint32 nValue) { m_Shadow.Push(nValue); m_Shadow.Push(CONSTANT); } void CCodeGen::PushRef(void* pAddr) { m_Shadow.Push(*(uint32*)&pAddr); m_Shadow.Push(REFERENCE); } void CCodeGen::PushRel(size_t nOffset) { m_Shadow.Push((uint32)nOffset); m_Shadow.Push(RELATIVE); } void CCodeGen::PushIdx(unsigned int nIndex) { uint32 nParam1, nParam2; nIndex *= 2; nParam1 = m_Shadow.GetAt(nIndex + 0); nParam2 = m_Shadow.GetAt(nIndex + 1); m_Shadow.Push(nParam2); m_Shadow.Push(nParam1); } void CCodeGen::PushTop() { PushIdx(0); } void CCodeGen::PushReg(unsigned int nRegister) { m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } bool CCodeGen::IsRegisterSaved(unsigned int registerId) { #ifdef AMD64 throw runtime_error("Not implemented."); #else CX86Assembler::REGISTER registerName = m_nRegisterLookupEx[registerId]; return ( registerName == CX86Assembler::rBX || registerName == CX86Assembler::rBP || registerName == CX86Assembler::rSP || registerName == CX86Assembler::rDI || registerName == CX86Assembler::rSI ); #endif } #ifdef AMD64 void CCodeGen::PushReg64(unsigned int nRegister) { m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER64); } #endif void CCodeGen::ReplaceRegisterInStack(unsigned int nDst, unsigned int nSrc) { for(unsigned int i = 0; i < m_Shadow.GetCount(); i += 2) { if(m_Shadow.GetAt(i + 0) == REGISTER) { unsigned int nRegister; nRegister = m_Shadow.GetAt(i + 1); if(nRegister == nSrc) { m_Shadow.SetAt(i + 1, nDst); } } } } void CCodeGen::PullRel(size_t nOffset) { if(m_Shadow.GetAt(0) == REGISTER) { uint32 nRegister; m_Shadow.Pull(); nRegister = m_Shadow.Pull(); //mov dword ptr[pValue], reg m_Assembler.MovGd( CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast(nOffset)), m_nRegisterLookupEx[nRegister]); if(!RegisterHasNextUse(nRegister)) { FreeRegister(nRegister); } } else if(m_Shadow.GetAt(0) == CONSTANT) { uint32 nConstant, nRegister; m_Shadow.Pull(); nConstant = m_Shadow.Pull(); nRegister = AllocateRegister(); if(nConstant == 0) { //xor reg, reg m_Assembler.XorGd( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), m_nRegisterLookupEx[nRegister]); } else { //mov reg, $Constant m_Assembler.MovId(m_nRegisterLookupEx[nRegister], nConstant); } //mov dword ptr[pValue], reg m_Assembler.MovGd( CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast(nOffset)), m_nRegisterLookupEx[nRegister]); FreeRegister(nRegister); } else if(m_Shadow.GetAt(0) == VARIABLE) { ReduceToRegister(); PullRel(nOffset); } else if(m_Shadow.GetAt(0) == RELATIVE) { uint32 nRelative, nRegister; m_Shadow.Pull(); nRelative = m_Shadow.Pull(); nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); PullRel(nOffset); } #ifdef AMD64 else if(m_Shadow.GetAt(0) == REGISTER64) { throw runtime_error("Not implemented"); /* if(m_PullReg64Stack.GetCount() == 0) { //Save the provided offset for the next time m_PullReg64Stack.Push(static_cast(nOffset)); } else { uint32 nRelative1, nRelative2; uint32 nRegister; nRelative2 = m_PullReg64Stack.Pull(); nRelative1 = static_cast(nOffset); m_Shadow.Pull(); nRegister = m_Shadow.Pull(); assert((nRelative2 - nRelative1) == 4); assert(m_nRegisterLookup[nRegister] < 8); //mov qword ptr[pValue], reg m_pBlock->StreamWrite(2, 0x48, 0x89); WriteRelativeRmRegister(nRegister, nRelative1); FreeRegister(nRegister); } */ } #endif else { assert(0); } } void CCodeGen::PullTop() { uint32 type = m_Shadow.Pull(); uint32 value = m_Shadow.Pull(); if(type == REGISTER) { if(!RegisterHasNextUse(value)) { FreeRegister(value); } } } void CCodeGen::Swap() { uint32 value[2]; uint32 valueType[2]; for(int i = 1; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } for(int i = 1; i >= 0; i--) { m_Shadow.Push(value[i]); m_Shadow.Push(valueType[i]); } } void CCodeGen::Add() { if(FitsPattern()) { CommutativeRelativeConstant::PatternValue ops(GetPattern()); unsigned int registerId = AllocateRegister(); LoadRelativeInRegister(registerId, ops.first); //add reg, Immediate m_Assembler.AddId( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), ops.second); PushReg(registerId); } else if(FitsPattern()) { RelativeRelative::PatternValue ops = GetPattern(); unsigned int resultRegister = AllocateRegister(); LoadRelativeInRegister(resultRegister, ops.first); m_Assembler.AddEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(resultRegister); } //else if((m_Shadow.GetAt(0) == REGISTER) && (m_Shadow.GetAt(2) == REGISTER)) //{ // uint32 nRegister1, nRegister2; // // m_Shadow.Pull(); // nRegister2 = m_Shadow.Pull(); // m_Shadow.Pull(); // nRegister1 = m_Shadow.Pull(); // //Can free this register // if(!RegisterHasNextUse(nRegister2)) // { // FreeRegister(nRegister2); // } // //add reg1, reg2 // m_pBlock->StreamWrite(2, 0x03, 0xC0 | (m_nRegisterLookup[nRegister1] << 3) | (m_nRegisterLookup[nRegister2])); // m_Shadow.Push(nRegister1); // m_Shadow.Push(REGISTER); //} else if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == REGISTER)) { uint32 nRegister, nConstant; m_Shadow.Pull(); nConstant = m_Shadow.Pull(); //No point in adding zero if(nConstant == 0) return; m_Shadow.Pull(); nRegister = m_Shadow.Pull(); m_Assembler.AddId( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), nConstant); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } else if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == CONSTANT)) { uint32 nConstant1, nConstant2; m_Shadow.Pull(); nConstant2 = m_Shadow.Pull(); m_Shadow.Pull(); nConstant1 = m_Shadow.Pull(); PushCst(nConstant2 + nConstant1); } else { assert(0); } } void CCodeGen::Add64() { if(FitsPattern()) { ConstantConstant64::PatternValue ops(GetPattern()); uint64 result = ops.second.q + ops.first.q; PushCst(static_cast(result)); PushCst(static_cast(result >> 32)); } else if(FitsPattern()) { CommutativeRelativeConstant64::PatternValue ops(GetPattern()); if(ops.second.q == 0) { //Simple copy PushRel(ops.first.d0); PushRel(ops.first.d1); } else { unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); LoadRelativeInRegister(resultLow, ops.first.d0); LoadRelativeInRegister(resultHigh, ops.first.d1); m_Assembler.AddId(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), ops.second.d0); m_Assembler.AdcId(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh]), ops.second.d1); PushReg(resultLow); PushReg(resultHigh); } } else if(FitsPattern()) { ZeroWithSomethingCommutative64::PatternValue ops(GetPattern()); //We have something like : op + 0 //We just need to copy it over m_Shadow.Push(ops.first.d0); m_Shadow.Push(ops.first.d1); m_Shadow.Push(ops.second.d0); m_Shadow.Push(ops.second.d1); } else { uint32 value[4]; uint32 valueType[4]; for(int i = 3; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); EmitOp(Op_Add, valueType[2], value[2], resultLow); EmitOp(Op_Adc, valueType[3], value[3], resultHigh); PushReg(resultLow); PushReg(resultHigh); } } void CCodeGen::And() { GenericLogical(Op_And); } void CCodeGen::And64() { if(FitsPattern()) { CommutativeRelativeConstant64::PatternValue ops(GetPattern()); for(unsigned int i = 0; i < 2; i++) { if(ops.second.d[i] == 0) { //x & 0 = 0 PushCst(0); continue; } unsigned int registerId = AllocateRegister(); LoadRelativeInRegister(registerId, ops.first.d[i]); m_Assembler.AndId(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), ops.second.d[i]); PushReg(registerId); } } else { uint32 value[4]; uint32 valueType[4]; for(int i = 3; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); EmitOp(Op_And, valueType[2], value[2], resultLow); EmitOp(Op_And, valueType[3], value[3], resultHigh); PushReg(resultLow); PushReg(resultHigh); } } void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet) { #ifdef AMD64 unsigned int nParamReg[4] = { 1, 2, 6, 7, }; assert(nParamCount <= 4); assert(m_nRegisterAllocated[nParamReg[0]] == false); assert(m_nRegisterAllocated[nParamReg[1]] == false); assert(m_nRegisterAllocated[nParamReg[2]] == false); assert(m_nRegisterAllocated[nParamReg[3]] == false); #endif unsigned int additionalStack = 0; #ifdef MACOSX //MacOS requires us to keep esp aligned on 16 bytes boundaries... additionalStack = (4 - (nParamCount & 3)) & 3; if(additionalStack != 0) { m_Assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), additionalStack * 4); } #endif for(unsigned int i = 0; i < nParamCount; i++) { if(m_Shadow.GetAt(0) == RELATIVE) { uint32 nRelative; m_Shadow.Pull(); nRelative = m_Shadow.Pull(); #ifdef AMD64 LoadRelativeInRegister(nParamReg[nParamCount - 1 - i], nRelative); #else //push [nBase + nRel] m_Assembler.PushEd( CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, nRelative)); #endif } else if(m_Shadow.GetAt(0) == REGISTER) { uint32 nRegister; m_Shadow.Pull(); nRegister = m_Shadow.Pull(); if(!RegisterHasNextUse(nRegister)) { FreeRegister(nRegister); } #ifdef AMD64 //mov param_reg, reg CopyRegister(nParamReg[nParamCount - 1 - i], nRegister); #else //push reg m_Assembler.Push(m_nRegisterLookupEx[nRegister]); #endif } else if((m_Shadow.GetAt(0) == REFERENCE) || (m_Shadow.GetAt(0) == CONSTANT)) { uint32 nNumber; m_Shadow.Pull(); nNumber = m_Shadow.Pull(); #ifdef AMD64 //mov reg, nNumber LoadConstantInRegister(nParamReg[nParamCount - 1 - i], nNumber); #else //push nNumber m_Assembler.PushId(nNumber); #endif } else { assert(0); } } if(m_nRegisterAllocated[0]) { //This register is going to be scrapped, gotta save it... unsigned int nSaveReg; nSaveReg = AllocateRegister(REGISTER_SAVED); CopyRegister(nSaveReg, 0); ReplaceRegisterInStack(nSaveReg, 0); FreeRegister(0); } unsigned int nCallRegister = AllocateRegister(); #ifdef AMD64 unsigned int nRegIndex; if(nParamCount != 0) { //sub rsp, (nParams * 0x08) m_pBlock->StreamWrite(3, 0x83, 0xC0 | (0x05 << 3) | (0x04), nParamCount * 0x08); } //mov reg, nFuncAddress LoadConstantInRegister64(nCallRegister, (uint64)((uint8*)pFunc - (uint8*)0)); //call reg nRegIndex = m_nRegisterLookup[nCallRegister]; if(nRegIndex > 7) { //REX byte m_pBlock->StreamWrite(1, 0x41); nRegIndex &= 7; } m_pBlock->StreamWrite(2, 0xFF, 0xD0 | (nRegIndex)); if(nParamCount != 0) { //add esp, 0x08 m_pBlock->StreamWrite(3, 0x83, 0xC0 | (0x00 << 3) | (0x04), nParamCount * 0x08); } #else //mov reg, pFunc m_Assembler.MovId( m_nRegisterLookupEx[nCallRegister], static_cast(reinterpret_cast(pFunc) - reinterpret_cast(NULL))); //call reg m_Assembler.CallEd( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nCallRegister])); if(nParamCount != 0) { //add esp, nParams * 4; m_Assembler.AddId( CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), (nParamCount + additionalStack) * 4); } #endif FreeRegister(nCallRegister); if(nKeepRet) { assert(m_nRegisterAllocated[0] == false); m_nRegisterAllocated[0] = true; m_Shadow.Push(0); m_Shadow.Push(REGISTER); } } void CCodeGen::Cmp(CONDITION nCondition) { if( (nCondition == CONDITION_EQ || nCondition == CONDITION_NE) && FitsPattern() ) { CommutativeRelativeConstant::PatternValue ops(GetPattern()); unsigned int resultRegister = AllocateRegister(REGISTER_HASLOW); //cmp [relative], $constant m_Assembler.CmpId( CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first), ops.second); if(nCondition == CONDITION_EQ) { //sete reg[l] m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); } else if(nCondition == CONDITION_NE) { //setne reg[l] m_Assembler.SetneEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); } else { throw exception(); } //movzx reg, reg[l] m_Assembler.MovzxEb(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); PushReg(resultRegister); } else if( nCondition == CONDITION_EQ && FitsPattern() ) { ConstantConstant::PatternValue ops(GetPattern()); unsigned int resultRegister = AllocateRegister(); LoadConstantInRegister(resultRegister, ops.first == ops.second ? 1 : 0); PushReg(resultRegister); } else if(IsTopRegZeroPairCom() && (nCondition == CONDITION_EQ)) { unsigned int valueRegister; GetRegCstPairCom(&valueRegister, NULL); if(!RegisterHasNextUse(valueRegister)) { FreeRegister(valueRegister); } //test reg, reg m_Assembler.TestEd(m_nRegisterLookupEx[valueRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[valueRegister])); unsigned int resultRegister = AllocateRegister(REGISTER_HASLOW); //sete reg[l] m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); //movzx reg, reg[l] m_Assembler.MovzxEb(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); PushReg(resultRegister); } else if(FitsPattern()) { RegisterRegister::PatternValue ops = GetPattern(); unsigned int resultRegister = AllocateRegister(REGISTER_HASLOW); //cmp op1, op2 m_Assembler.CmpEd(m_nRegisterLookupEx[ops.first], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[ops.second])); switch(nCondition) { case CONDITION_EQ: //sete res[l] m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); break; case CONDITION_BL: //setb res[l] m_Assembler.SetbEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); break; case CONDITION_GT: //setgt res[l] m_Assembler.SetgEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); break; default: throw exception(); break; } //movzx reg, reg[l] m_Assembler.MovzxEb(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); if(!RegisterHasNextUse(ops.first)) FreeRegister(ops.first); if(!RegisterHasNextUse(ops.second)) FreeRegister(ops.second); PushReg(resultRegister); } else if(FitsPattern()) { ConstantRelative::PatternValue ops = GetPattern(); unsigned int register1 = AllocateRegister(); unsigned int register2 = AllocateRegister(); LoadConstantInRegister(register1, ops.first); LoadRelativeInRegister(register2, ops.second); PushReg(register1); PushReg(register2); Cmp(nCondition); } else if(FitsPattern()) { RegisterConstant::PatternValue ops = GetPattern(); unsigned int register1 = ops.first; unsigned int register2 = AllocateRegister(); LoadConstantInRegister(register2, ops.second); PushReg(register1); PushReg(register2); Cmp(nCondition); } else if(FitsPattern()) { RelativeRelative::PatternValue ops = GetPattern(); unsigned int register1 = AllocateRegister(); unsigned int register2 = AllocateRegister(); LoadRelativeInRegister(register1, ops.first); LoadRelativeInRegister(register2, ops.second); PushReg(register1); PushReg(register2); Cmp(nCondition); } /* else if((m_Shadow.GetAt(2) == REGISTER) && (m_Shadow.GetAt(0) == CONSTANT)) { uint32 nConstant; unsigned int nRegister; m_Shadow.Pull(); nConstant = m_Shadow.Pull(); m_Shadow.Pull(); nRegister = m_Shadow.Pull(); if(GetMinimumConstantSize(nConstant) == 1) { //cmp reg, Immediate m_pBlock->StreamWrite(3, 0x83, 0xC0 | (0x07 << 3) | (m_nRegisterLookup[nRegister]), (uint8)nConstant); } else { //cmp reg, Immediate m_pBlock->StreamWrite(2, 0x81, 0xC0 | (0x07 << 3) | (m_nRegisterLookup[nRegister])); m_pBlock->StreamWriteWord(nConstant); } LoadConditionInRegister(nRegister, nCondition); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } */ else { throw exception(); } } void CCodeGen::Cmp64(CONDITION nCondition) { #ifdef AMD64 if(IsTopContRelPair64() || IsTopContRelCstPair64()) { //Can be done easily using 64-bits regs Cmp64Cont(nCondition); } else #endif { switch(nCondition) { case CONDITION_BL: case CONDITION_LT: Cmp64Lt(nCondition == CONDITION_LT, false); break; case CONDITION_LE: Cmp64Lt(nCondition == CONDITION_LE, true); break; case CONDITION_EQ: Cmp64Eq(); break; default: assert(0); break; } } } void CCodeGen::Div_Base(const MultFunction& function, bool isSigned) { if(FitsPattern()) { RelativeConstant::PatternValue ops(GetPattern()); //We need eax and edx for this assert(!m_nRegisterAllocated[REGISTER_EAX] && !m_nRegisterAllocated[REGISTER_EDX]); m_nRegisterAllocated[REGISTER_EAX] = true; m_nRegisterAllocated[REGISTER_EDX] = true; unsigned int lowRegister = REGISTER_EAX; unsigned int highRegister = REGISTER_EDX; unsigned int tempRegister = AllocateRegister(); LoadRelativeInRegister(lowRegister, ops.first); LoadConstantInRegister(tempRegister, ops.second); if(isSigned) { m_Assembler.Cdq(); } else { m_Assembler.XorEd(m_nRegisterLookupEx[highRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[highRegister])); } function(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister])); FreeRegister(tempRegister); PushReg(highRegister); PushReg(lowRegister); } else if(FitsPattern()) { ConstantRelative::PatternValue ops(GetPattern()); //We need eax and edx for this assert(!m_nRegisterAllocated[REGISTER_EAX] && !m_nRegisterAllocated[REGISTER_EDX]); m_nRegisterAllocated[REGISTER_EAX] = true; m_nRegisterAllocated[REGISTER_EDX] = true; unsigned int lowRegister = REGISTER_EAX; unsigned int highRegister = REGISTER_EDX; LoadConstantInRegister(lowRegister, ops.first); if(isSigned) { m_Assembler.Cdq(); } else { m_Assembler.XorEd(m_nRegisterLookupEx[highRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[highRegister])); } function(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(highRegister); PushReg(lowRegister); } else if(FitsPattern()) { RelativeRelative::PatternValue ops(GetPattern()); //We need eax and edx for this assert(!m_nRegisterAllocated[REGISTER_EAX] && !m_nRegisterAllocated[REGISTER_EDX]); m_nRegisterAllocated[REGISTER_EAX] = true; m_nRegisterAllocated[REGISTER_EDX] = true; unsigned int lowRegister = REGISTER_EAX; unsigned int highRegister = REGISTER_EDX; LoadRelativeInRegister(lowRegister, ops.first); if(isSigned) { m_Assembler.Cdq(); } else { m_Assembler.XorEd(m_nRegisterLookupEx[highRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[highRegister])); } function(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(highRegister); PushReg(lowRegister); } else if(FitsPattern()) { ConstantConstant::PatternValue ops(GetPattern()); uint32 result = 0, remainder = 0; if(isSigned) { result = static_cast(ops.first) / static_cast(ops.second); remainder = static_cast(ops.first) % static_cast(ops.second); } else { result = ops.first / ops.second; remainder = ops.first % ops.second; } PushCst(remainder); PushCst(result); } else { throw exception(); } } void CCodeGen::Div() { Div_Base(bind(&CX86Assembler::DivEd, &m_Assembler, _1), false); } void CCodeGen::DivS() { Div_Base(bind(&CX86Assembler::IdivEd, &m_Assembler, _1), true); } void CCodeGen::Lookup(uint32* table) { if(FitsPattern()) { SingleRegister::PatternValue indexRegister(GetPattern()); unsigned int resultRegister = RegisterHasNextUse(indexRegister) ? AllocateRegister() : indexRegister; unsigned int baseRegister = AllocateRegister(); m_Assembler.MovId(m_nRegisterLookupEx[baseRegister], static_cast(reinterpret_cast(table) - static_cast(NULL))); m_Assembler.MovEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeBaseIndexScaleAddress(m_nRegisterLookupEx[baseRegister], m_nRegisterLookupEx[resultRegister], 4)); FreeRegister(baseRegister); PushReg(resultRegister); } else { assert(0); } } void CCodeGen::Lzc() { if(FitsPattern()) { SingleRelative::PatternValue op = GetPattern(); uint32 registerId = AllocateRegister(); LoadRelativeInRegister(registerId, op); CX86Assembler::LABEL set32Label = m_Assembler.CreateLabel(); CX86Assembler::LABEL startCountLabel = m_Assembler.CreateLabel(); CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel(); m_Assembler.CmpId(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), -1); m_Assembler.JeJb(set32Label); m_Assembler.TestEd(m_nRegisterLookupEx[registerId], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId])); m_Assembler.JeJb(set32Label); m_Assembler.JnsJb(startCountLabel); m_Assembler.NotEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId])); //startCount: m_Assembler.MarkLabel(startCountLabel); m_Assembler.BsrEd(m_nRegisterLookupEx[registerId], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId])); m_Assembler.NegEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId])); m_Assembler.AddId(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), 0x1E); m_Assembler.JmpJb(doneLabel); //set32 m_Assembler.MarkLabel(set32Label); m_Assembler.MovId(m_nRegisterLookupEx[registerId], 0x1F); //done m_Assembler.MarkLabel(doneLabel); m_Assembler.ResolveLabelReferences(); PushReg(registerId); } else { throw exception(); } } void CCodeGen::Mult() { Mult_Base(bind(&CX86Assembler::MulEd, &m_Assembler, _1), false); } void CCodeGen::MultS() { Mult_Base(bind(&CX86Assembler::ImulEd, &m_Assembler, _1), true); } void CCodeGen::Mult_Base(const MultFunction& multFunction, bool isSigned) { if(FitsPattern()) { CommutativeRelativeConstant::PatternValue ops(GetPattern()); //We need eax and edx for this if(m_nRegisterAllocated[REGISTER_EAX] || m_nRegisterAllocated[REGISTER_EDX]) { throw runtime_error("Needed registers are allocated."); } m_nRegisterAllocated[REGISTER_EAX] = true; m_nRegisterAllocated[REGISTER_EDX] = true; unsigned int lowRegister = REGISTER_EAX; unsigned int highRegister = REGISTER_EDX; LoadRelativeInRegister(lowRegister, ops.first); LoadConstantInRegister(highRegister, ops.second); multFunction(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[highRegister])); PushReg(highRegister); PushReg(lowRegister); } else if(FitsPattern()) { RelativeRelative::PatternValue ops(GetPattern()); //We need eax and edx for this if(m_nRegisterAllocated[REGISTER_EAX] || m_nRegisterAllocated[REGISTER_EDX]) { throw runtime_error("Needed registers are allocated."); } m_nRegisterAllocated[REGISTER_EAX] = true; m_nRegisterAllocated[REGISTER_EDX] = true; unsigned int lowRegister = REGISTER_EAX; unsigned int highRegister = REGISTER_EDX; LoadRelativeInRegister(lowRegister, ops.first); multFunction(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(highRegister); PushReg(lowRegister); } else if(FitsPattern()) { ConstantConstant::PatternValue ops(GetPattern()); INTEGER64 result; if(isSigned) { result.q = static_cast(ops.first) * static_cast(ops.second); } else { result.q = static_cast(ops.first) * static_cast(ops.second); } PushCst(result.d1); PushCst(result.d0); } else { assert(0); } } void CCodeGen::Not() { if(FitsPattern()) { SingleRegister::PatternValue resultRegister = GetPattern(); assert(!RegisterHasNextUse(resultRegister)); m_Assembler.NotEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); PushReg(resultRegister); } else if(FitsPattern()) { SingleConstant::PatternValue constant = GetPattern(); PushCst(~constant); } else { throw runtime_error("Unhandled case."); } } void CCodeGen::GenericLogical(const GenericOp& operation) { if(FitsPattern()) { RegisterRegister::PatternValue ops(GetPattern()); uint32 nRegister1 = ops.first; uint32 nRegister2 = ops.second; //This register will change... Make sure there's no next uses if(RegisterHasNextUse(nRegister1)) { //Must save or something... assert(0); } //Can free this register if(!RegisterHasNextUse(nRegister2)) { FreeRegister(nRegister2); } ((m_Assembler).*(operation.registerAddressOp))(m_nRegisterLookupEx[nRegister1], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister2])); PushReg(nRegister1); } else if(FitsPattern()) { RelativeRelative::PatternValue ops(GetPattern()); unsigned int nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, ops.first); ((m_Assembler).*(operation.registerAddressOp))(m_nRegisterLookupEx[nRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(nRegister); } else if(FitsPattern()) { ConstantConstant::PatternValue ops(GetPattern()); uint32 result = operation.constantConstantOp(ops.first, ops.second); PushCst(result); } else if(FitsPattern()) { CommutativeRegisterConstant::PatternValue ops(GetPattern()); ((m_Assembler).*(operation.addressConstantOp))( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[ops.first]), ops.second); PushReg(ops.first); } else if(FitsPattern()) { CommutativeRelativeConstant::PatternValue ops(GetPattern()); unsigned int nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, ops.first); PushReg(nRegister); if(!operation.isNullOp(ops.second)) { PushCst(ops.second); GenericLogical(operation); } } else if(FitsPattern()) { CommutativeRelativeRegister::PatternValue ops(GetPattern()); unsigned int resultRegister; if(!RegisterHasNextUse(ops.second)) { resultRegister = ops.second; } else { resultRegister = AllocateRegister(); } ((m_Assembler).*(operation.registerAddressOp))(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first)); PushReg(resultRegister); } else { assert(0); } } void CCodeGen::Or() { GenericLogical(Op_Or); } void CCodeGen::SeX() { if(m_Shadow.GetAt(0) == CONSTANT) { uint32 constant = m_Shadow.GetAt(1); //Sign extend the constant and push it on the stack PushCst(constant & 0x80000000 ? 0xFFFFFFFF : 0x00000000); } else { ReduceToRegister(); m_Shadow.Pull(); unsigned int valueRegister = m_Shadow.Pull(); unsigned int resultRegister = AllocateRegister(); CopyRegister(resultRegister, valueRegister); m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister]), 0x1F); PushReg(valueRegister); PushReg(resultRegister); } } void CCodeGen::SeX8() { if(FitsPattern()) { SingleRegister::PatternValue registerId(GetPattern()); assert(!RegisterHasNextUse(registerId)); m_Assembler.MovsxEb(m_nRegisterLookupEx[registerId], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[registerId])); PushReg(registerId); } else { assert(0); } } void CCodeGen::SeX16() { if(FitsPattern()) { SingleConstant::PatternValue op = GetPattern(); PushCst(static_cast(op)); } else { ReduceToRegister(); m_Shadow.Pull(); uint32 nRegister = m_Shadow.Pull(); m_Assembler.MovsxEw(m_nRegisterLookupEx[nRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister])); PushReg(nRegister); } } void CCodeGen::Shl() { if(FitsPattern()) { RelativeRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadRelativeInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else if(FitsPattern()) { ConstantRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadConstantInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else if(FitsPattern()) { ConstantConstant::PatternValue ops = GetPattern(); PushCst(ops.first << ops.second); } else { throw exception(); } } void CCodeGen::Shl(uint8 nAmount) { if(FitsPattern()) { SingleRegister::PatternValue op = GetPattern(); unsigned int resultRegister; if(RegisterHasNextUse(op)) { resultRegister = AllocateRegister(); CopyRegister(resultRegister, op); } else { resultRegister = op; } m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister]), nAmount); PushReg(resultRegister); } else if(FitsPattern()) { UnaryRelativeSelfCallAsRegister(bind(&CCodeGen::Shl, this, nAmount)); } else if(FitsPattern()) { SingleConstant::PatternValue op = GetPattern(); PushCst(op << nAmount); } else { throw exception(); } } void CCodeGen::Shl64() { { uint32 value[3]; uint32 valueType[3]; for(int i = 2; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } assert(valueType[2] != CONSTANT); CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel(); CX86Assembler::LABEL more32Label = m_Assembler.CreateLabel(); unsigned int amountReg = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); EmitLoad(valueType[2], value[2], amountReg); m_Assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x3F); m_Assembler.TestEb(m_nRegisterLookupEx[amountReg], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg])); m_Assembler.JeJb(doneLabel); m_Assembler.CmpIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x20); m_Assembler.JaeJb(more32Label); m_Assembler.ShldEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh]), m_nRegisterLookupEx[resultLow]); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow])); m_Assembler.JmpJb(doneLabel); //$more32 m_Assembler.MarkLabel(more32Label); m_Assembler.MovEd(m_nRegisterLookupEx[resultHigh], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow])); m_Assembler.XorEd(m_nRegisterLookupEx[resultLow], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow])); m_Assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x1F); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh])); //$done m_Assembler.MarkLabel(doneLabel); m_Assembler.ResolveLabelReferences(); PushReg(resultLow); PushReg(resultHigh); FreeRegister(amountReg); } } void CCodeGen::Shl64(uint8 nAmount) { nAmount &= 0x3F; if(FitsPattern()) { RelativeRelative::PatternValue ops(GetPattern()); uint32 nRelative1 = ops.first; uint32 nRelative2 = ops.second; assert(nAmount < 0x40); #ifdef AMD64 throw runtime_error("Not implemented."); /* if((nRelative2 - nRelative1) == 4) { unsigned int nRegister; nRegister = AllocateRegister(); LoadRelativeInRegister64(nRegister, nRelative1); assert(m_nRegisterLookup[nRegister] < 8); //shl reg, amount m_pBlock->StreamWrite(4, 0x48, 0xC1, MakeRegFunRm(nRegister, 0x04), nAmount); PushReg64(nRegister); } else */ #endif { if(nAmount == 0) { uint32 nRegister1, nRegister2; nRegister1 = AllocateRegister(); nRegister2 = AllocateRegister(); LoadRelativeInRegister(nRegister1, nRelative1); LoadRelativeInRegister(nRegister2, nRelative2); PushReg(nRegister1); PushReg(nRegister2); } else if(nAmount == 32) { uint32 nRegister; nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative1); PushCst(0); PushReg(nRegister); } else if(nAmount > 32) { uint32 nRegister; nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative1); //shl reg, amount m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), nAmount & 0x1F); PushCst(0); PushReg(nRegister); } else { uint32 nRegister1, nRegister2; nRegister1 = AllocateRegister(); nRegister2 = AllocateRegister(); LoadRelativeInRegister(nRegister1, nRelative1); LoadRelativeInRegister(nRegister2, nRelative2); //shld nReg2, nReg1, nAmount m_Assembler.ShldEd( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister2]), m_nRegisterLookupEx[nRegister1], nAmount); //shl nReg1, nAmount m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister1]), nAmount); PushReg(nRegister1); PushReg(nRegister2); } } } else if(FitsPattern()) { RelativeConstant::PatternValue ops(GetPattern()); if(nAmount < 32) { unsigned int register1 = AllocateRegister(); unsigned int register2 = AllocateRegister(); LoadRelativeInRegister(register1, ops.first); LoadConstantInRegister(register2, ops.second); m_Assembler.ShldEd( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[register2]), m_nRegisterLookupEx[register1], nAmount); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[register1]), nAmount); PushReg(register1); PushReg(register2); } else if(nAmount == 32) { PushCst(0); PushRel(ops.first); } else if(nAmount > 32) { unsigned int resultRegister = AllocateRegister(); LoadRelativeInRegister(resultRegister, ops.first); m_Assembler.ShlEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister]), nAmount - 32); PushCst(0); PushReg(resultRegister); } else { assert(0); } } else if(FitsPattern()) { SingleConstant64::PatternValue ops(GetPattern()); ops.q <<= nAmount; PushCst(ops.d0); PushCst(ops.d1); } else { assert(0); } } void CCodeGen::Sra() { if(FitsPattern()) { RelativeRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadRelativeInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else if(FitsPattern()) { ConstantRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadConstantInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else { assert(0); } } void CCodeGen::Sra(uint8 nAmount) { if(FitsPattern()) { SingleRegister::PatternValue registerId(GetPattern()); m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), nAmount); PushReg(registerId); } else if(FitsPattern()) { UnaryRelativeSelfCallAsRegister(bind(&CCodeGen::Sra, this, nAmount)); } else { assert(0); } } void CCodeGen::Sra64(uint8 nAmount) { if(FitsPattern()) { assert(0); } else { uint32 value[2]; uint32 valueType[2]; for(int i = 1; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } assert(nAmount < 0x40); if(nAmount >= 32) { uint32 resultLow = AllocateRegister(); EmitLoad(valueType[1], value[1], resultLow); if(nAmount != 32) { //sar reg, amount m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), nAmount & 0x1F); } PushReg(resultLow); SeX(); } else //Amount < 32 { unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); if(nAmount != 0) { //shrd nReg1, nReg2, nAmount m_Assembler.ShrdEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), m_nRegisterLookupEx[resultHigh], nAmount); //sar nReg2, nAmount m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh]), nAmount); } PushReg(resultLow); PushReg(resultHigh); } } /* if(FitsPattern()) { RelativeRelative::PatternValue ops(GetPattern()); nAmount &= 0x3F; if(nAmount == 32) { PushRel(ops.second); SeX(); } else if(nAmount > 32) { PushRel(ops.second); Sra(nAmount - 32); SeX(); } else { assert(0); } } else if(FitsPattern()) { ConstantRelative::PatternValue ops(GetPattern()); nAmount &= 0x3F; if(nAmount == 32) { PushRel(ops.second); SeX(); } else if(nAmount > 32) { PushRel(ops.second); Sra(nAmount - 32); SeX(); } else { assert(0); } } else { assert(0); } */ } void CCodeGen::Srl() { if(FitsPattern()) { RelativeRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadRelativeInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else if(FitsPattern()) { ConstantRelative::PatternValue ops = GetPattern(); unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultRegister = AllocateRegister(); LoadConstantInRegister(resultRegister, ops.first); LoadRelativeInRegister(shiftAmount, ops.second); m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(shiftAmount); PushReg(resultRegister); } else if(FitsPattern()) { RelativeConstant::PatternValue ops = GetPattern(); PushRel(ops.first); Srl(static_cast(ops.second)); } else { assert(0); } } void CCodeGen::Srl(uint8 nAmount) { if(FitsPattern()) { SingleRegister::PatternValue registerId = GetPattern(); //shr nRegister, nAmount m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), nAmount); PushReg(registerId); } else if(FitsPattern()) { UnaryRelativeSelfCallAsRegister(bind(&CCodeGen::Srl, this, nAmount)); } else if(FitsPattern()) { SingleConstant::PatternValue op = GetPattern(); PushCst(op >> nAmount); } else { assert(0); } } void CCodeGen::Srl64() { { uint32 value[3]; uint32 valueType[3]; for(int i = 2; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } assert(valueType[2] != CONSTANT); CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel(); CX86Assembler::LABEL more32Label = m_Assembler.CreateLabel(); unsigned int amountReg = AllocateRegister(REGISTER_SHIFTAMOUNT); unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); EmitLoad(valueType[2], value[2], amountReg); m_Assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x3F); m_Assembler.TestEb(m_nRegisterLookupEx[amountReg], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg])); m_Assembler.JeJb(doneLabel); m_Assembler.CmpIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x20); m_Assembler.JaeJb(more32Label); m_Assembler.ShrdEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), m_nRegisterLookupEx[resultHigh]); m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh])); m_Assembler.JmpJb(doneLabel); //$more32 m_Assembler.MarkLabel(more32Label); m_Assembler.MovEd(m_nRegisterLookupEx[resultLow], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh])); m_Assembler.XorEd(m_nRegisterLookupEx[resultHigh], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh])); m_Assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[amountReg]), 0x1F); m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow])); //$done m_Assembler.MarkLabel(doneLabel); m_Assembler.ResolveLabelReferences(); FreeRegister(amountReg); PushReg(resultLow); PushReg(resultHigh); } } void CCodeGen::Srl64(uint8 nAmount) { if(FitsPattern()) { SingleConstant64::PatternValue ops(GetPattern()); ops.q >>= nAmount; PushCst(ops.d0); PushCst(ops.d1); } else { uint32 value[2]; uint32 valueType[2]; for(int i = 1; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } assert(nAmount < 0x40); if(nAmount >= 32) { uint32 resultLow = AllocateRegister(); EmitLoad(valueType[1], value[1], resultLow); if(nAmount != 32) { //shr reg, amount m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), nAmount & 0x1F); } PushReg(resultLow); PushCst(0); } else //Amount < 32 { unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); if(nAmount != 0) { //shrd nReg1, nReg2, nAmount m_Assembler.ShrdEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultLow]), m_nRegisterLookupEx[resultHigh], nAmount); //shr nReg2, nAmount m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultHigh]), nAmount); } PushReg(resultLow); PushReg(resultHigh); } } } void CCodeGen::Sub() { if((m_Shadow.GetAt(0) == RELATIVE) && (m_Shadow.GetAt(2) == RELATIVE)) { uint32 nRelative1, nRelative2, nRegister; m_Shadow.Pull(); nRelative2 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative1 = m_Shadow.Pull(); nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative1); m_Assembler.SubEd( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, nRelative2)); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } else if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == RELATIVE)) { uint32 nRelative, nConstant, nRegister; m_Shadow.Pull(); nConstant = m_Shadow.Pull(); m_Shadow.Pull(); nRelative = m_Shadow.Pull(); nRegister = AllocateRegister(); LoadRelativeInRegister(nRegister, nRelative); m_Assembler.SubId( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), nConstant); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } else if(FitsPattern()) { ConstantRelative::PatternValue ops(GetPattern()); unsigned int resultRegister = AllocateRegister(); LoadConstantInRegister(resultRegister, ops.first); m_Assembler.SubEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); PushReg(resultRegister); } else if(FitsPattern()) { ConstantConstant::PatternValue ops(GetPattern()); PushCst(ops.first - ops.second); } else { throw exception(); } } void CCodeGen::Sub64() { { uint32 value[4]; uint32 valueType[4]; for(int i = 3; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } unsigned int resultLow = AllocateRegister(); unsigned int resultHigh = AllocateRegister(); EmitLoad(valueType[0], value[0], resultLow); EmitLoad(valueType[1], value[1], resultHigh); EmitOp(Op_Sub, valueType[2], value[2], resultLow); EmitOp(Op_Sbb, valueType[3], value[3], resultHigh); PushReg(resultLow); PushReg(resultHigh); } } void CCodeGen::Xor() { GenericLogical(Op_Xor); } void CCodeGen::Cmp64Eq() { if( m_Shadow.GetAt(4) == CONSTANT && m_Shadow.GetAt(0) == CONSTANT && m_Shadow.GetAt(1) == m_Shadow.GetAt(5) ) { m_Shadow.Pull(); m_Shadow.Pull(); uint32 type1 = m_Shadow.Pull(); uint32 value1 = m_Shadow.Pull(); m_Shadow.Pull(); m_Shadow.Pull(); uint32 type0 = m_Shadow.Pull(); uint32 value0 = m_Shadow.Pull(); m_Shadow.Push(value0); m_Shadow.Push(type0); m_Shadow.Push(value1); m_Shadow.Push(type1); Cmp(CONDITION_EQ); } else if(FitsPattern()) { RelativeRelative64::PatternValue ops(GetPattern()); uint32 nRegister1 = AllocateRegister(REGISTER_HASLOW); uint32 nRegister2 = AllocateRegister(REGISTER_HASLOW); LoadRelativeInRegister(nRegister1, ops.first.d1); m_Assembler.CmpEd(m_nRegisterLookupEx[nRegister1], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second.d1)); m_Assembler.SeteEb(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister1])); LoadRelativeInRegister(nRegister2, ops.first.d0); m_Assembler.CmpEd(m_nRegisterLookupEx[nRegister2], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second.d0)); m_Assembler.SeteEb(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister2])); m_Assembler.AndEd(m_nRegisterLookupEx[nRegister1], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister2])); m_Assembler.MovzxEb(m_nRegisterLookupEx[nRegister1], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister1])); FreeRegister(nRegister2); m_Shadow.Push(nRegister1); m_Shadow.Push(REGISTER); } else if(FitsPattern()) { CommutativeRelativeConstant64::PatternValue ops = GetPattern(); unsigned int resultRegister = AllocateRegister(REGISTER_HASLOW); unsigned int tempRegister = AllocateRegister(REGISTER_HASLOW); m_Assembler.CmpId(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first.d1), ops.second.d1); m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); m_Assembler.CmpId(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first.d0), ops.second.d0); m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[tempRegister])); m_Assembler.AndEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister])); m_Assembler.MovzxEb(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(tempRegister); PushReg(resultRegister); } else { uint32 value[4]; uint32 valueType[4]; for(int i = 3; i >= 0; i--) { valueType[i] = m_Shadow.Pull(); value[i] = m_Shadow.Pull(); } unsigned int resultRegister = AllocateRegister(REGISTER_HASLOW); unsigned int tempRegister = AllocateRegister(REGISTER_HASLOW); EmitLoad(valueType[0], value[0], resultRegister); EmitOp(Op_Cmp, valueType[2], value[2], resultRegister); m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); EmitLoad(valueType[1], value[1], tempRegister); EmitOp(Op_Cmp, valueType[3], value[3], tempRegister); m_Assembler.SeteEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[tempRegister])); m_Assembler.AndEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister])); m_Assembler.MovzxEb(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[resultRegister])); FreeRegister(tempRegister); PushReg(resultRegister); } } void CCodeGen::Cmp64Lt(bool nSigned, bool nOrEqual) { uint32 nValue[4]; uint32 nValueType[4]; for(int i = 3; i >= 0; i--) { nValueType[i] = m_Shadow.Pull(); nValue[i] = m_Shadow.Pull(); } uint32 nRegister = AllocateRegister(); { CX86Assembler::LABEL highOrderEqualLabel = m_Assembler.CreateLabel(); CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel(); ///////////////////////////////////////// //Check high order word if equal //mov reg, dword ptr[base + rel2] EmitLoad(nValueType[1], nValue[1], nRegister); EmitOp(Op_Cmp, nValueType[3], nValue[3], nRegister); //je highOrderEqual m_Assembler.JeJb(highOrderEqualLabel); /////////////////////////////////////////////////////////// //If they aren't equal, this comparaison decides of result //setb/l reg[l] if(nSigned) { m_Assembler.SetlEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); } else { m_Assembler.SetbEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); } //movzx reg, reg[l] m_Assembler.MovzxEb( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); //jmp done m_Assembler.JmpJb(doneLabel); //highOrderEqual: ///////////////////////////////////// m_Assembler.MarkLabel(highOrderEqualLabel); //If they are equal, next comparaison decides of result EmitLoad(nValueType[0], nValue[0], nRegister); EmitOp(Op_Cmp, nValueType[2], nValue[2], nRegister); //setb/be reg[l] if(nOrEqual) { m_Assembler.SetbeEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); } else { m_Assembler.SetbEb(CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); } //movzx reg, reg[l] m_Assembler.MovzxEb( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeByteRegisterAddress(m_nRegisterLookupEx[nRegister])); //done: /////////////////////////////////////////////// m_Assembler.MarkLabel(doneLabel); m_Assembler.ResolveLabelReferences(); } m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); } void CCodeGen::Cmp64Cont(CONDITION nCondition) { #ifdef AMD64 uint32 nRegister; nRegister = AllocateRegister(REGISTER_HASLOW); if( (m_Shadow.GetAt(0) == RELATIVE) && (m_Shadow.GetAt(2) == RELATIVE) && (m_Shadow.GetAt(4) == RELATIVE) && (m_Shadow.GetAt(6) == RELATIVE) ) { uint32 nRelative1, nRelative2, nRelative3, nRelative4; m_Shadow.Pull(); nRelative4 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative3 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative2 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative1 = m_Shadow.Pull(); //Emit the comparason instruction LoadRelativeInRegister64(nRegister, nRelative1); //cmp reg, qword ptr[base + rel4] m_Assembler.CmpEq( m_nRegisterLookupEx[nRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, nRelative3)); } else if( (m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == CONSTANT) && (m_Shadow.GetAt(4) == RELATIVE) && (m_Shadow.GetAt(6) == RELATIVE) ) { uint64 nConstant; uint64 nConstant1, nConstant2; uint32 nRelative1, nRelative2; m_Shadow.Pull(); nConstant2 = m_Shadow.Pull(); m_Shadow.Pull(); nConstant1 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative2 = m_Shadow.Pull(); m_Shadow.Pull(); nRelative1 = m_Shadow.Pull(); LoadRelativeInRegister64(nRegister, nRelative1); nConstant = (nConstant2 << 32) | (nConstant1); m_Assembler.CmpIq( CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[nRegister]), nConstant); } else { assert(0); } uint8 nInstruction; switch(nCondition) { case CONDITION_EQ: nInstruction = 0x94; break; case CONDITION_LT: nInstruction = 0x9C; break; case CONDITION_BL: nInstruction = 0x92; break; case CONDITION_LE: nInstruction = 0x9E; break; default: assert(0); break; } //setcc reg[l] m_pBlock->StreamWrite(3, 0x0F, nInstruction, 0xC0 | (0x00 << 3) | (m_nRegisterLookup[nRegister])); //movzx reg, reg[l] m_pBlock->StreamWrite(3, 0x0F, 0xB6, 0xC0 | (m_nRegisterLookup[nRegister] << 3) | (m_nRegisterLookup[nRegister])); m_Shadow.Push(nRegister); m_Shadow.Push(REGISTER); #endif } bool CCodeGen::IsTopRegZeroPairCom() { return ((m_Shadow.GetAt(0) == CONSTANT)&& (m_Shadow.GetAt(1) == 0) && (m_Shadow.GetAt(2) == REGISTER)) || ((m_Shadow.GetAt(0) == REGISTER) && (m_Shadow.GetAt(2) == CONSTANT) && (m_Shadow.GetAt(3) == 0)); } void CCodeGen::GetRegCstPairCom(unsigned int* pReg, uint32* pCst) { if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == REGISTER)) { m_Shadow.Pull(); (pCst != NULL) ? (*pCst) = m_Shadow.Pull() : m_Shadow.Pull(); m_Shadow.Pull(); (pReg != NULL) ? (*pReg) = m_Shadow.Pull() : m_Shadow.Pull(); } else if((m_Shadow.GetAt(0) == REGISTER) && (m_Shadow.GetAt(2) == CONSTANT)) { m_Shadow.Pull(); (pReg != NULL) ? (*pReg) = m_Shadow.Pull() : m_Shadow.Pull(); m_Shadow.Pull(); (pCst != NULL) ? (*pCst) = m_Shadow.Pull() : m_Shadow.Pull(); } else { assert(0); } } bool CCodeGen::IsTopContRelPair64() { if( (m_Shadow.GetAt(0) == RELATIVE) && (m_Shadow.GetAt(2) == RELATIVE) && (m_Shadow.GetAt(4) == RELATIVE) && (m_Shadow.GetAt(6) == RELATIVE) ) { for(unsigned int i = 0; i < 2; i++) { uint32 nRelative[2]; nRelative[0] = m_Shadow.GetAt((i * 4) + 1); nRelative[1] = m_Shadow.GetAt((i * 4) + 3); if((nRelative[0] - nRelative[1]) != 4) { return false; } } return true; } else { return false; } } bool CCodeGen::IsTopContRelCstPair64() { if( (m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == CONSTANT) && (m_Shadow.GetAt(4) == RELATIVE) && (m_Shadow.GetAt(6) == RELATIVE) ) { for(unsigned int i = 1; i < 2; i++) { uint32 nRelative[2]; nRelative[0] = m_Shadow.GetAt((i * 4) + 1); nRelative[1] = m_Shadow.GetAt((i * 4) + 3); if((nRelative[0] - nRelative[1]) != 4) { return false; } } return true; } else { return false; } } void CCodeGen::StreamWriteByte(uint8 nByte) { if(m_stream == NULL) return; m_stream->Write(&nByte, 1); } void CCodeGen::StreamWriteAt(unsigned int position, uint8 value) { if(m_stream == NULL) return; uint64 currentPosition = m_stream->Tell(); m_stream->Seek(position, Framework::STREAM_SEEK_SET); m_stream->Write(&value, 1); m_stream->Seek(currentPosition, Framework::STREAM_SEEK_SET); } size_t CCodeGen::StreamTell() { if(m_stream == NULL) return 0; return static_cast(m_stream->Tell()); } void CCodeGen::EmitLoad(uint32 valueType, uint32 value, unsigned int registerId) { switch(valueType) { case CONSTANT: LoadConstantInRegister(registerId, value); break; case RELATIVE: LoadRelativeInRegister(registerId, value); break; case REGISTER: assert(!RegisterHasNextUse(value)); CopyRegister(registerId, value); FreeRegister(value); break; default: assert(0); break; } } void CCodeGen::EmitOp(const GenericOp& operation, uint32 valueType, uint32 value, unsigned int registerId) { switch(valueType) { case CONSTANT: ((m_Assembler).*(operation.addressConstantOp))(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[registerId]), value); break; case RELATIVE: ((m_Assembler).*(operation.registerAddressOp))(m_nRegisterLookupEx[registerId], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, value)); break; default: assert(0); break; } }