Source code of Windows XP (NT5)
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.
|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
mulops.c
Abstract:
This module implements the code to emulate the div and idiv opcodes.
Author:
David N. Cutler (davec) 21-Sep-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "nthal.h"
#include "emulate.h"
VOID XmDivOp ( IN PRXM_CONTEXT P )
/*++
Routine Description:
This function emulates an unsigned div opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
UNALIGNED ULONG *DstHigh; ULONG Dividend; ULONG Divisor; ULARGE_INTEGER Large; ULONG Quotient; ULONG Remainder;
//
// Divide the unsigned operands and store result.
//
Divisor = P->SrcValue.Long; if (Divisor == 0) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO); }
if (P->DataType == BYTE_DATA) { Dividend = (ULONG)P->Gpr[AX].Xx; Quotient = Dividend / Divisor; Remainder = Dividend % Divisor; DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh); Dividend >>= 8;
} else if (P->DataType == WORD_DATA) { Dividend = (P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx; Quotient = Dividend / Divisor; Remainder = Dividend % Divisor; DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx); Dividend >>= 16;
} else { Dividend = P->Gpr[EDX].Exx; Large.HighPart = Dividend; Large.LowPart = P->Gpr[EAX].Exx; Quotient = (ULONG)(Large.QuadPart / (ULONGLONG)Divisor); Remainder = (ULONG)(Large.QuadPart % (ULONGLONG)Divisor); DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx); }
if (Dividend >= Divisor) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW); }
XmStoreResult(P, Quotient); P->DstLong = DstHigh; XmStoreResult(P, Remainder); return; }
VOID XmIdivOp ( IN PRXM_CONTEXT P )
/*++
Routine Description:
This function emulates a signed idiv opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
UNALIGNED ULONG *DstHigh; LONG Dividend; LONG Divisor; LARGE_INTEGER Large; LONG Quotient; LONG Remainder; LARGE_INTEGER Result;
//
// Divide the signed operands and store result.
//
if (P->SrcValue.Long == 0) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO); }
if (P->DataType == BYTE_DATA) { Divisor = (LONG)((SCHAR)P->SrcValue.Byte); Dividend = (LONG)((SHORT)P->Gpr[AX].Xx); Quotient = Dividend / Divisor; Remainder = Dividend % Divisor; DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh); if ((Quotient >> 8) != ((Quotient << 24) >> 31)) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW); }
Quotient &= 0xff; Remainder &= 0xff;
} else if (P->DataType == WORD_DATA) { Divisor = (LONG)((SHORT)P->SrcValue.Word); Dividend = (LONG)((P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx); Quotient = Dividend / Divisor; Remainder = Dividend % Divisor; DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx); if ((Quotient >> 16) != ((Quotient << 16) >> 31)) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW); }
Quotient &= 0xffff; Remainder &= 0xfff;
} else { Divisor = (LONG)(P->SrcValue.Long); Large.HighPart = (LONG)P->Gpr[EDX].Exx; Large.LowPart = P->Gpr[EAX].Exx; Result.QuadPart = Large.QuadPart / (LONGLONG)Divisor; Quotient = Result.LowPart; Remainder = (LONG)(Large.QuadPart % (LONGLONG)Divisor); DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx); if (Result.HighPart != ((LONG)Result.LowPart >> 31)) { longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW); } }
XmStoreResult(P, Quotient); P->DstLong = DstHigh; XmStoreResult(P, Remainder); return; }
|