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=…
==============================================================================
--- 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=…
==============================================================================
--- 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_