From f0040c12e819b2cb091afae7e21f893e7703c8da Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Wed, 4 Sep 2013 18:28:58 +0000 Subject: [PATCH] [SOFT386] Implement the OR, AND and XOR instructions. svn path=/branches/ntvdm/; revision=59991 --- lib/soft386/opcodes.c | 836 +++++++++++++++++++++++++++++++++++++++++- lib/soft386/opcodes.h | 12 + 2 files changed, 830 insertions(+), 18 deletions(-) diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index 8147ba5a348..f6dccb80da4 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -32,12 +32,12 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = Soft386OpcodeAddEax, NULL, // TODO: OPCODE 0x06 NOT SUPPORTED NULL, // TODO: OPCODE 0x07 NOT SUPPORTED - NULL, // TODO: OPCODE 0x08 NOT SUPPORTED - NULL, // TODO: OPCODE 0x09 NOT SUPPORTED - NULL, // TODO: OPCODE 0x0A NOT SUPPORTED - NULL, // TODO: OPCODE 0x0B NOT SUPPORTED - NULL, // TODO: OPCODE 0x0C NOT SUPPORTED - NULL, // TODO: OPCODE 0x0D NOT SUPPORTED + Soft386OpcodeOrByteModrm, + Soft386OpcodeOrModrm, + Soft386OpcodeOrByteModrm, + Soft386OpcodeOrModrm, + Soft386OpcodeOrAl, + Soft386OpcodeOrEax, NULL, // TODO: OPCODE 0x0E NOT SUPPORTED NULL, // TODO: OPCODE 0x0F NOT SUPPORTED NULL, // TODO: OPCODE 0x10 NOT SUPPORTED @@ -56,12 +56,12 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0x1D NOT SUPPORTED NULL, // TODO: OPCODE 0x1E NOT SUPPORTED NULL, // TODO: OPCODE 0x1F NOT SUPPORTED - NULL, // TODO: OPCODE 0x20 NOT SUPPORTED - NULL, // TODO: OPCODE 0x21 NOT SUPPORTED - NULL, // TODO: OPCODE 0x22 NOT SUPPORTED - NULL, // TODO: OPCODE 0x23 NOT SUPPORTED - NULL, // TODO: OPCODE 0x24 NOT SUPPORTED - NULL, // TODO: OPCODE 0x25 NOT SUPPORTED + Soft386OpcodeAndByteModrm, + Soft386OpcodeAndModrm, + Soft386OpcodeAndByteModrm, + Soft386OpcodeAndModrm, + Soft386OpcodeAndAl, + Soft386OpcodeAndEax, Soft386OpcodePrefix, NULL, // TODO: OPCODE 0x27 NOT SUPPORTED NULL, // TODO: OPCODE 0x28 NOT SUPPORTED @@ -72,12 +72,12 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0x2D NOT SUPPORTED Soft386OpcodePrefix, NULL, // TODO: OPCODE 0x2F NOT SUPPORTED - NULL, // TODO: OPCODE 0x30 NOT SUPPORTED - NULL, // TODO: OPCODE 0x31 NOT SUPPORTED - NULL, // TODO: OPCODE 0x32 NOT SUPPORTED - NULL, // TODO: OPCODE 0x33 NOT SUPPORTED - NULL, // TODO: OPCODE 0x34 NOT SUPPORTED - NULL, // TODO: OPCODE 0x35 NOT SUPPORTED + Soft386OpcodeXorByteModrm, + Soft386OpcodeXorModrm, + Soft386OpcodeXorByteModrm, + Soft386OpcodeXorModrm, + Soft386OpcodeXorAl, + Soft386OpcodeXorEax, Soft386OpcodePrefix, NULL, // TODO: OPCODE 0x37 NOT SUPPORTED NULL, // TODO: OPCODE 0x38 NOT SUPPORTED @@ -282,6 +282,8 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0xFF NOT SUPPORTED }; +/* PUBLIC FUNCTIONS ***********************************************************/ + SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix) { BOOLEAN Valid = FALSE; @@ -1490,3 +1492,801 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax) return TRUE; } + +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm) +{ + 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) == 0x08); + + 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 = FALSE; + State->Flags.Of = 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); +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm) +{ + SOFT386_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x09); + + OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE) + { + /* The ADSIZE prefix toggles the address size */ + AddressSize = !AddressSize; + } + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the operand size */ + OperandSize = !OperandSize; + } + + if (State->PrefixFlags + & ~(SOFT386_PREFIX_ADSIZE + | SOFT386_PREFIX_OPSIZE + | 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; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmWordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl) +{ + UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x0C); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (!Soft386FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = 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 */ + State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result; + + return TRUE; +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x0D); + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Soft386FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Soft386FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm) +{ + 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) == 0x20); + + 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 = FALSE; + State->Flags.Of = 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); +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm) +{ + SOFT386_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x21); + + OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE) + { + /* The ADSIZE prefix toggles the address size */ + AddressSize = !AddressSize; + } + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the operand size */ + OperandSize = !OperandSize; + } + + if (State->PrefixFlags + & ~(SOFT386_PREFIX_ADSIZE + | SOFT386_PREFIX_OPSIZE + | 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; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmWordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl) +{ + UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x24); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (!Soft386FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = 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 */ + State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result; + + return TRUE; +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x25); + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Soft386FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Soft386FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm) +{ + 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) == 0x30); + + 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 = FALSE; + State->Flags.Of = 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); +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm) +{ + SOFT386_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x31); + + OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE) + { + /* The ADSIZE prefix toggles the address size */ + AddressSize = !AddressSize; + } + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the operand size */ + OperandSize = !OperandSize; + } + + if (State->PrefixFlags + & ~(SOFT386_PREFIX_ADSIZE + | SOFT386_PREFIX_OPSIZE + | 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; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Soft386ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + return Soft386WriteModrmWordOperands(State, + &ModRegRm, + Opcode & SOFT386_OPCODE_WRITE_REG, + Result); + } +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl) +{ + UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x34); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (!Soft386FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = 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 */ + State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result; + + return TRUE; +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x35); + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Soft386FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Soft386FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0) ? TRUE : FALSE; + State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE; + State->Flags.Pf = Soft386CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result; + } + + return TRUE; +} diff --git a/lib/soft386/opcodes.h b/lib/soft386/opcodes.h index a11bb0e9779..e0f7ed72353 100644 --- a/lib/soft386/opcodes.h +++ b/lib/soft386/opcodes.h @@ -54,5 +54,17 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm); SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm); SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl); SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax); +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl); +SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax); +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl); +SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax); +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm); +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl); +SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax); #endif // _OPCODES_H_