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.
580 lines
11 KiB
580 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mulops.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the code to emulate the shift opcodes.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 21-Sep-1994
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "nthal.h"
|
|
#include "emulate.h"
|
|
|
|
VOID
|
|
XmRolOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a rol opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Mask;
|
|
ULONG Shift;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Rotate destination left and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Mask = ((1 << Shift) - 1) | (1 << Shift);
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long & Shift;
|
|
if (Count != 0) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value >> (Shift - 1));
|
|
}
|
|
|
|
do {
|
|
Carry = Value >> Shift;
|
|
Value = Carry | ((Value << 1) & Mask);
|
|
Count -= 1;
|
|
} while (Count != 0);
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmRorOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a ror opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Shift;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Rotate destination right and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long & Shift;
|
|
if (Count != 0) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value & 0x1);
|
|
}
|
|
|
|
do {
|
|
Carry = Value & 1;
|
|
Value = (Carry << Shift) | (Value >> 1);
|
|
Count -= 1;
|
|
} while (Count != 0 );
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmRclOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a rcl opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Mask;
|
|
ULONG Shift;
|
|
ULONG Temp;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Rotate destination left through carry and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Mask = ((1 << Shift) - 1) | (1 << Shift);
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long & Shift;
|
|
Carry = P->Eflags.EFLAG_CF;
|
|
if (Count != 0) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value >> (Shift - 1));
|
|
}
|
|
|
|
do {
|
|
Temp = Value >> Shift;
|
|
Value = ((Value << 1) & Mask) | Carry;
|
|
Carry = Temp;
|
|
Count -= 1;
|
|
} while (Count != 0);
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmRcrOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a rcr opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Shift;
|
|
ULONG Temp;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Rotate destination right through carry and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long & Shift;
|
|
Carry = P->Eflags.EFLAG_CF;
|
|
if (Count != 0) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (Value >> Shift) ^ Carry;
|
|
}
|
|
|
|
do {
|
|
Temp = Value & 1;
|
|
Value = (Carry << Shift) | (Value >> 1);
|
|
Carry = Temp;
|
|
Count -= 1;
|
|
} while (Count != 0);
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmShlOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a shl opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Overflow;
|
|
ULONG Shift;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Shift destination left logical and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long;
|
|
if (Count != 0) {
|
|
if (P->DataType == LONG_DATA) {
|
|
Overflow = (Value ^ (Value << 1)) >> 31;
|
|
Carry = Value >> (32 - Count);
|
|
Value <<= Count;
|
|
|
|
} else if (P->DataType == WORD_DATA) {
|
|
Overflow = (Value ^ (Value << 1)) >> 15;
|
|
Carry = Value >> (16 - Count);
|
|
Value = (Value << Count) & 0xffff;
|
|
|
|
} else {
|
|
Overflow = (Value ^ (Value << 1)) >> 7;
|
|
Carry = Value >> (8 - Count);
|
|
Value = (Value << Count) & 0xff;
|
|
}
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
P->Eflags.EFLAG_OF = Overflow;
|
|
P->Eflags.EFLAG_PF = XmComputeParity(Value);
|
|
P->Eflags.EFLAG_ZF = (Value == 0);
|
|
P->Eflags.EFLAG_SF = Value >> Shift;
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmShrOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a shr opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Overflow;
|
|
ULONG Shift;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Shift destination right logical and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Value = P->DstValue.Long;
|
|
Count = P->SrcValue.Long;
|
|
if (Count != 0) {
|
|
if (P->DataType == LONG_DATA) {
|
|
Overflow = Value >> 31;
|
|
Carry = Value >> (Count - 1);
|
|
Value >>= Count;
|
|
|
|
} else if (P->DataType == WORD_DATA) {
|
|
Overflow = Value >> 15;
|
|
Carry = Value >> (Count - 1);
|
|
Value >>= Count;
|
|
|
|
} else {
|
|
Overflow = Value >> 7;
|
|
Carry = Value >> (Count - 1);
|
|
Value >>= Count;
|
|
}
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
P->Eflags.EFLAG_OF = Overflow;
|
|
P->Eflags.EFLAG_PF = XmComputeParity(Value);
|
|
P->Eflags.EFLAG_ZF = (Value == 0);
|
|
P->Eflags.EFLAG_SF = Value >> Shift;
|
|
}
|
|
|
|
XmStoreResult(P, Value);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmSarOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a sar opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG Shift;
|
|
LONG Value;
|
|
|
|
//
|
|
// Shift destination right arithmetic and store result.
|
|
//
|
|
|
|
Shift = ((P->DataType + 1) << 3) - 1;
|
|
Value = (LONG)P->DstValue.Long;
|
|
Count = P->SrcValue.Long;
|
|
if (Count != 0) {
|
|
if (P->DataType == LONG_DATA) {
|
|
Carry = Value >> (Count - 1);
|
|
Value >>= Count;
|
|
|
|
} else if (P->DataType == WORD_DATA) {
|
|
Carry = Value >> (Count - 1);
|
|
Value = ((Value << 16) >> (Count + 16)) & 0xffff;
|
|
|
|
} else {
|
|
Carry = Value >> (Count - 1);
|
|
Value = ((Value << 24) >> (Count + 24)) & 0xff;
|
|
}
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
P->Eflags.EFLAG_OF = 0;
|
|
P->Eflags.EFLAG_PF = XmComputeParity(Value);
|
|
P->Eflags.EFLAG_ZF = (Value == 0);
|
|
P->Eflags.EFLAG_SF = Value >> Shift;
|
|
}
|
|
|
|
XmStoreResult(P, (ULONG)Value);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmShldOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a shld opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG High;
|
|
ULONG Low;
|
|
ULONG Sign;
|
|
|
|
//
|
|
// Double shift left logical and store result.
|
|
//
|
|
// The low 32-bits of the shift are the source.
|
|
// The high 32-bits of the shift are the destination.
|
|
// The shift count has been masked modulo the datatype.
|
|
//
|
|
// This shift is equivalent to extracting the high 32-bits of the left
|
|
// shifted result.
|
|
//
|
|
|
|
Low = P->SrcValue.Long;
|
|
High = P->DstValue.Long;
|
|
Count = P->Shift;
|
|
if (Count != 0) {
|
|
if (P->DataType == LONG_DATA) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (High ^ (High << 1)) >> 31;
|
|
}
|
|
|
|
Carry = High >> (32 - Count);
|
|
High = (High << Count) | (Low >> (32 - Count));
|
|
Sign = High >> 31;
|
|
|
|
} else {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = (High ^ (High << 1)) >> 15;
|
|
}
|
|
|
|
Carry = High >> (16 - Count);
|
|
High = ((High << Count) | (Low >> (16 - Count))) & 0xffff;
|
|
Sign = High >> 15;
|
|
}
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
P->Eflags.EFLAG_PF = XmComputeParity(High);
|
|
P->Eflags.EFLAG_ZF = (High == 0);
|
|
P->Eflags.EFLAG_SF = Sign;
|
|
}
|
|
|
|
XmStoreResult(P, High);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
XmShrdOp (
|
|
IN PRXM_CONTEXT P
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function emulates a shrd opcode.
|
|
|
|
Arguments:
|
|
|
|
P - Supplies a pointer to the emulation context structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Carry;
|
|
ULONG Count;
|
|
ULONG High;
|
|
ULONG Low;
|
|
ULONG Sign;
|
|
|
|
//
|
|
// Double shift right logical and store result.
|
|
//
|
|
// The high 32-bits of the shift are the source.
|
|
// The low 32-bits of the shift are the destination.
|
|
// The shift count has been masked modulo the datatype.
|
|
//
|
|
// This shift is equivalent to extracting the low 32-bits of the right
|
|
// shifted result.
|
|
//
|
|
|
|
High = P->SrcValue.Long;
|
|
Low = P->DstValue.Long;
|
|
Count = P->Shift;
|
|
if (Count != 0) {
|
|
if (P->DataType == LONG_DATA) {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = High ^ (Low >> 31);
|
|
}
|
|
|
|
Carry = Low >> (Count - 1);
|
|
Low = (High << (32 - Count)) | (Low >> Count);
|
|
Sign = Low >> 31;
|
|
|
|
} else {
|
|
if (Count == 1) {
|
|
P->Eflags.EFLAG_OF = High ^ (Low >> 15);
|
|
}
|
|
|
|
Carry = Low >> (Count - 1);
|
|
Low = ((High << (16 - Count)) | (Low >> Count)) & 0xffff;
|
|
Sign = Low >> 15;
|
|
}
|
|
|
|
P->Eflags.EFLAG_CF = Carry;
|
|
P->Eflags.EFLAG_PF = XmComputeParity(Low);
|
|
P->Eflags.EFLAG_ZF = (Low == 0);
|
|
P->Eflags.EFLAG_SF = Sign;
|
|
}
|
|
|
|
XmStoreResult(P, Low);
|
|
return;
|
|
}
|