Author: aandrejevic Date: Wed Sep 4 01:11:12 2013 New Revision: 59981
URL: http://svn.reactos.org/svn/reactos?rev=59981&view=rev Log: [SOFT386] Implement helper functions for reading/writing operands of instructions that use the MOD-REG-R/M byte. Implement the MOD-REG-R/M ADD instruction for bytes.
Modified: branches/ntvdm/lib/soft386/common.c branches/ntvdm/lib/soft386/common.h branches/ntvdm/lib/soft386/opcodes.c branches/ntvdm/lib/soft386/opcodes.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] Wed Sep 4 01:11:12 2013 @@ -987,4 +987,304 @@ return TRUE; }
+inline +BOOLEAN +Soft386ReadModrmByteOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUCHAR RegValue, + PUCHAR RmValue) +{ + INT Segment = SOFT386_REG_DS; + + /* Get the register value */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte; + } + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +inline +BOOLEAN +Soft386ReadModrmWordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUSHORT RegValue, + PUSHORT RmValue) +{ + INT Segment = SOFT386_REG_DS; + + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord; + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +inline +BOOLEAN +Soft386ReadModrmDwordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PULONG RegValue, + PULONG RmValue) +{ + INT Segment = SOFT386_REG_DS; + + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].Long; + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +inline +BOOLEAN +Soft386WriteModrmByteOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + UCHAR Value) +{ + INT Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->Register & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->Register & 0x03].LowByte = Value; + } + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte = Value; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +inline +BOOLEAN +Soft386WriteModrmWordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + USHORT Value) +{ + INT Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].LowWord = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].LowWord = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +inline +BOOLEAN +Soft386WriteModrnDwordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + ULONG Value) +{ + INT Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].Long = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].Long = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + 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] Wed Sep 4 01:11:12 2013 @@ -149,6 +149,66 @@ PSOFT386_MOD_REG_RM ModRegRm );
+inline +BOOLEAN +Soft386ReadModrmByteOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUCHAR RegValue, + PUCHAR RmValue +); + +inline +BOOLEAN +Soft386ReadModrmWordOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUSHORT RegValue, + PUSHORT RmValue +); + +inline +BOOLEAN +Soft386ReadModrmDwordOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PULONG RegValue, + PULONG RmValue +); + +inline +BOOLEAN +Soft386WriteModrmByteOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + UCHAR Value +); + +inline +BOOLEAN +Soft386WriteModrmWordOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + USHORT Value +); + +inline +BOOLEAN +Soft386WriteModrnDwordOperands +( + PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + ULONG Value +); + #endif // _COMMON_H_
/* EOF */
Modified: branches/ntvdm/lib/soft386/opcodes.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/opcodes.c?rev=... ============================================================================== --- branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] Wed Sep 4 01:11:12 2013 @@ -24,9 +24,9 @@ SOFT386_OPCODE_HANDLER_PROC Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = { - NULL, // TODO: OPCODE 0x00 NOT SUPPORTED + Soft386OpcodeAddByteModrm, // TODO: OPCODE 0x00 NOT SUPPORTED NULL, // TODO: OPCODE 0x01 NOT SUPPORTED - NULL, // TODO: OPCODE 0x02 NOT SUPPORTED + Soft386OpcodeAddByteModrm, // TODO: OPCODE 0x02 NOT SUPPORTED NULL, // TODO: OPCODE 0x03 NOT SUPPORTED NULL, // TODO: OPCODE 0x04 NOT SUPPORTED NULL, // TODO: OPCODE 0x05 NOT SUPPORTED @@ -1258,3 +1258,64 @@
return TRUE; } + +BOOLEAN +FASTCALL +Soft386OpcodeAddByteModrm(PSOFT386_STATE State, UCHAR Opcode) +{ + UCHAR FirstValue, SecondValue, Result; + SOFT386_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x00); + + if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE) + { + /* The ADSIZE prefix toggles the size */ + AddressSize = !AddressSize; + } + else if (State->PrefixFlags + & ~(SOFT386_PREFIX_ADSIZE + | SOFT386_PREFIX_SEG + | SOFT386_PREFIX_LOCK)) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + /* Get the operands */ + if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Soft386ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmByteOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); +}
Modified: branches/ntvdm/lib/soft386/opcodes.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/opcodes.h?rev=... ============================================================================== --- branches/ntvdm/lib/soft386/opcodes.h [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/opcodes.h [iso-8859-1] Wed Sep 4 01:11:12 2013 @@ -16,6 +16,7 @@ #endif
#define SOFT386_NUM_OPCODE_HANDLERS 256 +#define SOFT386_OPCODE_WRITE_REG (1 << 1)
typedef BOOLEAN (FASTCALL *SOFT386_OPCODE_HANDLER_PROC)(PSOFT386_STATE, UCHAR);
@@ -207,4 +208,12 @@ UCHAR Opcode );
+BOOLEAN +FASTCALL +Soft386OpcodeAddByteModrm +( + PSOFT386_STATE State, + UCHAR Opcode +); + #endif // _OPCODES_H_