Added IDT emulation.

This commit is contained in:
Ivan Leo Puoti 2005-05-31 13:28:42 +00:00 committed by Alexandre Julliard
parent d9033a49da
commit f0c62a89ea
1 changed files with 82 additions and 35 deletions

View File

@ -68,6 +68,29 @@ inline static void *get_stack( CONTEXT86 *context )
return wine_ldt_get_ptr( context->SegSs, context->Esp );
}
#include "pshpack1.h"
struct idtr
{
WORD limit;
BYTE *base;
};
#include "poppack.h"
static LDT_ENTRY idt[256];
inline static struct idtr get_idtr(void)
{
struct idtr ret;
#if defined(__i386__) && defined(__GNUC__)
__asm__( "sidtl %0" : "=m" (ret) );
#else
ret.base = (BYTE *)idt;
ret.limit = sizeof(idt) - 1;
#endif
return ret;
}
/***********************************************************************
* INSTR_ReplaceSelector
*
@ -97,6 +120,46 @@ static BOOL INSTR_ReplaceSelector( CONTEXT86 *context, WORD *sel )
}
/* store an operand into a register */
static void store_reg( CONTEXT86 *context, BYTE regmodrm, const BYTE *addr, int long_op )
{
switch((regmodrm >> 3) & 7)
{
case 0:
if (long_op) context->Eax = *(DWORD *)addr;
else SET_LOWORD(context->Eax,*(WORD *)addr);
break;
case 1:
if (long_op) context->Ecx = *(DWORD *)addr;
else SET_LOWORD(context->Ecx,*(WORD *)addr);
break;
case 2:
if (long_op) context->Edx = *(DWORD *)addr;
else SET_LOWORD(context->Edx,*(WORD *)addr);
break;
case 3:
if (long_op) context->Ebx = *(DWORD *)addr;
else SET_LOWORD(context->Ebx,*(WORD *)addr);
break;
case 4:
if (long_op) context->Esp = *(DWORD *)addr;
else SET_LOWORD(context->Esp,*(WORD *)addr);
break;
case 5:
if (long_op) context->Ebp = *(DWORD *)addr;
else SET_LOWORD(context->Ebp,*(WORD *)addr);
break;
case 6:
if (long_op) context->Esi = *(DWORD *)addr;
else SET_LOWORD(context->Esi,*(WORD *)addr);
break;
case 7:
if (long_op) context->Edi = *(DWORD *)addr;
else SET_LOWORD(context->Edi,*(WORD *)addr);
break;
}
}
/***********************************************************************
* INSTR_GetOperandAddr
*
@ -278,41 +341,7 @@ static BOOL INSTR_EmulateLDS( CONTEXT86 *context, BYTE *instr, int long_op,
/* Now store the offset in the correct register */
switch((*regmodrm >> 3) & 7)
{
case 0:
if (long_op) context->Eax = *(DWORD *)addr;
else SET_LOWORD(context->Eax,*(WORD *)addr);
break;
case 1:
if (long_op) context->Ecx = *(DWORD *)addr;
else SET_LOWORD(context->Ecx,*(WORD *)addr);
break;
case 2:
if (long_op) context->Edx = *(DWORD *)addr;
else SET_LOWORD(context->Edx,*(WORD *)addr);
break;
case 3:
if (long_op) context->Ebx = *(DWORD *)addr;
else SET_LOWORD(context->Ebx,*(WORD *)addr);
break;
case 4:
if (long_op) context->Esp = *(DWORD *)addr;
else SET_LOWORD(context->Esp,*(WORD *)addr);
break;
case 5:
if (long_op) context->Ebp = *(DWORD *)addr;
else SET_LOWORD(context->Ebp,*(WORD *)addr);
break;
case 6:
if (long_op) context->Esi = *(DWORD *)addr;
else SET_LOWORD(context->Esi,*(WORD *)addr);
break;
case 7:
if (long_op) context->Edi = *(DWORD *)addr;
else SET_LOWORD(context->Edi,*(WORD *)addr);
break;
}
store_reg( context, *regmodrm, addr, long_op );
/* Store the correct segment in the segment register */
@ -676,6 +705,24 @@ DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context )
}
return ExceptionContinueExecution;
case 0x8b: /* mov Ev, Gv */
{
BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr,
segprefix, &len);
struct idtr idtr = get_idtr();
unsigned int offset = addr - idtr.base;
if (offset <= idtr.limit + 1 - (long_op ? 4 : 2))
{
idt[1].LimitLow = 0x100; /* FIXME */
idt[3].LimitLow = 0x500; /* FIXME */
store_reg( context, instr[1], (BYTE *)&idt + offset, long_op );
context->Eip += prefixlen + len + 1;
return ExceptionContinueExecution;
}
}
break; /* Unable to emulate it */
case 0x8e: /* mov XX,segment_reg */
{
WORD seg;