diff --git a/lib/soft386/common.c b/lib/soft386/common.c index 71115d495bf..0988a1356c0 100644 --- a/lib/soft386/common.c +++ b/lib/soft386/common.c @@ -754,4 +754,14 @@ Soft386Exception(PSOFT386_STATE State, INT ExceptionCode) } } +inline +BOOLEAN +Soft386CalculateParity(UCHAR Number) +{ + Number ^= Number >> 1; + Number ^= Number >> 2; + Number ^= Number >> 4; + return !(Number & 1); +} + /* EOF */ diff --git a/lib/soft386/common.h b/lib/soft386/common.h index df9ba0a12e9..bd8dc39e7d5 100644 --- a/lib/soft386/common.h +++ b/lib/soft386/common.h @@ -15,6 +15,9 @@ #define FASTCALL __fastcall #endif +#define SIGN_FLAG_BYTE 0x80 +#define SIGN_FLAG_WORD 0x8000 +#define SIGN_FLAG_LONG 0x80000000 #define GET_SEGMENT_RPL(s) ((s) & 3) #define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8) @@ -119,6 +122,13 @@ Soft386Exception INT ExceptionCode ); +inline +BOOLEAN +Soft386CalculateParity +( + UCHAR Number +); + #endif // _COMMON_H_ /* EOF */ diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index 9e642946ee6..bda4ca5cbd2 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -88,22 +88,22 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0x3D NOT SUPPORTED Soft386OpcodePrefix, NULL, // TODO: OPCODE 0x3F NOT SUPPORTED - NULL, // TODO: OPCODE 0x40 NOT SUPPORTED - NULL, // TODO: OPCODE 0x41 NOT SUPPORTED - NULL, // TODO: OPCODE 0x42 NOT SUPPORTED - NULL, // TODO: OPCODE 0x43 NOT SUPPORTED - NULL, // TODO: OPCODE 0x44 NOT SUPPORTED - NULL, // TODO: OPCODE 0x45 NOT SUPPORTED - NULL, // TODO: OPCODE 0x46 NOT SUPPORTED - NULL, // TODO: OPCODE 0x47 NOT SUPPORTED - NULL, // TODO: OPCODE 0x48 NOT SUPPORTED - NULL, // TODO: OPCODE 0x49 NOT SUPPORTED - NULL, // TODO: OPCODE 0x4A NOT SUPPORTED - NULL, // TODO: OPCODE 0x4B NOT SUPPORTED - NULL, // TODO: OPCODE 0x4C NOT SUPPORTED - NULL, // TODO: OPCODE 0x4D NOT SUPPORTED - NULL, // TODO: OPCODE 0x4E NOT SUPPORTED - NULL, // TODO: OPCODE 0x4F NOT SUPPORTED + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeIncrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, + Soft386OpcodeDecrement, NULL, // TODO: OPCODE 0x50 NOT SUPPORTED NULL, // TODO: OPCODE 0x51 NOT SUPPORTED NULL, // TODO: OPCODE 0x52 NOT SUPPORTED @@ -444,3 +444,93 @@ Soft386OpcodePrefix(PSOFT386_STATE State, UCHAR Opcode) return TRUE; } + +BOOLEAN +FASTCALL +Soft386OpcodeIncrement(PSOFT386_STATE State, UCHAR Opcode) +{ + ULONG Value; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else if (State->PrefixFlags != 0) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x40); + + if (Size) + { + Value = ++State->GeneralRegs[Opcode & 0x07].Long; + + State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE; + } + else + { + Value = ++State->GeneralRegs[Opcode & 0x07].LowWord; + + State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE; + State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE; + } + + State->Flags.Zf = (Value == 0) ? TRUE : FALSE; + State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value)); + + /* Return success */ + return TRUE; +} + +BOOLEAN +FASTCALL +Soft386OpcodeDecrement(PSOFT386_STATE State, UCHAR Opcode) +{ + ULONG Value; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else if (State->PrefixFlags != 0) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x48); + + if (Size) + { + Value = --State->GeneralRegs[Opcode & 0x07].Long; + + State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)) ? TRUE : FALSE; + State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE; + } + else + { + Value = --State->GeneralRegs[Opcode & 0x07].LowWord; + + State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)) ? TRUE : FALSE; + State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE; + } + + State->Flags.Zf = (Value == 0) ? TRUE : FALSE; + State->Flags.Af = ((Value & 0x0F) == 0x0F) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value)); + + /* Return success */ + return TRUE; +} diff --git a/lib/soft386/opcodes.h b/lib/soft386/opcodes.h index 25fec0002f4..b6d63b221ff 100644 --- a/lib/soft386/opcodes.h +++ b/lib/soft386/opcodes.h @@ -31,4 +31,20 @@ Soft386OpcodePrefix UCHAR Opcode ); +BOOLEAN +FASTCALL +Soft386OpcodeIncrement +( + PSOFT386_STATE State, + UCHAR Opcode +); + +BOOLEAN +FASTCALL +Soft386OpcodeDecrement +( + PSOFT386_STATE State, + UCHAR Opcode +); + #endif // _OPCODES_H_