summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/x86new/mulops.c
blob: cc020d392f07b8662963c6d5548ea6f70f6ddbf3 (plain) (tree)









































































































































































































                                                                             
/*++

Copyright (c) 1994  Microsoft Corporation

Module Name:

    mulops.c

Abstract:

    This module implements the code to emulate the mul and imul opcodes.

Author:

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

Environment:

    Kernel mode only.

Revision History:

--*/

#include "nthal.h"
#include "emulate.h"

VOID
XmImulOp (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function emulates an imul opcode with a single destination.

Arguments:

    P - Supplies a pointer to the emulation context structure.

Return Value:

    None.

--*/

{

    LARGE_INTEGER Product;
    ULONG UpperEqual;

    //
    // Multiply the signed operands and store result.
    //

    if (P->DataType == BYTE_DATA) {
        Product.QuadPart = Int32x32To64((LONG)((SCHAR)P->DstValue.Byte),
                                        (LONG)((SCHAR)P->SrcValue.Byte));

        XmStoreResult(P, Product.LowPart & 0xff);
        UpperEqual = ((UCHAR)((Product.LowPart >> 8) & 0xff) !=
                      (UCHAR)((SCHAR)Product.LowPart >> 7));

    } else if (P->DataType == LONG_DATA) {
        Product.QuadPart = Int32x32To64((LONG)P->DstValue.Long,
                                        (LONG)P->SrcValue.Long);

        XmStoreResult(P, Product.LowPart);
        UpperEqual = (Product.HighPart != (LONG)Product.LowPart >> 31);

    } else {
        Product.QuadPart = Int32x32To64((LONG)((SHORT)P->DstValue.Word),
                                        (LONG)((SHORT)P->SrcValue.Word));

        XmStoreResult(P, Product.LowPart & 0xffff);
        UpperEqual = ((USHORT)((Product.LowPart >> 16) & 0xffff) !=
                      (USHORT)((SHORT)Product.LowPart >> 15));
    }

    P->Eflags.CF = UpperEqual;
    P->Eflags.OF = UpperEqual;
    return;
}

VOID
XmImulxOp (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function emulates an imul opcode with an extended destination.

Arguments:

    P - Supplies a pointer to the emulation context structure.

Return Value:

    None.

--*/

{

    LARGE_INTEGER Product;
    ULONG UpperEqual;

    //
    // Multiply the signed operands and store the result and the extended
    // result.
    //

    if (P->DataType == BYTE_DATA) {
        Product.QuadPart = Int32x32To64((LONG)((SCHAR)P->DstValue.Byte),
                                        (LONG)((SCHAR)P->SrcValue.Byte));

        P->DataType = WORD_DATA;
        XmStoreResult(P, Product.LowPart & 0xffff);
        UpperEqual = (P->Gpr[AX].Xh != (UCHAR)((SCHAR)P->Gpr[AX].Xl >> 7));

    } else if (P->DataType == LONG_DATA) {
        Product.QuadPart = Int32x32To64((LONG)P->DstValue.Long,
                                        (LONG)P->SrcValue.Long);

        XmStoreResult(P, Product.LowPart);
        P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
        XmStoreResult(P, (ULONG)Product.HighPart);
        UpperEqual = (Product.HighPart != (LONG)Product.LowPart >> 31);

    } else {
        Product.QuadPart = Int32x32To64((LONG)((SHORT)P->DstValue.Word),
                                        (LONG)((SHORT)P->SrcValue.Word));

        XmStoreResult(P, Product.LowPart & 0xffff);
        P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[DX].Exx);
        XmStoreResult(P, Product.LowPart >> 16);
        UpperEqual = (P->Gpr[DX].Xx != (USHORT)((SHORT)P->Gpr[AX].Xx >> 15));
    }

    P->Eflags.CF = UpperEqual;
    P->Eflags.OF = UpperEqual;
    return;
}

VOID
XmMulOp (
    IN PRXM_CONTEXT P
    )

/*++

Routine Description:

    This function emulates a mul opcode.

Arguments:

    P - Supplies a pointer to the emulation context structure.

Return Value:

    None.

--*/

{

    ULARGE_INTEGER Product;
    ULONG UpperZero;

    //
    // Multiply the unsigned operands and store result.
    //

    Product.QuadPart = UInt32x32To64(P->DstValue.Long, P->SrcValue.Long);
    if (P->DataType == BYTE_DATA) {
        P->DataType = WORD_DATA;
        XmStoreResult(P, Product.LowPart);
        UpperZero = (P->Gpr[AX].Xh != 0);

    } else if (P->DataType == LONG_DATA) {
        XmStoreResult(P, Product.LowPart);
        P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
        XmStoreResult(P, Product.HighPart);
        UpperZero = (Product.HighPart != 0);

    } else {
        XmStoreResult(P, Product.LowPart & 0xffff);
        P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[DX].Exx);
        XmStoreResult(P, Product.LowPart >> 16);
        UpperZero = (P->Gpr[DX].Xx != 0);
    }

    P->Eflags.CF = UpperZero;
    P->Eflags.OF = UpperZero;
    return;
}