/*++ Copyright (c) 1994 Microsoft Corporation Module Name: operand.c Abstract: This module implements the operand functions necessary to decode x86 instruction operands. Author: David N. Cutler (davec) 3-Sep-1994 Environment: Kernel mode only. Revision History: --*/ #include "nthal.h" #include "emulate.h" ULONG XmPushPopSegment ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Index; // // Push or pop segment register. // Index = P->OpcodeControl.FormatType; P->DataType = WORD_DATA; if (P->FunctionIndex == X86_PUSH_OP) { XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Index])); } else { XmSetDestinationValue(P, (PVOID)(&P->SegmentRegister[Index])); } return TRUE; } ULONG XmLoadSegment ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Index; ULONG DataType; PVOID Operand; ULONG Number; // // Load a segment register and a displacement value into register. // Index = P->OpcodeControl.FormatType; if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); if (P->RegisterOffsetAddress != FALSE) { longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER); } XmSetSourceValue(P, Operand); DataType = P->DataType; P->DataType = WORD_DATA; Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1); XmSetDestinationValue(P, Operand); P->SegmentRegister[Index - FormatLoadSegmentES] = P->DstValue.Word; P->DataType = DataType; P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx); return TRUE; } ULONG XmGroup1General ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Group 1 opcodes with general operand specifier and a direction // bit. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); if ((P->CurrentOpcode & DIRECTION_BIT) == 0) { XmSetDestinationValue(P, Operand); XmSetSourceValue(P, XmGetRegisterAddress(P, Number)); } else { XmSetDestinationValue(P, XmGetRegisterAddress(P, Number)); XmSetSourceValue(P, Operand); } return TRUE; } ULONG XmGroup1Immediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Group 1 opcode with general operand specifier and an immediate // operand. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT); XmSetDestinationValue(P, Operand); XmSetImmediateSourceValue(P, Source); P->FunctionIndex += Number; return TRUE; } ULONG XmGroup2By1 ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Group 2 shift opcodes with a general operand specifier and a // shift count of 1. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); Source = 1; XmSetImmediateSourceValue(P, Source); XmSetDestinationValue(P, Operand); P->FunctionIndex += Number; return TRUE; } ULONG XmGroup2ByCL ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Group 2 shift opcodes with a general operand specifier and a // CL shift count. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); Source = (ULONG)P->Gpr[CL].Xl & 0x1f; XmSetImmediateSourceValue(P, Source); XmSetDestinationValue(P, Operand); P->FunctionIndex += Number; return TRUE; } ULONG XmGroup2ByByte ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Group 2 shift opcodes with a general operand specifier and a // byte immediate shift count. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); Source = XmGetByteImmediate(P) & 0x1f; XmSetImmediateSourceValue(P, Source); XmSetDestinationValue(P, Operand); P->FunctionIndex += Number; return TRUE; } ULONG XmGroup3General ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Group 3 opcodes with general operand specifier. // // N.B. The test operator for this group has an immediate operand // and the multiply and divide operators use the accumulator // as a source. The not and neg operators are unary. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); P->FunctionIndex += Number; if (P->FunctionIndex == X86_TEST_OP) { Source = XmGetImmediateSourceValue(P, 0); XmSetDestinationValue(P, Operand); XmSetImmediateSourceValue(P, Source); } else { // // If the operation is a mulitply or divide, then there is an // implied operand which is AL, AX, or EAX. If the operation is // a divide, then there is an additional implied operand which // is AH, DX, or EDX. // if ((Number & 0x4) != 0) { if ((Number & 0x2) == 0) { XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx)); } else { P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[EAX].Exx); } XmSetSourceValue(P, Operand); } else { XmSetDestinationValue(P, Operand); } } return TRUE; } ULONG XmGroup45General ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG DataType; PVOID Operand; ULONG Number; // // Group 4 and group 5 unary opcodes with general operand specifier. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); if (P->OpcodeControl.FormatType == FormatGroup4General) { Number &= 0x1; } P->FunctionIndex += Number; if (P->FunctionIndex == X86_PUSH_OP) { XmSetSourceValue(P, Operand); } else { // // If the operation is a call or jump that specifies a segment, // then get the segment value. // XmSetDestinationValue(P, Operand); if ((Number == 3) || (Number == 5)) { if (P->RegisterOffsetAddress != FALSE) { longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER); } DataType = P->DataType; P->DataType = WORD_DATA; Operand = XmGetOffsetAddress(P, P->Offset + DataType + 1); XmSetSourceValue(P, Operand); P->DstSegment = P->SrcValue.Word; P->DataType = DataType; } } return TRUE; } ULONG XmGroup8BitOffset ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Offset; ULONG Number; // // Bit test opcodes with an immediate bit offset and a memory or // register operand. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); Offset = XmGetByteImmediate(P); XmSetImmediateSourceValue(P, Offset); if (P->RegisterOffsetAddress == FALSE) { if (P->DataType == LONG_DATA) { Offset = (P->SrcValue.Long >> 5) << 2; } else { Offset = (P->SrcValue.Long >> 4) << 1; } Operand = XmGetOffsetAddress(P, Offset + P->Offset); } if (P->DataType == LONG_DATA) { P->SrcValue.Long &= 0x1f; } else { P->SrcValue.Long &= 0xf; } XmSetDestinationValue(P, Operand); P->FunctionIndex += (Number & 0x3); return TRUE; } ULONG XmOpcodeRegister ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Number; // // Unary opodes with a general register encoded in the low // 3 bits of the opcode value. // Number = P->CurrentOpcode & 0x7; if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } if (P->FunctionIndex == X86_PUSH_OP) { XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx)); } else { XmSetDestinationValue(P, (PVOID)(&P->Gpr[Number].Exx)); } return TRUE; } ULONG XmLongJump ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Offset; // // Long jump with opcode containing the control for conditional // jumps. The destination of the jump is stored in the destination // value and the jump control is stored in the sources value. // if (P->OpsizePrefixActive != FALSE) { Offset = XmGetLongImmediate(P); P->DstValue.Long = P->Eip + Offset; } else { Offset = XmGetWordImmediate(P); P->DstValue.Long = (USHORT)(Offset + P->Eip); } P->SrcValue.Long = P->CurrentOpcode & 0xf; return TRUE; } ULONG XmShortJump ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Offset; // // Short jump with opcode containing the control for conditional // jumps. The destination of the jump is stored in the destination // value and the jump control is stored in the sources value. // Offset = (ULONG)XmGetSignedByteImmediateToWord(P); P->DstValue.Long = (USHORT)(Offset + P->Eip); P->SrcValue.Long = P->CurrentOpcode & 0xf; return TRUE; } ULONG XmSetccByte ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Number; // // General byte destination with reg field ignored and the opcode // containing the condition control. // P->DataType = BYTE_DATA; P->DstByte = (UCHAR UNALIGNED *)XmEvaluateAddressSpecifier(P, &Number); P->SrcValue.Long = P->CurrentOpcode & 0xf; return TRUE; } ULONG XmAccumImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Source; // // Accumulator destination and immediate source operands. // XmSetDataType(P); Source = XmGetImmediateSourceValue(P, 0); XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx)); XmSetImmediateSourceValue(P, Source); return TRUE; } ULONG XmAccumRegister ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Number; // // Accumulator destination and a general register source encoded in // the low 3-bits of the opcode value. // Number = P->CurrentOpcode & 0x7; if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx)); XmSetDestinationValue(P, (PVOID)(&P->Gpr[EAX].Exx)); return TRUE; } ULONG XmMoveGeneral ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Move opcodes with general operand specifier and a direction bit. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); if ((P->CurrentOpcode & DIRECTION_BIT) == 0) { P->DstLong = (ULONG UNALIGNED *)Operand; XmSetSourceValue(P, XmGetRegisterAddress(P, Number)); } else { P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number); XmSetSourceValue(P, Operand); } return TRUE; } ULONG XmMoveImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Move opcodes with general operand specifier and an immediate // operand. // XmSetDataType(P); Operand = XmEvaluateAddressSpecifier(P, &Number); P->DstLong = (ULONG UNALIGNED *)Operand; Source = XmGetImmediateSourceValue(P, 0); XmSetImmediateSourceValue(P, Source); return TRUE; } ULONG XmMoveRegImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Number; // // Move register immediate opcodes with a general register encoded // in the low 3-bits of the opcode value and an immediate operand. // Number = P->CurrentOpcode & 0x7; if ((P->CurrentOpcode & 0x8) == 0) { P->DataType = BYTE_DATA; } else { if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } } P->DstLong = (ULONG UNALIGNED *)XmGetRegisterAddress(P, Number); XmSetImmediateSourceValue(P, XmGetImmediateSourceValue(P, 0)); return TRUE; } ULONG XmSegmentOffset ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Offset; // // Move opcodes with an implied accumlator operand and an immediate // segment offset and a direction bit. // XmSetDataType(P); if (P->OpaddrPrefixActive != FALSE) { Offset = XmGetLongImmediate(P); } else { Offset = XmGetWordImmediate(P); } Operand = XmGetOffsetAddress(P, Offset); if ((P->CurrentOpcode & DIRECTION_BIT) == 0) { P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx); XmSetSourceValue(P, Operand); } else { P->DstLong = (ULONG UNALIGNED *)Operand; XmSetSourceValue(P, &P->Gpr[EAX].Exx); } return TRUE; } ULONG XmMoveSegment ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Move segment opcodes with general operand specifier and a direction // bit. // P->DataType = WORD_DATA; Operand = XmEvaluateAddressSpecifier(P, &Number); if ((P->CurrentOpcode & DIRECTION_BIT) == 0) { P->DstLong = (ULONG UNALIGNED *)Operand; XmSetSourceValue(P, (PVOID)(&P->SegmentRegister[Number])); } else { P->DstLong = (ULONG UNALIGNED *)(&P->SegmentRegister[Number]); XmSetSourceValue(P, Operand); } return TRUE; } ULONG XmMoveXxGeneral ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Move zero or sign extended opcodes with general operand specifier. // if ((P->CurrentOpcode & WIDTH_BIT) == 0) { P->DataType = BYTE_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); XmSetSourceValue(P, Operand); if (P->DataType == BYTE_DATA) { if ((P->CurrentOpcode & 0x8) == 0) { P->SrcValue.Long = (ULONG)P->SrcValue.Byte; } else { P->SrcValue.Long = (ULONG)((LONG)((SCHAR)P->SrcValue.Byte)); } } else { if ((P->CurrentOpcode & 0x8) == 0) { P->SrcValue.Long = (ULONG)P->SrcValue.Word; } else { P->SrcValue.Long = (ULONG)((LONG)((SHORT)P->SrcValue.Word)); } } if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; P->SrcValue.Long &= 0xffff; } P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx); return TRUE; } ULONG XmFlagsRegister ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { // // Flags register source or destination with a stack source or // destination. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } if (P->FunctionIndex == X86_PUSH_OP) { XmSetSourceValue(P, (PVOID)(&P->AllFlags)); } else { XmSetDestinationValue(P, (PVOID)(&P->AllFlags)); } return TRUE; } ULONG XmPushImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Source; // // Push opcode with an immediate operand. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT); XmSetImmediateSourceValue(P, Source); return TRUE; } ULONG XmPopGeneral ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Pop opcode with a general specifier. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); XmSetDestinationValue(P, Operand); return TRUE; } ULONG XmImulImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Number; PVOID Operand; ULONG Source; // // Multiply signed opcode with a general specifier and an immediate // operand. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); Source = XmGetImmediateSourceValue(P, P->CurrentOpcode & SIGN_BIT); XmSetImmediateSourceValue(P, Source); XmSetDestinationValue(P, Operand); P->DstLong = (UNALIGNED ULONG *)(&P->Gpr[Number].Exx); return TRUE; } ULONG XmStringOperands ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { // // String opcode with implicit operands of eSI and eDI. // XmSetDataType(P); return TRUE; } ULONG XmEffectiveOffset ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Effective offset opcodes with general operand specifier. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } P->ComputeOffsetAddress = TRUE; Operand = XmEvaluateAddressSpecifier(P, &Number); if (P->RegisterOffsetAddress != FALSE) { longjmp(&P->JumpBuffer[0], XM_ILLEGAL_REGISTER_SPECIFIER); } P->SrcValue.Long = (ULONG)Operand; XmTraceSource(P, P->SrcValue.Long); P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx); return TRUE; } ULONG XmImmediateJump ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { // // Immediate long jump with the destination offset and new CS // segment value. The destination of the jump is stored in the // destination value and the new CS segment value is stored in // destination segment. // if (P->OpsizePrefixActive != FALSE) { P->DstValue.Long = XmGetLongImmediate(P); } else { P->DstValue.Long = XmGetWordImmediate(P); } P->DstSegment = XmGetWordImmediate(P); return TRUE; } ULONG XmImmediateEnter ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: enter Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { // // Enter operands with an allocation size and level number. // P->SrcValue.Long = XmGetWordImmediate(P); P->DstValue.Long = XmGetByteImmediate(P) & 0x1f; if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } return TRUE; } ULONG XmGeneralBitOffset ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Offset; ULONG Number; // // Bit test opcodes with a register bit offset and a memory or // register operand. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx)); if (P->RegisterOffsetAddress == FALSE) { if (P->DataType == LONG_DATA) { Offset = (P->SrcValue.Long >> 5) << 2; } else { Offset = (P->SrcValue.Long >> 4) << 1; } Operand = XmGetOffsetAddress(P, Offset + P->Offset); } if (P->DataType == LONG_DATA) { P->SrcValue.Long &= 0x1f; } else { P->SrcValue.Long &= 0xf; } XmSetDestinationValue(P, Operand); return TRUE; } ULONG XmShiftDouble ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: shld shrd Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; ULONG Source; // // Shift double operators with an immediate byte or cl shift count. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); if ((P->CurrentOpcode & 0x1) == 0) { Source = XmGetByteImmediate(P); } else { Source = P->Gpr[CX].Xl; } if (P->DataType == LONG_DATA) { P->Shift = (UCHAR)(Source & 0x1f); } else { P->Shift = (UCHAR)(Source & 0xf); } XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx)); XmSetDestinationValue(P, Operand); return TRUE; } ULONG XmPortImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Source; // // In/out opcodes with an immediate port and all other operands implied. // Source = (ULONG)XmGetByteImmediate(P); P->DataType = WORD_DATA; XmSetImmediateSourceValue(P, Source); XmSetDataType(P); return TRUE; } ULONG XmPortDX ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Source; // // In/out opcodes with a port in DX with all other operands implied. // Source = P->Gpr[DX].Xx; P->DataType = WORD_DATA; XmSetImmediateSourceValue(P, Source); XmSetDataType(P); return TRUE; } ULONG XmBitScanGeneral ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // Bit scan general opcodes with general operand specifier. // bit. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx); XmSetSourceValue(P, Operand); return TRUE; } ULONG XmByteImmediate ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: int xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { ULONG Source; // // int opcode with an immediate operand. // P->DataType = BYTE_DATA; Source = XmGetImmediateSourceValue(P, 0); XmSetImmediateSourceValue(P, Source); return TRUE; } ULONG XmXlatOpcode ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xlat Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Offset; // // xlat opcode with zero extended [AL] + [eBX] as the effective // address. // P->DataType = BYTE_DATA; if (P->OpaddrPrefixActive != FALSE) { Offset = P->Gpr[EBX].Exx + P->Gpr[AL].Xl; } else { Offset = P->Gpr[BX].Xx + P->Gpr[AL].Xl; } Operand = XmGetOffsetAddress(P, Offset); XmSetSourceValue(P, Operand); P->DstByte = (UCHAR UNALIGNED *)(&P->Gpr[AL].Xl); return TRUE; } ULONG XmGeneralRegister ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: bswap Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { PVOID Operand; ULONG Number; // // General register source and destination. // if (P->OpsizePrefixActive != FALSE) { P->DataType = LONG_DATA; } else { P->DataType = WORD_DATA; } Operand = XmEvaluateAddressSpecifier(P, &Number); if (P->RegisterOffsetAddress == FALSE) { longjmp(&P->JumpBuffer[0], XM_ILLEGAL_GENERAL_SPECIFIER); } XmSetSourceValue(P, (PVOID)(&P->Gpr[Number].Exx)); P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[Number].Exx); return TRUE; } ULONG XmOpcodeEscape ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: 2-byte escape Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of xx is returned as the function value. --*/ { // // Two byte opcode escape. // P->OpcodeControlTable = &XmOpcodeControlTable2[0]; #if defined(XM_DEBUG) P->OpcodeNameTable = &XmOpcodeNameTable2[0]; #endif return FALSE; } ULONG XmPrefixOpcode ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: CS: DS; ES: SS: FS: GS: lock adrsize opsize repz repnz Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of FALSE is returned as the function value. --*/ { // // Case on the function index. // switch (P->FunctionIndex) { // // Segment override prefix. // // Set the segment override prefix flags and the data segment // number. // case X86_ES_OP: case X86_CS_OP: case X86_SS_OP: case X86_DS_OP: case X86_FS_OP: case X86_GS_OP: P->SegmentPrefixActive = TRUE; P->DataSegment = P->FunctionIndex; XmTraceOverride(P); break; // // Lock prefix. // // Set the lock prefix flags. // case X86_LOCK_OP: P->LockPrefixActive = TRUE; break; // // Address size prefix. // // Set the address size prefix flag. // case X86_ADSZ_OP: P->OpaddrPrefixActive = TRUE; break; // // Operand size prefix. // // Set the operand size prefix flag. // case X86_OPSZ_OP: P->OpsizePrefixActive = TRUE; break; // // Repeat until ECX or ZF equals zero // // Set up repeat until ECX or ZF equals zero prefix flags. // case X86_REPZ_OP: P->RepeatPrefixActive = TRUE; P->RepeatZflag = 1; break; // // Repeat until ECX equals zero or ZF equals one. // // Set up repeat until ECX equals zero or ZF equals one prefix // flags. // case X86_REPNZ_OP: P->RepeatPrefixActive = TRUE; P->RepeatZflag = 0; break; } return FALSE; } ULONG XmNoOperands ( IN PRXM_CONTEXT P ) /*++ Routine Description: This function decodes x86 operand specifiers for the following opcodes: xxxxxx Arguments: P - Supplies a pointer to an emulator context structure. Return Value: A completion status of TRUE is returned as the function value. --*/ { return TRUE; }