#include #include #include #include #include "PtrMacro.h" #include "CacheBlock.h" #include "MIPS.h" #ifdef AMD64 #include extern "C" RET_CODE _CCacheBlock_Execute(void*, void*); #endif #define GROWSIZE (0x40000) CCacheBlock::CCacheBlock(uint32 nStart, uint32 nEnd) { m_nStart = nStart; m_nEnd = nEnd; m_pData = (uint8*)malloc(0); m_nSize = 0; m_nPtr = 0; m_pReloc = (uint32*)malloc((nEnd - nStart)); m_nValid = false; m_nCheckDelayedJump = false; } CCacheBlock::~CCacheBlock() { DELETEPTR(m_pData); DELETEPTR(m_pReloc); } RET_CODE CCacheBlock::Execute(CMIPS* pCtx) { void* pEntry; RET_CODE nRet; uint32 nAddress; if(!m_nValid) { Compile(pCtx); #ifdef AMD64 DWORD nOldProtect; VirtualProtect(m_pData, m_nSize, PAGE_EXECUTE_READWRITE, &nOldProtect); #endif } nAddress = pCtx->m_pAddrTranslator(pCtx, 0x00000000, pCtx->m_State.nPC); pEntry = (uint8*)m_pData + m_pReloc[(nAddress - m_nStart) / 4]; #ifdef AMD64 nRet = _CCacheBlock_Execute(pEntry, pCtx); #else __asm { push ebx push esi push edi push ebp mov eax, [pEntry]; mov ebp, [pCtx]; call eax pop ebp pop edi pop esi pop ebx mov [nRet], eax; } #endif return nRet; } void CCacheBlock::Compile(CMIPS* pCtx) { uint32 i; bool nJump; m_nCheckDelayedJump = pCtx->IsBranch(m_nStart - 4); //Check if there's a jump instruction before this one for(i = m_nStart; i < m_nEnd; i += 4) { m_pReloc[(i - m_nStart) / 4] = m_nPtr; m_nProgramCounterChanged = false; nJump = m_nCheckDelayedJump; InsertProlog(pCtx); pCtx->m_pArch->CompileInstruction(i, this, pCtx, true); InsertEpilog(pCtx, nJump); } //Check jump out of the block Ret(RET_CODE_INTERBLOCKJUMP); m_nValid = true; printf("CacheBlock: Compiled block [0x%0.8X, 0x%0.8X]. %i byte(s) allocated.\r\n", m_nStart, m_nEnd, m_nSize); } void CCacheBlock::InsertProlog(CMIPS* pCtx) { //add [pCtx->m_State.nPC], 4 StreamWrite(4, 0x83, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nPC), 4); } void CCacheBlock::InsertEpilog(CMIPS* pCtx, bool nDelayJump) { //Check delay slot (we truly need to do something better about this...) if(nDelayJump) { m_nCheckDelayedJump = false; //mov eax, dword ptr[nDelayedJumpAddr] StreamWrite(3, 0x8B, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nDelayedJumpAddr)); //cmp eax, 1 StreamWrite(1, 0x3D); StreamWriteWord(MIPS_INVALID_PC); //je +0B StreamWrite(2, 0x74, 0x0B); //mov dword ptr[nPC], eax StreamWrite(3, 0x89, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nPC)); //mov eax, 1 StreamWrite(1, 0xB8); StreamWriteWord(MIPS_INVALID_PC); //mov dword ptr[nDelayedJumpAddr], eax StreamWrite(3, 0x89, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nDelayedJumpAddr)); //PC Changed SetProgramCounterChanged(); } if(pCtx->m_pTickFunction != NULL) { //Call the tick function (push a different value than 1 if there's a dead loop in there) #ifdef AMD64 //mov ecx, 1 StreamWrite(1, 0xB9); StreamWriteWord(1); //sub esp, 0x08 StreamWrite(3, 0x83, 0xC0 | (0x05 << 3) | (0x04), 0x08); #else //push 1 StreamWrite(2, 0x6A, 0x01); #endif //call [TickFunction] StreamWrite(2, 0xFF, (0x02 << 6) | (0x02 << 3) | (0x05)); StreamWriteWord(offsetof(CMIPS, m_pTickFunction)); #ifdef AMD64 //add esp, 0x08 StreamWrite(3, 0x83, 0xC0 | (0x00 << 3) | (0x04), 0x08); #else //add esp, 4 StreamWrite(3, 0x83, 0xC4, 0x04); #endif //test eax, eax StreamWrite(2, 0x85, 0xC0); //je +0x06 StreamWrite(2, 0x74, 0x06); //mov eax, RET_CODE_BREAKPOINT StreamWrite(1, 0xB8); StreamWriteWord(RET_CODE_BREAKPOINT); //ret StreamWrite(1, 0xC3); } ////////////////////////////// //Decrement quota //sub [Quota], 1 StreamWrite(2, 0x83, (0x02 << 6) | (0x05 << 3) | (0x05)); StreamWriteWord(offsetof(CMIPS, m_nQuota)); StreamWriteByte(1); //jne $notdone StreamWriteByte(0x75); StreamWriteByte(0x06); //mov eax, nCode StreamWriteByte(0xB8); StreamWriteWord(RET_CODE_QUOTADONE); //ret (stack unwinding?) StreamWriteByte(0xC3); //////////////////////////////////////////////////// //Take the jump if(m_nProgramCounterChanged) { SynchornizePC(pCtx); } } void CCacheBlock::SynchornizePC(CMIPS* pCtx) { //mov eax, dword ptr[nPC] StreamWrite(3, 0x8B, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nPC)); //sub eax, m_nStart StreamWrite(1, 0x2D); StreamWriteWord(m_nStart); //jns +0x06 StreamWrite(2, 0x79, 0x06); //mov eax, RET_CODE_INTERBLOCKJUMP StreamWrite(1, 0xB8); StreamWriteWord(RET_CODE_INTERBLOCKJUMP); //ret StreamWrite(1, 0xC3); //cmp eax, m_nSize StreamWrite(1, 0x3D); StreamWriteWord(m_nEnd - m_nStart); //jb +0x06 StreamWrite(2, 0x72, 0x06); //mov eax, RET_CODE_INTERBLOCKJUMP StreamWrite(1, 0xB8); StreamWriteWord(RET_CODE_INTERBLOCKJUMP); //ret StreamWrite(1, 0xC3); //mov ebx, m_nReloc (64-BITS : Potentially dangerous!) StreamWrite(1, 0xBB); StreamWriteWord((uint32)((uint8*)(m_pReloc) - (uint8*)0)); //mov eax, [ebx + eax] StreamWrite(3, 0x8B, 0x00 | (0x00 << 3) | (0x04), 0x03); //add eax, m_pData (64-BITS : Potentially dangerous!) StreamWrite(1, 0x05); StreamWriteWord((uint32)((uint8*)(m_pData) - (uint8*)0)); //jmp eax StreamWrite(2, 0xFF, 0xE0); } /////////////////////////////////////////////////////////// //Stream Fonction Implementation /////////////////////////////////////////////////////////// void CCacheBlock::StreamWriteByte(uint8 nByte) { if(m_nPtr == m_nSize) { m_nSize += GROWSIZE; m_pData = (uint8*)realloc(m_pData, m_nSize); } m_pData[m_nPtr] = nByte; m_nPtr++; } void CCacheBlock::StreamWriteWord(uint32 nWord) { unsigned int i; for(i = 0; i < 4; i++) { StreamWriteByte(((uint8*)&nWord)[i]); } } void CCacheBlock::StreamWrite(unsigned int nCount, ...) { va_list args; uint8 nValue; unsigned int i; va_start(args, nCount); for(i = 0; i < nCount; i++) { nValue = va_arg(args, uint8); StreamWriteByte(nValue); } va_end(args); } unsigned int CCacheBlock::StreamGetSize() { return m_nPtr; } void CCacheBlock::StreamWriteAt(unsigned int nPosition, uint8 nValue) { m_pData[nPosition] = nValue; } /////////////////////////////////////////////////////////// //Intermediate Language Implementation /////////////////////////////////////////////////////////// void CCacheBlock::PushAddr(void* pAddr) { //push [pAddr] StreamWriteByte(0xFF); StreamWriteByte(0x35); StreamWriteWord((uint32)((uint8*)pAddr - (uint8*)0)); } void CCacheBlock::PullAddr(void* pAddr) { //pop [pAddr] StreamWriteByte(0x8F); StreamWriteByte(0x05); StreamWriteWord((uint32)((uint8*)pAddr - (uint8*)0)); } void CCacheBlock::PushImm(uint32 nValue) { //push nValue StreamWriteByte(0x68); StreamWriteWord(nValue); } void CCacheBlock::PushRef(void* pRef) { PushImm((uint32)((uint8*)pRef - (uint8*)0)); } void CCacheBlock::SeX8() { //pop eax StreamWriteByte(0x58); //movsx eax, al StreamWriteByte(0x0F); StreamWriteByte(0xBE); StreamWriteByte(0xC0); //push eax StreamWriteByte(0x50); } void CCacheBlock::SeX16() { //pop eax StreamWriteByte(0x58); //cwde StreamWriteByte(0x98); //push eax StreamWriteByte(0x50); } void CCacheBlock::SeX32() { //pop eax StreamWriteByte(0x58); //cdq StreamWriteByte(0x99); //push eax StreamWriteByte(0x50); //push edx StreamWriteByte(0x52); } void CCacheBlock::PullTop() { Free(1); } void CCacheBlock::Free(unsigned int nAmount) { nAmount *= 4; assert(nAmount < 128); //add esp, 4 StreamWriteByte(0x83); StreamWriteByte(0xC4); StreamWriteByte((uint8)nAmount); } void CCacheBlock::PushTop() { //push [esp] StreamWriteByte(0xFF); StreamWriteByte(0x34); StreamWriteByte(0x24); } void CCacheBlock::PushValueAt(unsigned int nAddress) { nAddress *= 4; assert(nAddress < 128); //push [esp + nAddress]; StreamWriteByte(0xFF); StreamWriteByte(0x74); StreamWriteByte(0x24); StreamWriteByte((uint8)nAddress); } void CCacheBlock::Lookup(uint32* pTable) { //pop eax StreamWriteByte(0x58); //mov ebx, $pTable StreamWriteByte(0xBB); StreamWriteWord((uint32)((uint8*)pTable - (uint8*)0)); //mov eax, [eax * 4 + ebx] StreamWriteByte(0x8B); StreamWriteByte(0x04); StreamWriteByte(0x83); //push eax StreamWriteByte(0x50); } void CCacheBlock::Exchange(unsigned int nA1, unsigned int nA2) { nA1 *= 4; nA2 *= 4; assert(nA1 < 128); assert(nA2 < 128); //mov eax, [esp + nA1] StreamWriteByte(0x8B); StreamWriteByte(0x44); StreamWriteByte(0x24); StreamWriteByte((uint8)nA1); //xchg eax, [esp + nA2] StreamWriteByte(0x87); StreamWriteByte(0x44); StreamWriteByte(0x24); StreamWriteByte((uint8)nA2); //mov [esp + nA1], eax StreamWriteByte(0x89); StreamWriteByte(0x44); StreamWriteByte(0x24); StreamWriteByte((uint8)nA1); } void CCacheBlock::Swap() { Exchange(0, 1); } void CCacheBlock::And() { //pop eax StreamWriteByte(0x58); //and [esp], eax StreamWriteByte(0x21); StreamWriteByte(0x04); StreamWriteByte(0x24); } void CCacheBlock::AndImm(uint32 nValue) { //and [esp], nValue StreamWriteByte(0x81); StreamWriteByte(0x24); StreamWriteByte(0x24); StreamWriteWord(nValue); } void CCacheBlock::Add() { //pop eax StreamWriteByte(0x58); //add [esp], eax StreamWriteByte(0x01); StreamWriteByte(0x04); StreamWriteByte(0x24); } void CCacheBlock::AddC() { //pop eax StreamWriteByte(0x58); //pop ebx StreamWriteByte(0x5B); //push 0 StreamWriteByte(0x6A); StreamWriteByte(0x00); //add ebx, eax StreamWriteByte(0x03); StreamWriteByte(0xD8); //adc [esp], 0 StreamWriteByte(0x80); StreamWriteByte(0x14); StreamWriteByte(0x24); StreamWriteByte(0x00); //push ebx StreamWriteByte(0x53); } void CCacheBlock::AddImm(uint32 nValue) { if(nValue == 0) return; //add [esp], nValue StreamWriteByte(0x81); StreamWriteByte(0x04); StreamWriteByte(0x24); StreamWriteWord(nValue); } void CCacheBlock::Sub() { //pop eax StreamWriteByte(0x58); //sub [esp], eax StreamWriteByte(0x29); StreamWriteByte(0x04); StreamWriteByte(0x24); } void CCacheBlock::SubImm(uint32 nValue) { //sub [esp], nValue StreamWriteByte(0x81); StreamWriteByte(0x2C); StreamWriteByte(0x24); StreamWriteWord(nValue); } void CCacheBlock::SubC() { //pop eax StreamWriteByte(0x58); //pop ebx StreamWriteByte(0x5B); //push 0 StreamWriteByte(0x6A); StreamWriteByte(0x00); //sub ebx, eax StreamWriteByte(0x2B); StreamWriteByte(0xD8); //adc [esp], 0 StreamWriteByte(0x80); StreamWriteByte(0x14); StreamWriteByte(0x24); StreamWriteByte(0x00); //push ebx StreamWriteByte(0x53); } void CCacheBlock::PushConditionBit(JCC_CONDITION nCond) { switch(nCond) { case JCC_CONDITION_EQ: //je StreamWriteByte(0x74); break; case JCC_CONDITION_NE: //jne StreamWriteByte(0x75); break; case JCC_CONDITION_BL: //jb StreamWriteByte(0x72); break; case JCC_CONDITION_BE: //jbe StreamWriteByte(0x76); break; case JCC_CONDITION_LT: //jl StreamWriteByte(0x7C); break; case JCC_CONDITION_LE: //jle StreamWriteByte(0x7E); break; default: assert(0); break; } //$04 (label for previous jump) StreamWriteByte(0x04); //push 0 StreamWriteByte(0x6A); StreamWriteByte(0x00); //jmp $02 StreamWriteByte(0xEB); StreamWriteByte(0x02); //push 1 StreamWriteByte(0x6A); StreamWriteByte(0x01); } void CCacheBlock::Cmp(JCC_CONDITION nCond) { //pop eax StreamWriteByte(0x58); //cmp [esp], eax StreamWriteByte(0x39); StreamWriteByte(0x04); StreamWriteByte(0x24); //pop eax StreamWriteByte(0x58); PushConditionBit(nCond); } void CCacheBlock::Call(void* pFunc, unsigned int nParams, bool nSaveRes) { /* //call [pFunc] StreamWrite(2, 0xFF, 0x00 | (0x02 << 3) | (0x05)); StreamWriteWord((uint32)((uint8*)(pFunc) - (uint8*)0)); */ //mov eax, pFunc StreamWriteByte(0xB8); StreamWriteWord((uint32)((uint8*)pFunc - (uint8*)0)); //call eax StreamWriteByte(0xFF); StreamWriteByte(0xD0); if(nParams != 0) { //add esp, [nParams * 4]; StreamWriteByte(0x83); StreamWriteByte(0xC4); StreamWriteByte(nParams * 4); } if(nSaveRes) { //push eax StreamWriteByte(0x50); } } void CCacheBlock::BeginJcc(bool nCond) { //pop eax StreamWriteByte(0x58); //test eax, eax StreamWriteByte(0x85); StreamWriteByte(0xC0); if(!nCond) { //jne $l StreamWriteByte(0x75); } else { //je $l StreamWriteByte(0x74); } m_nJccPos = m_nPtr; StreamWriteByte(0x00); } void CCacheBlock::EndJcc() { uint8 nDist; nDist = (uint8)(m_nPtr - (m_nJccPos + 1)); m_pData[m_nJccPos] = nDist; } void CCacheBlock::Ret(RET_CODE nCode) { //mov eax, nCode StreamWriteByte(0xB8); StreamWriteWord(nCode); //ret (stack unwinding?) StreamWriteByte(0xC3); } void CCacheBlock::Mult() { //pop eax StreamWriteByte(0x58); //pop ebx StreamWriteByte(0x5B); //mul ebx StreamWriteByte(0xF7); StreamWriteByte(0xE3); //push edx StreamWriteByte(0x52); //push eax StreamWriteByte(0x50); } void CCacheBlock::MultS() { //pop eax StreamWriteByte(0x58); //pop ebx StreamWriteByte(0x5B); //imul ebx StreamWriteByte(0xF7); StreamWriteByte(0xEB); //push edx StreamWriteByte(0x52); //push eax StreamWriteByte(0x50); } void CCacheBlock::Div() { //pop ebx StreamWriteByte(0x5B); //pop eax StreamWriteByte(0x58); //xor edx, edx StreamWriteByte(0x33); StreamWriteByte(0xD2); //div ebx StreamWriteByte(0xF7); StreamWriteByte(0xF3); //push edx StreamWriteByte(0x52); //push eax StreamWriteByte(0x50); } void CCacheBlock::DivS() { //pop ebx StreamWriteByte(0x5B); //pop eax StreamWriteByte(0x58); //cdq StreamWriteByte(0x99); //idiv ebx StreamWriteByte(0xF7); StreamWriteByte(0xFB); //push edx StreamWriteByte(0x52); //push eax StreamWriteByte(0x50); } void CCacheBlock::Or() { //pop eax StreamWriteByte(0x58); //or [esp], eax StreamWriteByte(0x09); StreamWriteByte(0x04); StreamWriteByte(0x24); } void CCacheBlock::OrImm(uint32 nValue) { //or [esp], nValue StreamWriteByte(0x81); StreamWriteByte(0x0C); StreamWriteByte(0x24); StreamWriteWord(nValue); } void CCacheBlock::Xor() { //pop eax StreamWriteByte(0x58); //xor [esp], eax StreamWriteByte(0x31); StreamWriteByte(0x04); StreamWriteByte(0x24); } void CCacheBlock::Not() { //not [esp] StreamWriteByte(0xF7); StreamWriteByte(0x14); StreamWriteByte(0x24); } void CCacheBlock::Sll() { //pop ecx StreamWriteByte(0x59); //shl [esp], cl StreamWriteByte(0xD3); StreamWriteByte(0x24); StreamWriteByte(0x24); } void CCacheBlock::SllImm(uint8 nAmount) { //shl [esp], nAmount StreamWriteByte(0xC1); StreamWriteByte(0x24); StreamWriteByte(0x24); StreamWriteByte(nAmount); } void CCacheBlock::Sll64() { //pop ecx StreamWriteByte(0x59); //pop edx StreamWriteByte(0x5A); //pop eax StreamWriteByte(0x58); //test cl, cl StreamWriteByte(0x84); StreamWriteByte(0xC9); //je $done StreamWriteByte(0x74); StreamWriteByte(0x20); //cmp cl, 0x40 StreamWriteByte(0x80); StreamWriteByte(0xF9); StreamWriteByte(0x40); //jae $zero StreamWriteByte(0x73); StreamWriteByte(0x17); //cmp cl, 0x20 StreamWriteByte(0x80); StreamWriteByte(0xF9); StreamWriteByte(0x20); //jae $more32 StreamWriteByte(0x73); StreamWriteByte(0x07); //shld edx, eax, cl StreamWriteByte(0x0F); StreamWriteByte(0xA5); StreamWriteByte(0xC2); //shl eax, cl StreamWriteByte(0xD3); StreamWriteByte(0xE0); //jmp $done StreamWriteByte(0xEB); StreamWriteByte(0x0F); //$more32 //mov edx, eax StreamWriteByte(0x8B); StreamWriteByte(0xD0); //xor eax, eax StreamWriteByte(0x33); StreamWriteByte(0xC0); //and cl, 0x1F StreamWriteByte(0x80); StreamWriteByte(0xE1); StreamWriteByte(0x1F); //shl edx, cl StreamWriteByte(0xD3); StreamWriteByte(0xE2); //jmp $done StreamWriteByte(0xEB); StreamWriteByte(0x04); //$zero //xor eax, eax StreamWriteByte(0x33); StreamWriteByte(0xC0); //xor edx, edx StreamWriteByte(0x33); StreamWriteByte(0xD2); //$done //push eax StreamWriteByte(0x50); //push edx StreamWriteByte(0x52); } void CCacheBlock::Srl() { //pop ecx StreamWriteByte(0x59); //shr [esp], cl StreamWriteByte(0xD3); StreamWriteByte(0x2C); StreamWriteByte(0x24); } void CCacheBlock::SrlImm(uint8 nAmount) { //shr [esp], nAmount StreamWriteByte(0xC1); StreamWriteByte(0x2C); StreamWriteByte(0x24); StreamWriteByte(nAmount); } void CCacheBlock::Srl64() { //pop ecx StreamWriteByte(0x59); //pop edx StreamWriteByte(0x5A); //pop eax StreamWriteByte(0x58); //test cl, cl StreamWriteByte(0x84); StreamWriteByte(0xC9); //je $done StreamWriteByte(0x74); StreamWriteByte(0x20); //cmp cl, 0x40 StreamWriteByte(0x80); StreamWriteByte(0xF9); StreamWriteByte(0x40); //jae $zero StreamWriteByte(0x73); StreamWriteByte(0x17); //cmp cl, 0x20 StreamWriteByte(0x80); StreamWriteByte(0xF9); StreamWriteByte(0x20); //jae $more32 StreamWriteByte(0x73); StreamWriteByte(0x07); //shrd eax, edx, cl StreamWriteByte(0x0F); StreamWriteByte(0xAD); StreamWriteByte(0xD0); //shr edx, cl StreamWriteByte(0xD3); StreamWriteByte(0xEA); //jmp $done StreamWriteByte(0xEB); StreamWriteByte(0x0F); //$more32 //mov eax, edx StreamWriteByte(0x8B); StreamWriteByte(0xC2); //xor edx, edx StreamWriteByte(0x33); StreamWriteByte(0xD2); //and cl, 0x1F StreamWriteByte(0x80); StreamWriteByte(0xE1); StreamWriteByte(0x1F); //shr eax, cl StreamWriteByte(0xD3); StreamWriteByte(0xE8); //jmp $done StreamWriteByte(0xEB); StreamWriteByte(0x04); //$zero //xor eax, eax StreamWriteByte(0x33); StreamWriteByte(0xC0); //xor edx, edx StreamWriteByte(0x33); StreamWriteByte(0xD2); //$done //push eax StreamWriteByte(0x50); //push edx StreamWriteByte(0x52); } void CCacheBlock::Sra() { //pop ecx StreamWriteByte(0x59); //sar [esp], cl StreamWriteByte(0xD3); StreamWriteByte(0x3C); StreamWriteByte(0x24); } void CCacheBlock::SraImm(uint8 nAmount) { //sar [esp], nAmount StreamWriteByte(0xC1); StreamWriteByte(0x3C); StreamWriteByte(0x24); StreamWriteByte(nAmount); } void CCacheBlock::Sra64() { //pop ecx StreamWriteByte(0x59); //pop edx StreamWriteByte(0x5A); //pop eax StreamWriteByte(0x58); //cmp cl, 0x40 StreamWrite(3, 0x80, 0xF9, 0x40); //jae $more64 StreamWrite(2, 0x73, 0x18); //cmp cl, 0x40 StreamWrite(3, 0x80, 0xF9, 0x20); //jae $more32 StreamWrite(2, 0x73, 0x07); //shrd eax, edx, cl StreamWrite(3, 0x0F, 0xAD, 0xD0); //sar edx, cl StreamWrite(2, 0xD3, 0xFA); //jmp $done StreamWrite(2, 0xEB, 0x11); //more32: //mov eax, edx StreamWrite(2, 0x8B, 0xC2); //sar edx, 0x1F StreamWrite(3, 0xC1, 0xFA, 0x1F); //and cl, 0x1F StreamWrite(3, 0x80, 0xE1, 0x1F); //sar eax, cl StreamWrite(2, 0xD3, 0xF8); //jmp $done StreamWrite(2, 0xEB, 0x05); //more64: //sar edx, 0x1F StreamWrite(3, 0xC1, 0xFA, 0x1F); //mov eax, edx StreamWrite(2, 0x8B, 0xC2); /* __asm { cmp cl,64 jae more64 cmp cl, 32 jae more32 shrd eax,edx,cl sar edx,cl jmp done more32: mov eax,edx sar edx,31 and cl,31 sar eax,cl jmp done more64: sar edx,31 mov eax,edx done: } */ //push eax StreamWriteByte(0x50); //push edx StreamWriteByte(0x52); } void CCacheBlock::SetDelayedJumpCheck() { m_nCheckDelayedJump = true; } void CCacheBlock::SetProgramCounterChanged() { m_nProgramCounterChanged = true; } /////////////////////////////////////////////////////////// //Proxies Implementations /////////////////////////////////////////////////////////// uint32 CCacheBlock::GetByteProxy(CMIPS* pCtx, uint32 nAddress) { return (uint32)pCtx->m_pMemoryMap->GetByte(nAddress); } uint32 CCacheBlock::GetHalfProxy(CMIPS* pCtx, uint32 nAddress) { return (uint32)pCtx->m_pMemoryMap->GetHalf(nAddress); } uint32 CCacheBlock::GetWordProxy(CMIPS* pCtx, uint32 nAddress) { return pCtx->m_pMemoryMap->GetWord(nAddress); } void CCacheBlock::SetByteProxy(CMIPS* pCtx, uint32 nValue, uint32 nAddress) { pCtx->m_pMemoryMap->SetByte(nAddress, (uint8)(nValue & 0xFF)); } void CCacheBlock::SetHalfProxy(CMIPS* pCtx, uint32 nValue, uint32 nAddress) { pCtx->m_pMemoryMap->SetHalf(nAddress, (uint16)(nValue & 0xFFFF)); } void CCacheBlock::SetWordProxy(CMIPS* pCtx, uint32 nValue, uint32 nAddress) { pCtx->m_pMemoryMap->SetWord(nAddress, nValue); }