From a93095e6780950952a706bd527d4676e193846b5 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sun, 20 Oct 2013 00:25:41 +0000 Subject: [PATCH] [FAST486] Implement BT, BTS, BTR and BTC. svn path=/branches/ntvdm/; revision=60716 --- lib/fast486/extraops.c | 353 ++++++++++++++++++++++++++++++++++++++++- lib/fast486/extraops.h | 4 + 2 files changed, 352 insertions(+), 5 deletions(-) diff --git a/lib/fast486/extraops.c b/lib/fast486/extraops.c index 682f3e159c9..c9a90d2e33d 100644 --- a/lib/fast486/extraops.c +++ b/lib/fast486/extraops.c @@ -201,7 +201,7 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] = Fast486ExtOpcodePushFs, Fast486ExtOpcodePopFs, NULL, // Invalid - NULL, // TODO: OPCODE 0xA3 NOT IMPLEMENTED + Fast486ExtOpcodeBitTest, NULL, // TODO: OPCODE 0xA4 NOT IMPLEMENTED NULL, // TODO: OPCODE 0xA5 NOT IMPLEMENTED NULL, // Invalid @@ -209,7 +209,7 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] = Fast486ExtOpcodePushGs, Fast486ExtOpcodePopGs, NULL, // TODO: OPCODE 0xAA NOT IMPLEMENTED - NULL, // TODO: OPCODE 0xAB NOT IMPLEMENTED + Fast486ExtOpcodeBts, NULL, // TODO: OPCODE 0xAC NOT IMPLEMENTED NULL, // TODO: OPCODE 0xAD NOT IMPLEMENTED NULL, // TODO: OPCODE 0xAE NOT IMPLEMENTED @@ -217,7 +217,7 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] = Fast486ExtOpcodeCmpXchgByte, Fast486ExtOpcodeCmpXchg, NULL, // TODO: OPCODE 0xB2 NOT IMPLEMENTED - NULL, // TODO: OPCODE 0xB3 NOT IMPLEMENTED + Fast486ExtOpcodeBtr, NULL, // TODO: OPCODE 0xB4 NOT IMPLEMENTED NULL, // TODO: OPCODE 0xB5 NOT IMPLEMENTED NULL, // TODO: OPCODE 0xB6 NOT IMPLEMENTED @@ -225,7 +225,7 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0xB8 NOT IMPLEMENTED NULL, // TODO: OPCODE 0xB9 NOT IMPLEMENTED NULL, // TODO: OPCODE 0xBA NOT IMPLEMENTED - NULL, // TODO: OPCODE 0xBB NOT IMPLEMENTED + Fast486ExtOpcodeBtc, NULL, // TODO: OPCODE 0xBC NOT IMPLEMENTED NULL, // TODO: OPCODE 0xBD NOT IMPLEMENTED NULL, // TODO: OPCODE 0xBE NOT IMPLEMENTED @@ -318,6 +318,77 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs) return Fast486LoadSegment(State, FAST486_REG_FS, LOWORD(NewSelector)); } +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber &= (1 << DataSize) - 1; + + if (OperandSize) + { + ULONG Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + } + else + { + USHORT Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + } + + /* Return success */ + return TRUE; +} + FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs) { /* Call the internal API */ @@ -338,12 +409,103 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs) return Fast486LoadSegment(State, FAST486_REG_GS, LOWORD(NewSelector)); } +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber &= (1 << DataSize) - 1; + + if (OperandSize) + { + ULONG Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Set the bit */ + Value |= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Set the bit */ + Value |= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte) { FAST486_MOD_REG_RM ModRegRm; UCHAR Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowByte; UCHAR Source, Destination, Result; - BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; TOGGLE_ADSIZE(AddressSize); @@ -478,7 +640,188 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg) /* Return success */ return TRUE; +} +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber &= (1 << DataSize) - 1; + + if (OperandSize) + { + ULONG Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Clear the bit */ + Value &= ~(1 << BitNumber); + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Clear the bit */ + Value &= ~(1 << BitNumber); + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber &= (1 << DataSize) - 1; + + if (OperandSize) + { + ULONG Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Toggle the bit */ + Value ^= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Dummy, Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Toggle the bit */ + Value ^= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; } FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp) diff --git a/lib/fast486/extraops.h b/lib/fast486/extraops.h index 2cf2abc87ac..07a9127ae11 100644 --- a/lib/fast486/extraops.h +++ b/lib/fast486/extraops.h @@ -25,10 +25,14 @@ /* DEFINES ********************************************************************/ FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs); FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest); FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs); FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts); FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte); FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc); FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp); FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet); FAST486_OPCODE_HANDLER(Fast486OpcodeExtended);