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.

182 lines
3.9 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. mulops.c
  5. Abstract:
  6. This module implements the code to emulate the div and idiv opcodes.
  7. Author:
  8. David N. Cutler (davec) 21-Sep-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "nthal.h"
  14. #include "emulate.h"
  15. VOID
  16. XmDivOp (
  17. IN PRXM_CONTEXT P
  18. )
  19. /*++
  20. Routine Description:
  21. This function emulates an unsigned div opcode.
  22. Arguments:
  23. P - Supplies a pointer to the emulation context structure.
  24. Return Value:
  25. None.
  26. --*/
  27. {
  28. UNALIGNED ULONG *DstHigh;
  29. ULONG Dividend;
  30. ULONG Divisor;
  31. ULARGE_INTEGER Large;
  32. ULONG Quotient;
  33. ULONG Remainder;
  34. //
  35. // Divide the unsigned operands and store result.
  36. //
  37. Divisor = P->SrcValue.Long;
  38. if (Divisor == 0) {
  39. longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO);
  40. }
  41. if (P->DataType == BYTE_DATA) {
  42. Dividend = (ULONG)P->Gpr[AX].Xx;
  43. Quotient = Dividend / Divisor;
  44. Remainder = Dividend % Divisor;
  45. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh);
  46. Dividend >>= 8;
  47. } else if (P->DataType == WORD_DATA) {
  48. Dividend = (P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx;
  49. Quotient = Dividend / Divisor;
  50. Remainder = Dividend % Divisor;
  51. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx);
  52. Dividend >>= 16;
  53. } else {
  54. Dividend = P->Gpr[EDX].Exx;
  55. Large.HighPart = Dividend;
  56. Large.LowPart = P->Gpr[EAX].Exx;
  57. Quotient = (ULONG)(Large.QuadPart / (ULONGLONG)Divisor);
  58. Remainder = (ULONG)(Large.QuadPart % (ULONGLONG)Divisor);
  59. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
  60. }
  61. if (Dividend >= Divisor) {
  62. longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
  63. }
  64. XmStoreResult(P, Quotient);
  65. P->DstLong = DstHigh;
  66. XmStoreResult(P, Remainder);
  67. return;
  68. }
  69. VOID
  70. XmIdivOp (
  71. IN PRXM_CONTEXT P
  72. )
  73. /*++
  74. Routine Description:
  75. This function emulates a signed idiv opcode.
  76. Arguments:
  77. P - Supplies a pointer to the emulation context structure.
  78. Return Value:
  79. None.
  80. --*/
  81. {
  82. UNALIGNED ULONG *DstHigh;
  83. LONG Dividend;
  84. LONG Divisor;
  85. LARGE_INTEGER Large;
  86. LONG Quotient;
  87. LONG Remainder;
  88. LARGE_INTEGER Result;
  89. //
  90. // Divide the signed operands and store result.
  91. //
  92. if (P->SrcValue.Long == 0) {
  93. longjmp(&P->JumpBuffer[0], XM_DIVIDE_BY_ZERO);
  94. }
  95. if (P->DataType == BYTE_DATA) {
  96. Divisor = (LONG)((SCHAR)P->SrcValue.Byte);
  97. Dividend = (LONG)((SHORT)P->Gpr[AX].Xx);
  98. Quotient = Dividend / Divisor;
  99. Remainder = Dividend % Divisor;
  100. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[AX].Xh);
  101. if ((Quotient >> 8) != ((Quotient << 24) >> 31)) {
  102. longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
  103. }
  104. Quotient &= 0xff;
  105. Remainder &= 0xff;
  106. } else if (P->DataType == WORD_DATA) {
  107. Divisor = (LONG)((SHORT)P->SrcValue.Word);
  108. Dividend = (LONG)((P->Gpr[DX].Xx << 16) | P->Gpr[AX].Xx);
  109. Quotient = Dividend / Divisor;
  110. Remainder = Dividend % Divisor;
  111. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[DX].Xx);
  112. if ((Quotient >> 16) != ((Quotient << 16) >> 31)) {
  113. longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
  114. }
  115. Quotient &= 0xffff;
  116. Remainder &= 0xfff;
  117. } else {
  118. Divisor = (LONG)(P->SrcValue.Long);
  119. Large.HighPart = (LONG)P->Gpr[EDX].Exx;
  120. Large.LowPart = P->Gpr[EAX].Exx;
  121. Result.QuadPart = Large.QuadPart / (LONGLONG)Divisor;
  122. Quotient = Result.LowPart;
  123. Remainder = (LONG)(Large.QuadPart % (LONGLONG)Divisor);
  124. DstHigh = (UNALIGNED ULONG *)(&P->Gpr[EDX].Exx);
  125. if (Result.HighPart != ((LONG)Result.LowPart >> 31)) {
  126. longjmp(&P->JumpBuffer[0], XM_DIVIDE_QUOTIENT_OVERFLOW);
  127. }
  128. }
  129. XmStoreResult(P, Quotient);
  130. P->DstLong = DstHigh;
  131. XmStoreResult(P, Remainder);
  132. return;
  133. }