/*++

Copyright (c) 1994  Microsoft Corporation

Module Name:

    operand.c

Abstract:

    This module implements the operand functions necessary to decode x86
    instruction operands.

Author:

    David N. Cutler (davec) 3-Sep-1994

Environment:

    Kernel mode only.

Revision History:

--*/

#include "nthal.h"
#include "emulate.h"

ULONG
XmPushPopSegment (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Index;

    //
    // Push or pop segment register.
    //

    Index = P->OpcodeControl.FormatType;
    P->DataType = WORD_DATA;
    if (P->FunctionIndex == X86_PUSH_OP) {
        XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Index]));

    } else {
        XmSetDestinationValue(P, (PVOID)(&P->SegmentRegister[Index]));
    }

    return TRUE;
}

ULONG
XmLoadSegment (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Index;
    ULONG DataType;
    PVOID Operand;
    ULONG Number;

    //
    // Load a segment register and a displacement value into register.
    //

    Index = P->OpcodeControl.FormatType;
    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    if (P->RegisterOffsetAddress != FALSE) {
        longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
    }

    XmSetSourceValue(P, Operand);
    DataType = P->DataType;
    P->DataType = WORD_DATA;
    Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
    XmSetDestinationValue(P, Operand);
    P->SegmentRegister[Index - FormatLoadSegmentES] = P->DstValue.Word;
    P->DataType = DataType;
    P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
    return TRUE;
}

ULONG
XmGroup1General (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Group 1 opcodes with general operand specifier and a direction
    // bit.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
        XmSetDestinationValue(P, Operand);
        XmSetSourceValue(P, XmGetRegisterAddress(P, Number));

    } else {
        XmSetDestinationValue(P, XmGetRegisterAddress(P, Number));
        XmSetSourceValue(P, Operand);
    }

    return TRUE;
}

ULONG
XmGroup1Immediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Group 1 opcode with general operand specifier and an immediate
    // operand.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
    XmSetDestinationValue(P, Operand);
    XmSetImmediateSourceValue(P, Source);
    P->FunctionIndex += Number;
    return TRUE;
}

ULONG
XmGroup2By1 (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Group 2 shift opcodes with a general operand specifier and a
    // shift count of 1.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    Source = 1;
    XmSetImmediateSourceValue(P, Source);
    XmSetDestinationValue(P, Operand);
    P->FunctionIndex += Number;
    return TRUE;
}

ULONG
XmGroup2ByCL (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Group 2 shift opcodes with a general operand specifier and a
    // CL shift count.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    Source = (ULONG)P->Gpr[CL].Xl & 0x1f;
    XmSetImmediateSourceValue(P, Source);
    XmSetDestinationValue(P, Operand);
    P->FunctionIndex += Number;
    return TRUE;
}

ULONG
XmGroup2ByByte (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Group 2 shift opcodes with a general operand specifier and a
    // byte immediate shift count.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    Source = XmGetByteImmediate(P) & 0x1f;
    XmSetImmediateSourceValue(P, Source);
    XmSetDestinationValue(P, Operand);
    P->FunctionIndex += Number;
    return TRUE;
}

ULONG
XmGroup3General (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Group 3 opcodes with general operand specifier.
    //
    // N.B. The test operator for this group has an immediate operand
    //      and the multiply and divide operators use the accumulator
    //      as a source. The not and neg operators are unary.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    P->FunctionIndex += Number;
    if (P->FunctionIndex == X86_TEST_OP) {
        Source = XmGetImmediateSourceValue(P, 0);
        XmSetDestinationValue(P, Operand);
        XmSetImmediateSourceValue(P, Source);

    } else {

        //
        // If the operation is a mulitply or divide, then there is an
        // implied operand which is AL, AX, or EAX. If the operation is
        // a divide, then there is an additional implied operand which
        // is AH, DX, or EDX.
        //

        if ((Number & 0x4) != 0) {
            if ((Number & 0x2) == 0) {
                XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));

            } else {
                P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EAX].Exx);
            }

            XmSetSourceValue(P, Operand);

        } else {
            XmSetDestinationValue(P, Operand);
        }
    }

    return TRUE;
}

ULONG
XmGroup45General (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG DataType;
    PVOID Operand;
    ULONG Number;

    //
    // Group 4 and group 5 unary opcodes with general operand specifier.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    if (P->OpcodeControl.FormatType == FormatGroup4General) {
        Number &= 0x1;
    }

    P->FunctionIndex += Number;
    if (P->FunctionIndex == X86_PUSH_OP) {
        XmSetSourceValue(P, Operand);

    } else {

        //
        // If the operation is a call or jump that specifies a segment,
        // then get the segment value.
        //

        XmSetDestinationValue(P, Operand);
        if ((Number == 3) || (Number == 5)) {
            if (P->RegisterOffsetAddress != FALSE) {
                longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
            }

            DataType = P->DataType;
            P->DataType = WORD_DATA;
            Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1);
            XmSetSourceValue(P, Operand);
            P->DstSegment = P->SrcValue.Word;
            P->DataType = DataType;
        }
    }

    return TRUE;
}

ULONG
XmGroup8BitOffset (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Offset;
    ULONG Number;

    //
    // Bit test opcodes with an immediate bit offset and a memory or
    // register operand.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    Offset = XmGetByteImmediate(P);
    XmSetImmediateSourceValue(P, Offset);
    if (P->RegisterOffsetAddress == FALSE) {
        if (P->DataType == LONG_DATA) {
            Offset = (P->SrcValue.Long >> 5) << 2;

        } else {
            Offset = (P->SrcValue.Long >> 4) << 1;
        }

        Operand = XmGetOffsetAddress(P, Offset + P->Offset);
    }

    if (P->DataType == LONG_DATA) {
        P->SrcValue.Long &= 0x1f;

    } else {
        P->SrcValue.Long &= 0xf;
    }

    XmSetDestinationValue(P, Operand);
    P->FunctionIndex += (Number & 0x3);
    return TRUE;
}

ULONG
XmOpcodeRegister (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Number;

    //
    // Unary opodes with a general register encoded in the low
    // 3 bits of the opcode value.
    //

    Number = P->CurrentOpcode & 0x7;
    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    if (P->FunctionIndex == X86_PUSH_OP) {
        XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));

    } else {
        XmSetDestinationValue(P, (PVOID)(&P->Gpr[Number].Exx));
    }

    return TRUE;
}

ULONG
XmLongJump (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Offset;

    //
    // Long jump with opcode containing the control for conditional
    // jumps. The destination of the jump is stored in the destination
    // value and the jump control is stored in the sources value.
    //

    if (P->OpsizePrefixActive != FALSE) {
        Offset = XmGetLongImmediate(P);
        P->DstValue.Long = P->Eip + Offset;

    } else {
        Offset = XmGetWordImmediate(P);
        P->DstValue.Long = (USHORT)(Offset + P->Eip);
    }

    P->SrcValue.Long = P->CurrentOpcode & 0xf;
    return TRUE;
}

ULONG
XmShortJump (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Offset;

    //
    // Short jump with opcode containing the control for conditional
    // jumps. The destination of the jump is stored in the destination
    // value and the jump control is stored in the sources value.
    //

    Offset = (ULONG)XmGetSignedByteImmediateToWord(P);
    P->DstValue.Long = (USHORT)(Offset + P->Eip);
    P->SrcValue.Long = P->CurrentOpcode & 0xf;
    return TRUE;
}

ULONG
XmSetccByte (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Number;

    //
    // General byte destination with reg field ignored and the opcode
    // containing the condition control.
    //

    P->DataType = BYTE_DATA;
    P->DstByte = (UCHAR UNALIGNED *)XmEvaluateAddressSpecifier(P, &Number);
    P->SrcValue.Long = P->CurrentOpcode & 0xf;
    return TRUE;
}

ULONG
XmAccumImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Source;

    //
    // Accumulator destination and immediate source operands.
    //

    XmSetDataType(P);
    Source = XmGetImmediateSourceValue(P, 0);
    XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
    XmSetImmediateSourceValue(P, Source);
    return TRUE;
}

ULONG
XmAccumRegister (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Number;

    //
    // Accumulator destination and a general register source encoded in
    // the low 3-bits of the opcode value.
    //

    Number = P->CurrentOpcode & 0x7;
    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
    XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx));
    return TRUE;
}

ULONG
XmMoveGeneral (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Move opcodes with general operand specifier and a direction bit.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
        P->DstLong = (ULONG UNALIGNED *)Operand;
        XmSetSourceValue(P, XmGetRegisterAddress(P, Number));

    } else {
        P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
        XmSetSourceValue(P, Operand);
    }

    return TRUE;
}

ULONG
XmMoveImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Move opcodes with general operand specifier and an immediate
    // operand.
    //

    XmSetDataType(P);
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    P->DstLong = (ULONG UNALIGNED *)Operand;
    Source = XmGetImmediateSourceValue(P, 0);
    XmSetImmediateSourceValue(P, Source);
    return TRUE;
}

ULONG
XmMoveRegImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Number;

    //
    // Move register immediate opcodes with a general register encoded
    // in the low 3-bits of the opcode value and an immediate operand.
    //

    Number = P->CurrentOpcode & 0x7;
    if ((P->CurrentOpcode & 0x8) == 0) {
        P->DataType = BYTE_DATA;

    } else {
        if (P->OpsizePrefixActive != FALSE) {
            P->DataType = LONG_DATA;

        } else {
            P->DataType = WORD_DATA;
        }
    }

    P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number);
    XmSetImmediateSourceValue(P, XmGetImmediateSourceValue(P, 0));
    return TRUE;
}

ULONG
XmSegmentOffset (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Offset;

    //
    // Move opcodes with an implied accumlator operand and an immediate
    // segment offset and a direction bit.
    //

    XmSetDataType(P);
    if (P->OpaddrPrefixActive != FALSE) {
        Offset = XmGetLongImmediate(P);

    } else {
        Offset = XmGetWordImmediate(P);
    }

    Operand = XmGetOffsetAddress(P, Offset);
    if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
        P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
        XmSetSourceValue(P, Operand);

    } else {
        P->DstLong = (ULONG UNALIGNED *)Operand;
        XmSetSourceValue(P, &P->Gpr[EAX].Exx);
    }

    return TRUE;
}

ULONG
XmMoveSegment (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Move segment opcodes with general operand specifier and a direction
    // bit.
    //

    P->DataType = WORD_DATA;
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    if ((P->CurrentOpcode & DIRECTION_BIT) == 0) {
        P->DstLong = (ULONG UNALIGNED *)Operand;
        XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Number]));

    } else {
        P->DstLong = (ULONG UNALIGNED *)(&P->SegmentRegister[Number]);
        XmSetSourceValue(P, Operand);
    }

    return TRUE;
}

ULONG
XmMoveXxGeneral (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Move zero or sign extended opcodes with general operand specifier.
    //

    if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
        P->DataType = BYTE_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    XmSetSourceValue(P, Operand);
    if (P->DataType == BYTE_DATA) {
        if ((P->CurrentOpcode & 0x8) == 0) {
            P->SrcValue.Long = (ULONG)P->SrcValue.Byte;

        } else {
            P->SrcValue.Long = (ULONG)((LONG)((SCHAR)P->SrcValue.Byte));
        }

    } else {
        if ((P->CurrentOpcode & 0x8) == 0) {
            P->SrcValue.Long = (ULONG)P->SrcValue.Word;

        } else {
            P->SrcValue.Long = (ULONG)((LONG)((SHORT)P->SrcValue.Word));
        }
    }

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
        P->SrcValue.Long &= 0xffff;
    }

    P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
    return TRUE;
}

ULONG
XmFlagsRegister (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    //
    // Flags register source or destination with a stack source or
    // destination.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    if (P->FunctionIndex == X86_PUSH_OP) {
        XmSetSourceValue(P, (PVOID)(&P->AllFlags));

    } else {
        XmSetDestinationValue(P, (PVOID)(&P->AllFlags));
    }

    return TRUE;
}

ULONG
XmPushImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Source;

    //
    // Push opcode with an immediate operand.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
    XmSetImmediateSourceValue(P, Source);
    return TRUE;
}

ULONG
XmPopGeneral (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Pop opcode with a general specifier.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    XmSetDestinationValue(P, Operand);
    return TRUE;
}

ULONG
XmImulImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Number;
    PVOID Operand;
    ULONG Source;

    //
    // Multiply signed opcode with a general specifier and an immediate
    // operand.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT);
    XmSetImmediateSourceValue(P, Source);
    XmSetDestinationValue(P, Operand);
    P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx);
    return TRUE;
}

ULONG
XmStringOperands (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    //
    // String opcode with implicit operands of eSI and eDI.
    //

    XmSetDataType(P);
    return TRUE;
}

ULONG
XmEffectiveOffset (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Effective offset opcodes with general operand specifier.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    P->ComputeOffsetAddress = TRUE;
    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (P->RegisterOffsetAddress != FALSE) {
        longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER);
    }

    P->SrcValue.Long = (ULONG)((ULONG_PTR)Operand);
    XmTraceSource(P, P->SrcValue.Long);
    P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
    return TRUE;
}

ULONG
XmImmediateJump (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    //
    // Immediate long jump with the destination offset and new CS
    // segment value. The destination of the jump is stored in the
    // destination value and the new CS segment value is stored in
    // destination segment.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DstValue.Long = XmGetLongImmediate(P);

    } else {
        P->DstValue.Long = XmGetWordImmediate(P);
    }

    P->DstSegment = XmGetWordImmediate(P);
    return TRUE;
}

ULONG
XmImmediateEnter (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    enter

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    //
    // Enter operands with an allocation size and level number.
    //

    P->SrcValue.Long = XmGetWordImmediate(P);
    P->DstValue.Long = XmGetByteImmediate(P) & 0x1f;
    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    return TRUE;
}

ULONG
XmGeneralBitOffset (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Offset;
    ULONG Number;

    //
    // Bit test opcodes with a register bit offset and a memory or
    // register operand.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
    if (P->RegisterOffsetAddress == FALSE) {
        if (P->DataType == LONG_DATA) {
            Offset = (P->SrcValue.Long >> 5) << 2;

        } else {
            Offset = (P->SrcValue.Long >> 4) << 1;
        }

        Operand = XmGetOffsetAddress(P, Offset + P->Offset);
    }

    if (P->DataType == LONG_DATA) {
        P->SrcValue.Long &= 0x1f;

    } else {
        P->SrcValue.Long &= 0xf;
    }

    XmSetDestinationValue(P, Operand);
    return TRUE;
}

ULONG
XmShiftDouble (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    shld    shrd

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;
    ULONG Source;

    //
    // Shift double operators with an immediate byte or cl shift count.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if ((P->CurrentOpcode & 0x1) == 0) {
        Source = XmGetByteImmediate(P);

    } else {
        Source = P->Gpr[CX].Xl;
    }

    if (P->DataType == LONG_DATA) {
        P->Shift = (UCHAR)(Source & 0x1f);

    } else {
        P->Shift = (UCHAR)(Source & 0xf);
    }

    XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
    XmSetDestinationValue(P, Operand);
    return TRUE;
}

ULONG
XmPortImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Source;

    //
    // In/out opcodes with an immediate port and all other operands implied.
    //

    Source = (ULONG)XmGetByteImmediate(P);
    P->DataType = WORD_DATA;
    XmSetImmediateSourceValue(P, Source);
    XmSetDataType(P);
    return TRUE;
}

ULONG
XmPortDX (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Source;

    //
    // In/out opcodes with a port in DX with all other operands implied.
    //

    Source = P->Gpr[DX].Xx;
    P->DataType = WORD_DATA;
    XmSetImmediateSourceValue(P, Source);
    XmSetDataType(P);
    return TRUE;
}

ULONG
XmBitScanGeneral (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // Bit scan general opcodes with general operand specifier.
    // bit.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (!Operand) return FALSE;
    P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
    XmSetSourceValue(P, Operand);
    return TRUE;
}

ULONG
XmByteImmediate (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    int     xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    ULONG Source;

    //
    // int opcode with an immediate operand.
    //

    P->DataType = BYTE_DATA;
    Source = XmGetImmediateSourceValue(P, 0);
    XmSetImmediateSourceValue(P, Source);
    return TRUE;
}

ULONG
XmXlatOpcode (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xlat

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Offset;

    //
    // xlat opcode with zero extended [AL] + [eBX] as the effective
    // address.
    //

    P->DataType = BYTE_DATA;
    if (P->OpaddrPrefixActive != FALSE) {
        Offset = P->Gpr[EBX].Exx + P->Gpr[AL].Xl;

    } else {
        Offset = P->Gpr[BX].Xx + P->Gpr[AL].Xl;
    }

    Operand = XmGetOffsetAddress(P, Offset);
    XmSetSourceValue(P, Operand);
    P->DstByte = (UCHAR UNALIGNED *)(&P->Gpr[AL].Xl);
    return TRUE;
}

ULONG
XmGeneralRegister (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    bswap

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    PVOID Operand;
    ULONG Number;

    //
    // General register source and destination.
    //

    if (P->OpsizePrefixActive != FALSE) {
        P->DataType = LONG_DATA;

    } else {
        P->DataType = WORD_DATA;
    }

    Operand = XmEvaluateAddressSpecifier(P, &Number);
    if (P->RegisterOffsetAddress == FALSE) {
        longjmp(&P->JumpBuffer[0], XM_ILLEGAL_GENERAL_SPECIFIER);
    }

    XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx));
    P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx);
    return TRUE;
}

ULONG
XmOpcodeEscape (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    2-byte escape

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of xx is returned as the function value.

--*/

{

    //
    // Two byte opcode escape.
    //

    P->OpcodeControlTable = &XmOpcodeControlTable2[0];

#if defined(XM_DEBUG)

    P->OpcodeNameTable = &XmOpcodeNameTable2[0];

#endif

    return FALSE;
}

ULONG
XmPrefixOpcode (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    CS:     DS;     ES:     SS:     FS:     GS:     lock    adrsize
    opsize  repz    repnz

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of FALSE is returned as the function value.

--*/

{

    //
    // Case on the function index.
    //

    switch (P->FunctionIndex) {

        //
        // Segment override prefix.
        //
        // Set the segment override prefix flags and the data segment
        // number.
        //

    case X86_ES_OP:
    case X86_CS_OP:
    case X86_SS_OP:
    case X86_DS_OP:
    case X86_FS_OP:
    case X86_GS_OP:
        P->SegmentPrefixActive = TRUE;
        P->DataSegment = P->FunctionIndex;
        XmTraceOverride(P);
        break;

        //
        // Lock prefix.
        //
        // Set the lock prefix flags.
        //

    case X86_LOCK_OP:
        P->LockPrefixActive = TRUE;
        break;

        //
        // Address size prefix.
        //
        // Set the address size prefix flag.
        //

    case X86_ADSZ_OP:
        P->OpaddrPrefixActive = TRUE;
        break;

        //
        // Operand size prefix.
        //
        // Set the operand size prefix flag.
        //


    case X86_OPSZ_OP:
        P->OpsizePrefixActive = TRUE;
        break;

        //
        // Repeat until ECX or ZF equals zero
        //
        // Set up repeat until ECX or ZF equals zero prefix flags.
        //

    case X86_REPZ_OP:
        P->RepeatPrefixActive = TRUE;
        P->RepeatZflag = 1;
        break;

        //
        // Repeat until ECX equals zero or ZF equals one.
        //
        // Set up repeat until ECX equals zero or ZF equals one prefix
        // flags.
        //

    case X86_REPNZ_OP:
        P->RepeatPrefixActive = TRUE;
        P->RepeatZflag = 0;
        break;
    }

    return FALSE;
}

ULONG
XmNoOperands (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function decodes x86 operand specifiers for the following opcodes:

    xxxxxx

Arguments:

    P - Supplies a pointer to an emulator context structure.

Return Value:

    A completion status of TRUE is returned as the function value.

--*/

{

    return TRUE;
}