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.

405 lines
8.6 KiB

  1. // TITLE("Alignment emulation")
  2. //++
  3. //
  4. //
  5. // Copyright (c) 1992 Digital Equipment Corporation
  6. //
  7. // Module Name:
  8. //
  9. // align.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements the code to complete unaligned access
  14. // emulation.
  15. //
  16. // Author:
  17. //
  18. // Joe Notarangelo 14-May-1992
  19. //
  20. // Environment:
  21. //
  22. // Kernel mode only.
  23. //
  24. // Revision History:
  25. //
  26. //--
  27. #include "ksalpha.h"
  28. //++
  29. //
  30. // UQUAD
  31. // KiEmulateLoadLong(
  32. // IN PULONG UnalignedAddress
  33. // )
  34. //
  35. // Routine Description:
  36. //
  37. // This routine returns the longword value stored at the unaligned
  38. // address passed in UnalignedAddress.
  39. //
  40. // Arguments:
  41. //
  42. // UnalignedAddress(a0) - Supplies a pointer to long data value.
  43. //
  44. // Return Value:
  45. //
  46. // The longword value at the address pointed to by UnalignedAddress.
  47. //
  48. //--
  49. LEAF_ENTRY(KiEmulateLoadLong)
  50. ldq_u t0, 0(a0) // get 1st quadword
  51. ldq_u v0, 3(a0) // get 2nd quadword
  52. extll t0, a0, t0 // extract bytes from low quadword
  53. extlh v0, a0, v0 // extract bytes from high quadword
  54. bis v0, t0, v0 // v0 = longword
  55. addl v0, zero, v0 // insure canonical longword form
  56. ret zero, (ra) // return
  57. .end KiEmulateLoadLong
  58. //++
  59. //
  60. // UQUAD
  61. // KiEmulateLoadQuad(
  62. // IN PUQUAD UnalignedAddress
  63. // )
  64. //
  65. // Routine Description:
  66. //
  67. // This routine returns the quadword value stored at the unaligned
  68. // address passed in UnalignedAddress.
  69. //
  70. // Arguments:
  71. //
  72. // UnalignedAddress(a0) - Supplies a pointer to quad data value.
  73. //
  74. // Return Value:
  75. //
  76. // The quadword value at the address pointed to by UnalignedAddress.
  77. //
  78. //--
  79. LEAF_ENTRY(KiEmulateLoadQuad)
  80. ldq_u t0, 0(a0) // get 1st quadword
  81. ldq_u v0, 7(a0) // get 2nd quadword
  82. extql t0, a0, t0 // extract bytes from low quadword
  83. extqh v0, a0, v0 // extract bytes from high quadword
  84. bis v0, t0, v0 // v0 = longword
  85. ret zero, (ra) // return
  86. .end KiEmulateLoadQuad
  87. //++
  88. //
  89. // VOID
  90. // KiEmulateStoreLong(
  91. // IN PULONG UnalignedAddress
  92. // IN UQUAD Data
  93. // )
  94. //
  95. // Routine Description:
  96. //
  97. // This routine stores the longword in Data to the UnalignedAddress.
  98. //
  99. // Arguments:
  100. //
  101. // UnalignedAddress(a0) - Supplies a pointer to longword destination.
  102. // Data(a1) - Supplies data value to store.
  103. //
  104. // Return Value:
  105. //
  106. // None.
  107. //
  108. //--
  109. LEAF_ENTRY(KiEmulateStoreLong)
  110. ldq_u t0, 0(a0) // get 1st quadword
  111. ldq_u t1, 3(a0) // get 2nd quadword
  112. inslh a1, a0, t2 // get bytes for high quadword
  113. insll a1, a0, t3 // get bytes for low quadword
  114. msklh t1, a0, t1 // clear corresponding bytes
  115. mskll t0, a0, t0 // clear corresponding bytes
  116. bis t1, t2, t1 // merge in bytes for high qw
  117. bis t0, t3, t0 // merge in bytes for low qw
  118. stq_u t1, 3(a0) // must store high first in case
  119. stq_u t0, 0(a0) // address was actually aligned
  120. ret zero, (ra) // return
  121. .end KiEmulateStoreLong
  122. //++
  123. //
  124. // VOID
  125. // KiEmulateStoreQuad(
  126. // IN PUQUAD UnalignedAddress
  127. // IN UQUAD Data
  128. // )
  129. //
  130. // Routine Description:
  131. //
  132. // This routine stores the quadword in Data to the UnalignedAddress.
  133. //
  134. // Arguments:
  135. //
  136. // UnalignedAddress(a0) - Supplies a pointer to quadword destination.
  137. // Data(a1) - Supplies the data value to store.
  138. //
  139. // Return Value:
  140. //
  141. // None.
  142. //
  143. //--
  144. LEAF_ENTRY(KiEmulateStoreQuad)
  145. ldq_u t0, 0(a0) // get 1st quadword
  146. ldq_u t1, 7(a0) // get 2nd quadword
  147. insqh a1, a0, t2 // get bytes for high quadword
  148. insql a1, a0, t3 // get bytes for low quadword
  149. mskqh t1, a0, t1 // clear corresponding bytes
  150. mskql t0, a0, t0 // clear corresponding bytes
  151. bis t1, t2, t1 // merge in bytes for high qw
  152. bis t0, t3, t0 // merge in bytes for low qw
  153. stq_u t1, 7(a0) // must store high first in case
  154. stq_u t0, 0(a0) // address was actually aligned
  155. ret zero, (ra) // return
  156. .end KiEmulateStoreQuad
  157. //++
  158. //
  159. // UQUAD
  160. // KiEmulateLoadFloatIEEESingle(
  161. // IN PULONG UnalignedAddress
  162. // )
  163. //
  164. // Routine Description:
  165. //
  166. // This routine returns the IEEE Single value stored at the unaligned
  167. // address passed in UnalignedAddress.
  168. //
  169. // N.B. The value is returned as the memory format T-formatted
  170. // interpretation of the read S-format value.
  171. //
  172. // Arguments:
  173. //
  174. // UnalignedAddress(a0) - Supplies a pointer to float single data.
  175. //
  176. // Return Value:
  177. //
  178. // The single float value at the address pointed to by UnalignedAddress.
  179. //
  180. //--
  181. .struct 0
  182. FlTemp: .space 8 // temporary memory
  183. .space 8 // filler for alignment
  184. FlFrameLength: // length of stack frame
  185. NESTED_ENTRY(KiEmulateLoadFloatIEEESingle, FlFrameLength, zero)
  186. lda sp, -FlFrameLength(sp) // allocate temp space
  187. PROLOGUE_END
  188. //
  189. // get the value into an integer register
  190. //
  191. ldq_u t0, 0(a0) // get 1st quadword
  192. ldq_u v0, 3(a0) // get 2nd quadword
  193. extll t0, a0, t0 // extract bytes from low quadword
  194. extlh v0, a0, v0 // extract bytes from high quadword
  195. bis v0, t0, v0 // v0 = longword
  196. //
  197. // v0 now is S memory format, however return from exception
  198. // sequence will restore floating registers as T memory format
  199. // convert v0 to T memory format
  200. stl v0, FlTemp(sp) // store bytes, S-mem-format
  201. lds f0, FlTemp(sp) // now S-reg-format
  202. stt f0, FlTemp(sp) // write as T-mem-format
  203. ldq v0, FlTemp(sp) // return as T-mem_format
  204. lda sp, FlFrameLength(sp) // deallocate stack frame
  205. ret zero, (ra) // return
  206. .end KiEmulateLoadFloatIEEESingle
  207. //++
  208. //
  209. // UQUAD
  210. // KiEmulateLoadFloatIEEEDouble(
  211. // IN PUQUAD UnalignedAddress
  212. // )
  213. //
  214. // Routine Description:
  215. //
  216. // This routine returns the quadword value stored at the unaligned
  217. // address passed in UnalignedAddress.
  218. //
  219. // Arguments:
  220. //
  221. // UnalignedAddress(a0) - Supplies a pointer to double float data value.
  222. //
  223. // Return Value:
  224. //
  225. // The double float value at the address pointed to by UnalignedAddress.
  226. //
  227. //--
  228. LEAF_ENTRY(KiEmulateLoadFloatIEEEDouble)
  229. ldq_u t0, 0(a0) // get 1st quadword
  230. ldq_u v0, 7(a0) // get 2nd quadword
  231. extql t0, a0, t0 // extract bytes from low quadword
  232. extqh v0, a0, v0 // extract bytes from high quadword
  233. bis v0, t0, v0 // v0 = longword
  234. ret zero, (ra) // return
  235. .end KiEmulateLoadFloatIEEEDouble
  236. //++
  237. //
  238. // VOID
  239. // KiEmulateStoreFloatIEEESingle(
  240. // IN PULONG UnalignedAddress
  241. // IN UQUAD Data
  242. // )
  243. //
  244. // Routine Description:
  245. //
  246. // This routine stores the float value in Data to the UnalignedAddress.
  247. //
  248. // Arguments:
  249. //
  250. // UnalignedAddress(a0) - Supplies a pointer to float destination.
  251. // Data(a1) - Supplies the data value to store.
  252. //
  253. // Return Value:
  254. //
  255. // None.
  256. //
  257. //--
  258. .struct 0
  259. FsTemp: .space 8 // temporary memory
  260. .space 8 // filler for alignment
  261. FsFrameLength: // length of stack frame
  262. NESTED_ENTRY(KiEmulateStoreFloatIEEESingle, FsFrameLength, zero)
  263. lda sp, -FsFrameLength(sp) // allocate stack space
  264. PROLOGUE_END
  265. //
  266. // a1 is an integer version of the T-memory format
  267. // convert it to integer version of S-memory format
  268. //
  269. stq a1, FsTemp(sp) // store bytes, T-mem-format
  270. ldt f10, FsTemp(sp) // load back in now in S-reg-format
  271. sts f10, FsTemp(sp) // now in S-mem-format
  272. ldl a1, FsTemp(sp) // now integer version of S-mem
  273. //
  274. // now problem is just to store an unaligned longword
  275. //
  276. ldq_u t0, 0(a0) // get 1st quadword
  277. ldq_u t1, 3(a0) // get 2nd quadword
  278. inslh a1, a0, t2 // get bytes for high quadword
  279. insll a1, a0, t3 // get bytes for low quadword
  280. msklh t1, a0, t1 // clear corresponding bytes
  281. mskll t0, a0, t0 // clear corresponding bytes
  282. bis t1, t2, t1 // merge in bytes for high qw
  283. bis t0, t3, t0 // merge in bytes for low qw
  284. stq_u t1, 3(a0) // must store high first in case
  285. stq_u t0, 0(a0) // was actually aligned
  286. lda sp, FsFrameLength(sp) // restore stack frame
  287. ret zero, (ra) // return
  288. .end KiEmulateStoreFloatIEEESingle
  289. //++
  290. //
  291. // VOID
  292. // KiEmulateStoreFloatIEEEDouble(
  293. // IN PUQUAD UnalignedAddress
  294. // IN UQUAD Data
  295. // )
  296. //
  297. // Routine Description:
  298. //
  299. // This routine stores the quadword in Data to the UnalignedAddress.
  300. //
  301. // Arguments:
  302. //
  303. // UnalignedAddress(a0) - Supplies a pointer to double float destination.
  304. // Data(a1) - Supplies the data value to store.
  305. //
  306. // Return Value:
  307. //
  308. // None.
  309. //
  310. //--
  311. LEAF_ENTRY(KiEmulateStoreFloatIEEEDouble)
  312. ldq_u t0, 0(a0) // get 1st quadword
  313. ldq_u t1, 7(a0) // get 2nd quadword
  314. insqh a1, a0, t2 // get bytes for high quadword
  315. insql a1, a0, t3 // get bytes for low quadword
  316. mskqh t1, a0, t1 // clear corresponding bytes
  317. mskql t0, a0, t0 // clear corresponding bytes
  318. bis t1, t2, t1 // merge in bytes for high qw
  319. bis t0, t3, t0 // merge in bytes for low qw
  320. stq_u t1, 7(a0) // must store high first in case
  321. stq_u t0, 0(a0) // was actually aligned
  322. ret zero, (ra) // return
  323. .end KiEmulateStoreFloatIEEEDouble