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.

447 lines
10 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. getsetrg.c
  5. Abstract:
  6. This module implement the code necessary to get and set register values.
  7. These routines are used during the emulation of unaligned data references
  8. and floating point exceptions.
  9. Author:
  10. David N. Cutler (davec) 17-Jun-1991
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "ki.h"
  16. #include "ntfpia64.h"
  17. ULONGLONG
  18. KiGetRegisterValue (
  19. IN ULONG Register,
  20. IN PKEXCEPTION_FRAME ExceptionFrame,
  21. IN PKTRAP_FRAME TrapFrame
  22. )
  23. /*++
  24. Routine Description:
  25. This function is called to get the value of a register from the specified
  26. exception or trap frame.
  27. Arguments:
  28. Register - Supplies the number of the register whose value is to be
  29. returned. Integer registers are specified as 0 - 31 and floating
  30. registers are specified as 32 - 63.
  31. ExceptionFrame - Supplies a pointer to an exception frame.
  32. TrapFrame - Supplies a pointer to a trap frame.
  33. Return Value:
  34. The value of the specified register is returned as the function value.
  35. --*/
  36. {
  37. //
  38. // Dispatch on the register number.
  39. //
  40. if (Register == 0) {
  41. return 0;
  42. } else if (Register <= 3) {
  43. Register -= 1;
  44. return ( *(&TrapFrame->IntGp + Register) );
  45. } else if (Register <= 7) {
  46. Register -= 4;
  47. return ( *(&ExceptionFrame->IntS0 + Register) );
  48. } else if (Register <= 31) {
  49. Register -= 8;
  50. return ( *(&TrapFrame->IntV0 + Register) );
  51. }
  52. //
  53. // Register is the stacked register
  54. //
  55. // (R32 - R127)
  56. //
  57. {
  58. PULONGLONG UserBStore, KernelBStore;
  59. ULONG SizeOfCurrentFrame;
  60. SizeOfCurrentFrame = (ULONG)(TrapFrame->StIFS & 0x7F);
  61. Register = Register - 32;
  62. if (TrapFrame->PreviousMode == UserMode) {
  63. //
  64. // PreviousMode is user
  65. //
  66. UserBStore = (PULONGLONG) TrapFrame->RsBSP;
  67. do {
  68. UserBStore = UserBStore - 1;
  69. SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
  70. if (((ULONG_PTR) UserBStore & 0x1F8) == 0x1F8) {
  71. //
  72. // Adjust Bsp, by skipping RNAT
  73. //
  74. UserBStore = UserBStore - 1;
  75. }
  76. } while (Register < SizeOfCurrentFrame);
  77. return (*UserBStore);
  78. } else {
  79. //
  80. // PreviousMode is kernel
  81. //
  82. KernelBStore = (ULONGLONG *) TrapFrame->RsBSP;
  83. do {
  84. KernelBStore = KernelBStore - 1;
  85. SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
  86. if (((ULONG_PTR) KernelBStore & 0x1F8) == 0x1F8) {
  87. //
  88. // Adjust UserBsp, by skipping RNAT
  89. //
  90. KernelBStore = KernelBStore -1;
  91. }
  92. } while (Register < SizeOfCurrentFrame);
  93. return (*KernelBStore);
  94. }
  95. }
  96. }
  97. #define GET_NAT_OFFSET(addr) (USHORT)(((ULONG_PTR) (addr) >> 3) & 0x3F)
  98. #define CLEAR_NAT_BIT(Nats, Offset) Nats &= ~((ULONGLONG)1i64 << Offset)
  99. #define GET_NAT(Nats, addr) (UCHAR)((Nats >> GET_NAT_OFFSET(addr)) & 1)
  100. VOID
  101. KiSetRegisterValue (
  102. IN ULONG Register,
  103. IN ULONGLONG Value,
  104. OUT PKEXCEPTION_FRAME ExceptionFrame,
  105. OUT PKTRAP_FRAME TrapFrame
  106. )
  107. /*++
  108. Routine Description:
  109. This function is called to set the value of a register in the specified
  110. exception or trap frame.
  111. Arguments:
  112. Register - Supplies the number of the register whose value is to be
  113. stored. Integer registers are specified as 0 - 31 and floating
  114. registers are specified as 32 - 63.
  115. Value - Supplies the value to be stored in the specified register.
  116. ExceptionFrame - Supplies a pointer to an exception frame.
  117. TrapFrame - Supplies a pointer to a trap frame.
  118. Return Value:
  119. None.
  120. --*/
  121. {
  122. USHORT NatBitOffset;
  123. PULONGLONG UserBStore, KernelBStore, RnatAddress;
  124. ULONG SizeOfCurrentFrame;
  125. //
  126. // Dispatch on the register number.
  127. //
  128. if (Register == 0) {
  129. return;
  130. } else if (Register < 32) {
  131. if ((Register <= 3) || (Register >= 8)) {
  132. Register -= 1;
  133. *(&TrapFrame->IntGp + Register) = Value;
  134. NatBitOffset = GET_NAT_OFFSET(&TrapFrame->IntGp + Register);
  135. CLEAR_NAT_BIT(TrapFrame->IntNats, NatBitOffset);
  136. } else if ((Register >= 4) && (Register <= 7)) {
  137. Register -= 4;
  138. *(&ExceptionFrame->IntS0 + Register) = Value;
  139. NatBitOffset = GET_NAT_OFFSET(&ExceptionFrame->IntS0 + Register);
  140. CLEAR_NAT_BIT(ExceptionFrame->IntNats, NatBitOffset);
  141. }
  142. return;
  143. }
  144. //
  145. // Register is the stacked register
  146. //
  147. // (R32 - R127)
  148. //
  149. RnatAddress = NULL;
  150. SizeOfCurrentFrame = (ULONG)(TrapFrame->StIFS & 0x7F);
  151. Register = Register - 32;
  152. if (TrapFrame->PreviousMode == UserMode) {
  153. //
  154. // PreviousMode is user
  155. //
  156. UserBStore = (PULONGLONG) TrapFrame->RsBSP;
  157. do {
  158. UserBStore = UserBStore - 1;
  159. SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
  160. if (((ULONG_PTR) UserBStore & 0x1F8) == 0x1F8) {
  161. //
  162. // Adjust Bsp, by skipping RNAT
  163. //
  164. RnatAddress = UserBStore;
  165. UserBStore = UserBStore - 1;
  166. }
  167. } while (Register < SizeOfCurrentFrame);
  168. *UserBStore = Value;
  169. NatBitOffset = GET_NAT_OFFSET(UserBStore);
  170. if (RnatAddress == NULL) {
  171. CLEAR_NAT_BIT(TrapFrame->RsRNAT, NatBitOffset);
  172. } else {
  173. CLEAR_NAT_BIT(*RnatAddress, NatBitOffset);
  174. }
  175. } else {
  176. //
  177. // PreviousMode is kernel
  178. //
  179. ULONGLONG OriginalRsc, BspStore, Rnat;
  180. //
  181. // put RSE in lazy mode
  182. //
  183. OriginalRsc = __getReg(CV_IA64_RsRSC);
  184. __setReg(CV_IA64_RsRSC, RSC_KERNEL_DISABLED);
  185. KernelBStore = (ULONGLONG *) TrapFrame->RsBSP;
  186. do {
  187. KernelBStore = KernelBStore - 1;
  188. SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
  189. if (((ULONG_PTR) KernelBStore & 0x1F8) == 0x1F8) {
  190. //
  191. // Adjust UserBsp, by skipping RNAT
  192. //
  193. KernelBStore = KernelBStore -1;
  194. }
  195. } while (Register < SizeOfCurrentFrame);
  196. *KernelBStore = Value;
  197. NatBitOffset = GET_NAT_OFFSET(KernelBStore);
  198. RnatAddress = (PULONGLONG)((ULONGLONG)KernelBStore | RNAT_ALIGNMENT);
  199. //
  200. // disable interrupt and read bspstore & rnat
  201. //
  202. _disable();
  203. BspStore = __getReg(CV_IA64_RsBSPSTORE);
  204. Rnat = __getReg(CV_IA64_RsRNAT);
  205. if ((ULONGLONG)RnatAddress == ((ULONGLONG)BspStore | RNAT_ALIGNMENT)) {
  206. CLEAR_NAT_BIT(Rnat, NatBitOffset);
  207. __setReg(CV_IA64_RsRNAT, Rnat);
  208. } else {
  209. CLEAR_NAT_BIT(*RnatAddress, NatBitOffset);
  210. }
  211. //
  212. // enable interrupt and restore RSC setting
  213. //
  214. _enable();
  215. __setReg(CV_IA64_RsRSC, OriginalRsc);
  216. }
  217. }
  218. FLOAT128
  219. KiGetFloatRegisterValue (
  220. IN ULONG Register,
  221. IN struct _KEXCEPTION_FRAME *ExceptionFrame,
  222. IN struct _KTRAP_FRAME *TrapFrame
  223. )
  224. {
  225. if (Register == 0) {
  226. FLOAT128 t = {0ULL,0ULL};
  227. return t;
  228. } else if (Register == 1) {
  229. FLOAT128 t = {0x8000000000000000ULL,0x000000000000FFFFULL}; // low,high
  230. return t;
  231. } else if (Register <= 5) {
  232. Register -= 2;
  233. return ( *(&ExceptionFrame->FltS0 + Register) );
  234. } else if (Register <= 15) {
  235. Register -= 6;
  236. return ( *(&TrapFrame->FltT0 + Register) );
  237. } else if (Register <= 31) {
  238. Register -= 16;
  239. return ( *(&ExceptionFrame->FltS4 + Register) );
  240. } else {
  241. PKHIGHER_FP_VOLATILE HigherVolatile;
  242. HigherVolatile = GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase);
  243. Register -= 32;
  244. return ( *(&HigherVolatile->FltF32 + Register) );
  245. }
  246. }
  247. VOID
  248. KiSetFloatRegisterValue (
  249. IN ULONG Register,
  250. IN FLOAT128 Value,
  251. OUT struct _KEXCEPTION_FRAME *ExceptionFrame,
  252. OUT struct _KTRAP_FRAME *TrapFrame
  253. )
  254. {
  255. if (Register <= 1) {
  256. return;
  257. } else if (Register <= 5) {
  258. Register -= 2;
  259. *(&ExceptionFrame->FltS0 + Register) = Value;
  260. return;
  261. } else if (Register <= 15) {
  262. Register -= 6;
  263. *(&TrapFrame->FltT0 + Register) = Value;
  264. return;
  265. } else if (Register <= 31) {
  266. Register -= 16;
  267. *(&ExceptionFrame->FltS4 + Register) = Value;
  268. return;
  269. } else {
  270. PKHIGHER_FP_VOLATILE HigherVolatile;
  271. HigherVolatile = GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase);
  272. Register -= 32;
  273. *(&HigherVolatile->FltF32 + Register) = Value;
  274. TrapFrame->StIPSR &= ~(1i64 << PSR_MFH);
  275. TrapFrame->StIPSR |= (1i64 << PSR_DFH);
  276. return;
  277. }
  278. }
  279. VOID
  280. __cdecl
  281. KeSaveStateForHibernate(
  282. IN PKPROCESSOR_STATE ProcessorState
  283. )
  284. /*++
  285. Routine Description:
  286. Saves all processor-specific state that must be preserved
  287. across an S4 state (hibernation).
  288. Arguments:
  289. ProcessorState - Supplies the KPROCESSOR_STATE where the
  290. current CPU's state is to be saved.
  291. Return Value:
  292. None.
  293. --*/
  294. {
  295. //
  296. // BUGBUG John Vert (jvert) 4/30/1998
  297. // someone needs to implement this and probably put it in a more
  298. // appropriate file.
  299. }
  300. FLOAT128
  301. get_fp_register (
  302. IN ULONG Register,
  303. IN PVOID FpState
  304. )
  305. {
  306. return(KiGetFloatRegisterValue (
  307. Register,
  308. ((PFLOATING_POINT_STATE)FpState)->ExceptionFrame,
  309. ((PFLOATING_POINT_STATE)FpState)->TrapFrame
  310. ));
  311. }
  312. VOID
  313. set_fp_register (
  314. IN ULONG Register,
  315. IN FLOAT128 Value,
  316. IN PVOID FpState
  317. )
  318. {
  319. KiSetFloatRegisterValue (
  320. Register,
  321. Value,
  322. ((PFLOATING_POINT_STATE)FpState)->ExceptionFrame,
  323. ((PFLOATING_POINT_STATE)FpState)->TrapFrame
  324. );
  325. }