windows-nt/Source/XPSP1/NT/base/hals/x86new/mulops.c

203 lines
4.4 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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.EFLAG_CF = UpperEqual;
P->Eflags.EFLAG_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.EFLAG_CF = UpperEqual;
P->Eflags.EFLAG_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.EFLAG_CF = UpperZero;
P->Eflags.EFLAG_OF = UpperZero;
return;
}