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

558 lines
9.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
utility.c
Abstract:
This module implements utility functions.
Author:
David N. Cutler (davec) 7-Sep-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "nthal.h"
#include "emulate.h"
//
// Define bit count array.
//
UCHAR XmBitCount[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
ULONG
XmComputeParity (
IN ULONG Result
)
/*++
Routine Description:
This function computes the parity of the low byte of the specified
result.
Arguments:
Result - Supplies the result for which the parity flag is computed.
Return Value:
The parity flag value.
--*/
{
ULONG Count;
//
// Sum the bits in the result and return the complement of the low bit.
//
Count = XmBitCount[Result & 0xf];
Count += XmBitCount[(Result >> 4) & 0xf];
return (~Count) & 1;
}
UCHAR
XmGetCodeByte (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets the next code byte from the instruction stream.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte form the instruction stream.
--*/
{
ULONG Offset;
//
// If the current IP is within the code segment, then return the
// next byte from the instrcution stream and increment the IP value.
// Otherwise, raise an exception.
//
Offset = P->Eip;
if (Offset > P->SegmentLimit[CS]) {
longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
}
P->Ip += 1;
return *(PUCHAR)((P->TranslateAddress)(P->SegmentRegister[CS], (USHORT)Offset));
}
UCHAR
XmGetByteImmediate (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate byte operand from the
code stream and returns a byte value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte from the instruction stream.
--*/
{
UCHAR Byte;
//
// Get immediate byte from the code stream.
//
Byte = XmGetCodeByte(P);
XmTraceInstruction(BYTE_DATA, (ULONG)Byte);
return Byte;
}
USHORT
XmGetByteImmediateToWord (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate byte operand from the
code stream and returns a zero extended byte to word value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte from the instruction stream zero extended to a word.
--*/
{
USHORT Word;
//
// Get immediate byte from the code stream.
//
Word = XmGetCodeByte(P);
XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
return Word;
}
ULONG
XmGetByteImmediateToLong (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate byte operand from the
code stream and returns a zero extended byte to long value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte from the instruction stream zero extended to a long.
--*/
{
ULONG Long;
//
// Get immediate byte from the code stream.
//
Long = XmGetCodeByte(P);
XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
return Long;
}
USHORT
XmGetSignedByteImmediateToWord (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate byte operand from the
code stream and returns a sign extended byte to word value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte from the instruction stream sign extended to a word.
--*/
{
USHORT Word;
//
// Get immediate byte from the code stream.
//
Word = (USHORT)((SHORT)((SCHAR)XmGetCodeByte(P)));
XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
return Word;
}
ULONG
XmGetSignedByteImmediateToLong (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate byte operand from the
code stream and returns a sign extended byte to long value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next byte from the instruction stream sign extended to a long.
--*/
{
ULONG Long;
//
// Get immediate byte from the code stream.
//
Long = (ULONG)((LONG)((SCHAR)XmGetCodeByte(P)));
XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
return Long;
}
USHORT
XmGetWordImmediate (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate word operand from the
code stream and returns a word value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next word from the instruction stream.
--*/
{
USHORT Word;
//
// Get immediate word from the code stream.
//
Word = XmGetCodeByte(P);
Word += XmGetCodeByte(P) << 8;
XmTraceInstruction(WORD_DATA, (ULONG)Word);
return Word;
}
ULONG
XmGetLongImmediate (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function gets an unsigned immediate long operand from the
code stream and returns a long value.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
The next long from the instruction stream.
--*/
{
ULONG Long;
//
// Get immediate long from the code stream.
//
Long = XmGetCodeByte(P);
Long += XmGetCodeByte(P) << 8;
Long += XmGetCodeByte(P) << 16;
Long += XmGetCodeByte(P) << 24;
XmTraceInstruction(LONG_DATA, Long);
return Long;
}
ULONG
XmPopStack (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function pops an operand from the stack.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
ULONG Offset;
//
// Compute the new stack address and compare against the segment limit.
// If the new address is greater than the limit, then raise an exception.
// Otherwise, perform the push operation.
//
Offset = P->Gpr[ESP].Exx;
if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
longjmp(&P->JumpBuffer[0], XM_STACK_UNDERFLOW);
}
P->Gpr[ESP].Exx += (P->DataType + 1);
XmSetSourceValue(P, (P->TranslateAddress)(P->SegmentRegister[SS], (USHORT)Offset));
return P->SrcValue.Long;
}
VOID
XmPushStack (
IN PRXM_CONTEXT P,
IN ULONG Value
)
/*++
Routine Description:
This function pushes an operand on the stack.
Arguments:
P - Supplies a pointer to the emulation context structure.
Value - Supplies the value to be pushed.
Return Value:
None.
--*/
{
ULONG Offset;
//
// Compute the new stack address and compare against the segment limit.
// If the new address is greater than the limit, then raise an exception.
// Otherwise, perform the push operation.
//
Offset = P->Gpr[ESP].Exx - P->DataType - 1;
if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
longjmp(&P->JumpBuffer[0], XM_STACK_OVERFLOW);
}
P->Gpr[ESP].Exx = Offset;
P->DstLong = (ULONG UNALIGNED *)((P->TranslateAddress)(P->SegmentRegister[SS],
(USHORT)Offset));
XmStoreResult(P, Value);
return;
}
VOID
XmSetDataType (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function sets the data type of the operation based on the width
bit of the current opcode.
Arguments:
P - Supplies a pointer to an emulator context structure.
Return Value:
None.
--*/
{
//
// If the width bit is zero, then the data type is byte. Otherwise,
// the datatype is determined by the presence of absence of a operand
// size prefix.
//
if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
P->DataType = BYTE_DATA;
} else if (P->OpsizePrefixActive != FALSE) {
P->DataType = LONG_DATA;
} else {
P->DataType = WORD_DATA;
}
return;
}
VOID
XmStoreResult (
IN PRXM_CONTEXT P,
IN ULONG Result
)
/*++
Routine Description:
This function stores the result of an operation.
Arguments:
P - Supplies a pointer to an emulator context structure.
Result - Supplies the result value to store.
Return Value:
None.
--*/
{
//
// Store result of operation.
//
if (P->DataType == BYTE_DATA) {
*P->DstByte = (UCHAR)Result;
} else if (P->DataType == WORD_DATA) {
if (((ULONG_PTR)P->DstWord & 0x1) == 0) {
*((PUSHORT)(P->DstWord)) = (USHORT)Result;
} else {
*P->DstWord = (USHORT)Result;
}
} else {
#ifdef _IA64_
//
// Hack to force the compiler to generate unaligned
// accesses. We can remove it when the compiler is
// fixed.
//
*P->DstLong = Result;
#else
if (((ULONG_PTR)P->DstLong & 0x3) == 0) {
*((PULONG)(P->DstLong)) = Result;
} else {
*P->DstLong = Result;
}
#endif // #ifdef _IA64_
}
XmTraceResult(P, Result);
return;
}