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.

174 lines
4.6 KiB

  1. //
  2. // Copyright (c) 1996-1998 Microsoft Corporation
  3. //
  4. // Module Name:
  5. //
  6. // fphelp.s
  7. //
  8. // Abstract:
  9. //
  10. //
  11. // This module contains assembly code helpers for floating-point
  12. // emulation.
  13. //
  14. // Author:
  15. //
  16. // Barry Bond (barrybo) creation-date 26-Aug-1996
  17. //
  18. // Notes:
  19. //
  20. // Revision History:
  21. #include "kxalpha.h"
  22. #include "soalpha.h"
  23. #include "ksalpha.h"
  24. .rdata
  25. RoundingTable:
  26. .long (2 << 26), (1 << 26), (3 << 26), 0
  27. .text
  28. //
  29. // Define call frame used to exchange a floating point and integer register.
  30. //
  31. .struct 0
  32. FpCr: .space 8 // fpcr value
  33. .space 8 // ensure 16-byte stack alignment
  34. FpFrameLength: // length of stack frame
  35. NESTED_ENTRY(SetNativeRoundingMode, FpFrameLength, ra)
  36. //
  37. // Routine Description:
  38. //
  39. // Sets the native FPU to the specified x86 rounding mode.
  40. //
  41. // Arguments:
  42. //
  43. // a0 -- the x86 rounding mode (already guaranteed to be just 2 bits)
  44. //
  45. // Return Value:
  46. //
  47. // None
  48. //
  49. lda sp, -FpFrameLength(sp) // allocate stack frame
  50. PROLOGUE_END
  51. // map x86 rounding mode to Alpha rounding mode in a0
  52. lda t0, RoundingTable
  53. s4addl a0, t0, a0
  54. ldl a0, 0(a0)
  55. excb // wait for all pending traps
  56. mf_fpcr f0, f0, f0 // get current fpcr
  57. excb // block against new traps
  58. stt f0, FpCr(sp) // store fpcr to stack
  59. ldl t0, FpCr+4(sp) // load the high dword of fpcr into integer register
  60. ldiq t1, (3 << 26) // load immediate value
  61. bic t0, t1, t0 // t0 = t0 & ~(3 << 26)
  62. or t0, a0, t0 // t0 |= a0
  63. stl t0, FpCr+4(sp) // store new high dword of fpcr to stack
  64. ldt f0, FpCr(sp) // load into fp register
  65. mt_fpcr f0, f0, f0 // set new fpcr
  66. excb // block against new traps
  67. lda sp, FpFrameLength(sp)
  68. ret zero, (ra)
  69. .end SetNativeRoundingMode
  70. NESTED_ENTRY(GetNativeFPStatus, FpFrameLength, ra)
  71. //
  72. // Routine Description:
  73. //
  74. // Alpha-specific version of _statusfp()/_clearfp().
  75. //
  76. // Arguments:
  77. //
  78. // None.
  79. //
  80. // Return Value:
  81. //
  82. // Alpha-specific equivalent of _statusfp().
  83. //
  84. lda sp, -FpFrameLength(sp) // allocate stack frame
  85. PROLOGUE_END
  86. // this is _get_softfpcr, except the result ends up in t0
  87. GET_THREAD_ENVIRONMENT_BLOCK
  88. ldl t0, TeSoftFpcr(v0) // get current software fpcr value
  89. ldiq t3, 0x3e0000 // t3 = SW_FPCR_STATUS_MASK
  90. bic t0, t3, t1 // t1 = soft_fpcr & (~SW_FPCR_STATUS_MASK)
  91. // this is _set_softfpcr, except arg is in t1
  92. stl t1, TeSoftFpcr(v0) // store new software fpcr value
  93. excb // wait for all pending traps
  94. mf_fpcr f0, f0, f0 // get current fpcr
  95. excb // block against new traps
  96. stt f0, FpCr(sp) // store fpcr to stack
  97. ldq t3, FpCr(sp) // load fpcr into integer register
  98. ldiq t1, 0x1c01000000000000 // (FPCR_ROUND_MASK|FPCR_UNDERFLOW_TO_ZERO_ENABLE|FPCR_DENORMAL_OPERANDS_TO_ZERO_ENABLE)
  99. and t3, t1, t3 // t3 &= t1
  100. stq t3, FpCr(sp) // save integer version to stack
  101. ldt f0, FpCr(sp) // load it into floating-point reg
  102. mt_fpcr f0, f0, f0 // set new fpcr
  103. excb // block against new traps
  104. bis t0, zero, v0 // move original software fpcr into v0 for ret
  105. lda sp, FpFrameLength(sp)
  106. ret zero, (ra)
  107. .end GetNativeFPStatus
  108. NESTED_ENTRY(CastDoubleToInt64, FpFrameLength, ra)
  109. //
  110. // Arguments:
  111. //
  112. // f16 = double value to be cast
  113. //
  114. // Return Value:
  115. //
  116. // The double is cast to an __int64 value using Dynamic rounding.
  117. // NOTE: The Alpha C compiler generates chopped rounding always,
  118. // so "i64 = (double)-1.2" will give a different answer than
  119. // "i64 = CastDoubleToInt64(-1.2)" if the FP control word
  120. // is set to round towards -infinity.
  121. //
  122. lda sp, -FpFrameLength(sp) // allocate stack frame
  123. PROLOGUE_END
  124. // Convert IEEE floating to Integer.
  125. // Trapping: S - software
  126. // V - integer overflow enable
  127. // I - inexact enable
  128. // Rounding: D - dynamic
  129. cvttqsvid f16, f1
  130. // Store the int64 value onto the stack
  131. stt f1, FpCr(sp)
  132. // Load the int64 value into an integer register
  133. ldq v0, FpCr(sp)
  134. // Clean up the stack frame
  135. lda sp, FpFrameLength(sp)
  136. ret zero, (ra)
  137. .end CastDoubleToInt64