You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
4.6 KiB
202 lines
4.6 KiB
/*++
|
|
|
|
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;
|
|
}
|