Author: aandrejevic Date: Sun Sep 1 23:49:57 2013 New Revision: 59959
URL: http://svn.reactos.org/svn/reactos?rev=59959&view=rev Log: [SOFT386] Implement "MOD-REG-R/M" byte decoding.
Modified: branches/ntvdm/lib/soft386/common.c branches/ntvdm/lib/soft386/common.h
Modified: branches/ntvdm/lib/soft386/common.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.c?rev=5... ============================================================================== --- branches/ntvdm/lib/soft386/common.c [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/common.c [iso-8859-1] Sun Sep 1 23:49:57 2013 @@ -764,4 +764,227 @@ return !(Number & 1); }
+inline +BOOLEAN +Soft386ParseModRegRm(PSOFT386_STATE State, + BOOLEAN AddressSize, + PSOFT386_MOD_REG_RM ModRegRm) +{ + UCHAR ModRmByte, Mode, RegMem; + + /* Fetch the MOD REG R/M byte */ + if (!Soft386FetchByte(State, &ModRmByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the mode and R/M */ + Mode = ModRmByte >> 6; + RegMem = ModRmByte & 0x07; + + /* Set the register operand */ + ModRegRm->Register = (ModRmByte >> 3) & 0x07; + + /* Check the mode */ + if ((ModRmByte >> 6) == 3) + { + /* The second operand is also a register */ + ModRegRm->Memory = FALSE; + ModRegRm->SecondRegister = RegMem; + + /* Done parsing */ + return TRUE; + } + + /* The second operand is memory */ + ModRegRm->Memory = TRUE; + + if (AddressSize) + { + if (RegMem == SOFT386_REG_ESP) + { + UCHAR SibByte; + ULONG Scale, Index, Base; + + /* Fetch the SIB byte */ + if (!Soft386FetchByte(State, &SibByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the scale, index and base */ + Scale = 1 << (SibByte >> 6); + Index = (SibByte >> 3) & 0x07; + if (Index != SOFT386_REG_ESP) Index = State->GeneralRegs[Index].Long; + else Index = 0; + Base = State->GeneralRegs[SibByte & 0x07].Long; + + /* Calculate the address */ + ModRegRm->MemoryAddress = Base + Index * Scale; + } + else if (RegMem == SOFT386_REG_EBP) + { + if (Mode) ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].Long; + else ModRegRm->MemoryAddress = 0; + } + else + { + /* Get the base from the register */ + ModRegRm->MemoryAddress = State->GeneralRegs[RegMem].Long; + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == SOFT386_REG_EBP) && Mode) + { + /* Add a SS: prefix */ + State->PrefixFlags |= SOFT386_PREFIX_SEG; + State->SegmentOverride = SOFT386_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == SOFT386_REG_EBP))) + { + LONG Offset; + + /* Fetch the dword */ + if (!Soft386FetchDword(State, (PULONG)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += Offset; + } + } + else + { + /* Check the operand */ + switch (RegMem) + { + case 0: + case 2: + { + /* (SS:)[BX + SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord + + State->GeneralRegs[SOFT386_REG_ESI].LowWord; + + break; + } + + case 1: + case 3: + { + /* (SS:)[BX + DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord + + State->GeneralRegs[SOFT386_REG_EDI].LowWord; + + break; + } + + case 4: + { + /* [SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_ESI].LowWord; + + break; + } + + case 5: + { + /* [DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EDI].LowWord; + + break; + } + + case 6: + { + if (Mode) + { + /* [BP] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].LowWord; + } + else + { + /* [constant] (added later) */ + ModRegRm->MemoryAddress = 0; + } + + break; + } + + case 7: + { + /* [BX] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord; + + break; + } + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == 2) || (RegMem == 3) || ((RegMem == 6) && Mode)) + { + /* Add a SS: prefix */ + State->PrefixFlags |= SOFT386_PREFIX_SEG; + State->SegmentOverride = SOFT386_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6))) + { + SHORT Offset; + + /* Fetch the word */ + if (!Soft386FetchWord(State, (PUSHORT)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + } + + return TRUE; +} + /* EOF */
Modified: branches/ntvdm/lib/soft386/common.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.h?rev=5... ============================================================================== --- branches/ntvdm/lib/soft386/common.h [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/common.h [iso-8859-1] Sun Sep 1 23:49:57 2013 @@ -20,6 +20,17 @@ #define SIGN_FLAG_LONG 0x80000000 #define GET_SEGMENT_RPL(s) ((s) & 3) #define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8) + +typedef struct _SOFT386_MOD_REG_RM +{ + INT Register; + BOOLEAN Memory; + union + { + INT SecondRegister; + ULONG MemoryAddress; + }; +} SOFT386_MOD_REG_RM, *PSOFT386_MOD_REG_RM;
/* FUNCTIONS ******************************************************************/
@@ -129,6 +140,15 @@ UCHAR Number );
+inline +BOOLEAN +Soft386ParseModRegRm +( + PSOFT386_STATE State, + BOOLEAN AddressSize, + PSOFT386_MOD_REG_RM ModRegRm +); + #endif // _COMMON_H_
/* EOF */