Sunday, August 1, 2010

Just In Time Compiler for Managed Platform- Part 4A: Conditional Branch Correction

The Jxx instructions I used for branching was not working right- It treated values unsigned. The "IA-32 Intel Architecture Software Developers Manual- Vol 2" describes this (page- 3-355): The terms "less" and "greater" are used for comparisons of signed integers and the terms "above" and "below" are used for unsigned integers. So, for signed comparison, we use JL, JG, JLE and JGE instead of JB, GA, JBE and JAE.

With that change all branching instruction seems working now. We need two helper method for all of them.

First one is comparison with zero:

void IfXX(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap, u1 XX)
{
u1 c[] = {
//pContext->stackTop--;
0x8B,0x45,0x08, // mov eax,dword ptr [pContext]
0x8B,0x48,0x04, // mov ecx,dword ptr [eax+4]
0x83,0xE9,0x01, // sub ecx,1
0x8B,0x55,0x08, // mov edx,dword ptr [pContext]
0x89,0x4A,0x04, // mov dword ptr [edx+4],ecx

//if(pContext->stack[pContext->stackTop].intValue [XXoperator] 0)
0x8B, 0x45, 0x08, // mov eax,dword ptr [pContext]
0x8B, 0x48, 0x04, // mov ecx,dword ptr [eax+4]
0x8B, 0x55, 0x08, // mov edx,dword ptr [pContext]
0x8B, 0x02, // mov eax,dword ptr [edx]
0x83, 0x3C, 0xC8, 0x00, // cmp dword ptr [eax+ecx*8],0
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, // JXX
};

memcpy(&code[ip], c, sizeof(c));
ip+=sizeof(c);

code[ip-5] = XX;
CreateJmpLink(&code[ip-5], targetpc, pJmpTargetMap);
}

void Ifle(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JLE);
}

void Ifeq(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JE);
}

void Ifne(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JNE);
}

void Iflt(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JL);
}

void Ifge(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JGE);
}

void Ifgt(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfXX(code, ip, targetpc, pJmpTargetMap, JG);
}



Second one is comparison of any two numbers:

void IfICmpXX(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap, u1 XX)
{
u1 c[]={
//pContext->stackTop -= 2;
0x8B, 0x45, 0x08, // mov eax,dword ptr [pContext]
0x8B, 0x48, 0x04, // mov ecx,dword ptr [eax+4]
0x83, 0xE9, 0x02, // sub ecx,2
0x8B, 0x55, 0x08, // mov edx,dword ptr [pContext]
0x89, 0x4A, 0x04, // mov dword ptr [edx+4],ecx

//if(!(pContext->stack[pContext->stackTop -2+2].intValue [XXOperator] pContext->stack[pContext->stackTop-1+2].intValue))
0x8B, 0x45, 0x08, // mov eax,dword ptr [pContext]
0x8B, 0x48, 0x04, // mov ecx,dword ptr [eax+4]
0x8B, 0x55, 0x08, // mov edx,dword ptr [pContext]
0x8B, 0x02, // mov eax,dword ptr [edx]
0x8B, 0x55, 0x08, // mov edx,dword ptr [pContext]
0x8B, 0x52, 0x04, // mov edx,dword ptr [edx+4]
0x8B, 0x75, 0x08, // mov esi,dword ptr [pContext]
0x8B, 0x36, // mov esi,dword ptr [esi]
0x8B, 0x04, 0xC8, // mov eax,dword ptr [eax+ecx*8]
0x3B, 0x44, 0xD6, 0x08, // cmp eax,dword ptr [esi+edx*8+8]
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, // JXX
};

memcpy(&code[ip], c, sizeof(c));
ip+=sizeof(c);

code[ip-5] = XX;

CreateJmpLink(&code[ip-5], targetpc, pJmpTargetMap);
}

void IfIcmple(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JLE);
}

void IfIcmpne(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JNE);
}

void IfIcmpge(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JGE);
}

void IfIcmplt(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JL);
}

void IfIcmpgt(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JG);
}

void IfIcmpeq(u1* code, int& ip, int targetpc, CMapPtrToPtr *pJmpTargetMap)
{
IfICmpXX(code, ip, targetpc, pJmpTargetMap, JE);
}


Thats it. We have all the branching instructions working correctly now.