From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/x86new/mulops.c | 202 ++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 private/ntos/nthals/x86new/mulops.c (limited to 'private/ntos/nthals/x86new/mulops.c') diff --git a/private/ntos/nthals/x86new/mulops.c b/private/ntos/nthals/x86new/mulops.c new file mode 100644 index 000000000..cc020d392 --- /dev/null +++ b/private/ntos/nthals/x86new/mulops.c @@ -0,0 +1,202 @@ +/*++ + +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; +} -- cgit v1.2.3