Monday, August 2, 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.

No comments:

Post a Comment