mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 12:29:56 +00:00
[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. svn path=/branches/ntvdm/; revision=59981
This commit is contained in:
parent
6f2f5335c2
commit
5f874178e7
4 changed files with 432 additions and 2 deletions
|
@ -987,4 +987,304 @@ Soft386ParseModRegRm(PSOFT386_STATE State,
|
|||
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 */
|
||||
|
|
|
@ -149,6 +149,66 @@ Soft386ParseModRegRm
|
|||
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 */
|
||||
|
|
|
@ -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 @@ Soft386OpcodeMovByteRegImm(PSOFT386_STATE State, UCHAR Opcode)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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 @@ Soft386OpcodeMovByteRegImm
|
|||
UCHAR Opcode
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
Soft386OpcodeAddByteModrm
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
UCHAR Opcode
|
||||
);
|
||||
|
||||
#endif // _OPCODES_H_
|
||||
|
|
Loading…
Reference in a new issue