mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 20:36:35 +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;
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -149,6 +149,66 @@ Soft386ParseModRegRm
|
||||||
PSOFT386_MOD_REG_RM ModRegRm
|
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_
|
#endif // _COMMON_H_
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
SOFT386_OPCODE_HANDLER_PROC
|
SOFT386_OPCODE_HANDLER_PROC
|
||||||
Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
|
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 0x01 NOT SUPPORTED
|
||||||
NULL, // TODO: OPCODE 0x02 NOT SUPPORTED
|
Soft386OpcodeAddByteModrm, // TODO: OPCODE 0x02 NOT SUPPORTED
|
||||||
NULL, // TODO: OPCODE 0x03 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0x03 NOT SUPPORTED
|
||||||
NULL, // TODO: OPCODE 0x04 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0x04 NOT SUPPORTED
|
||||||
NULL, // TODO: OPCODE 0x05 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0x05 NOT SUPPORTED
|
||||||
|
@ -1258,3 +1258,64 @@ Soft386OpcodeMovByteRegImm(PSOFT386_STATE State, UCHAR Opcode)
|
||||||
|
|
||||||
return TRUE;
|
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
|
#endif
|
||||||
|
|
||||||
#define SOFT386_NUM_OPCODE_HANDLERS 256
|
#define SOFT386_NUM_OPCODE_HANDLERS 256
|
||||||
|
#define SOFT386_OPCODE_WRITE_REG (1 << 1)
|
||||||
|
|
||||||
typedef BOOLEAN (FASTCALL *SOFT386_OPCODE_HANDLER_PROC)(PSOFT386_STATE, UCHAR);
|
typedef BOOLEAN (FASTCALL *SOFT386_OPCODE_HANDLER_PROC)(PSOFT386_STATE, UCHAR);
|
||||||
|
|
||||||
|
@ -207,4 +208,12 @@ Soft386OpcodeMovByteRegImm
|
||||||
UCHAR Opcode
|
UCHAR Opcode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FASTCALL
|
||||||
|
Soft386OpcodeAddByteModrm
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
UCHAR Opcode
|
||||||
|
);
|
||||||
|
|
||||||
#endif // _OPCODES_H_
|
#endif // _OPCODES_H_
|
||||||
|
|
Loading…
Reference in a new issue