mmx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/config.h>
  2. #include <linux/types.h>
  3. #include <linux/string.h>
  4. #include <linux/sched.h>
  5. #include <asm/i387.h>
  6. #include <asm/hardirq.h> 
  7. /*
  8.  * MMX 3DNow! library helper functions
  9.  *
  10.  * To do:
  11.  * We can use MMX just for prefetch in IRQ's. This may be a win. 
  12.  * (reported so on K6-III)
  13.  * We should use a better code neutral filler for the short jump
  14.  * leal ebx. [ebx] is apparently best for K6-2, but Cyrix ??
  15.  * We also want to clobber the filler register so we dont get any
  16.  * register forwarding stalls on the filler. 
  17.  *
  18.  * Add *user handling. Checksums are not a win with MMX on any CPU
  19.  * tested so far for any MMX solution figured.
  20.  *
  21.  * 22/09/2000 - Arjan van de Ven 
  22.  * Improved for non-egineering-sample Athlons 
  23.  *
  24.  */
  25.  
  26. void *_mmx_memcpy(void *to, const void *from, size_t len)
  27. {
  28. void *p;
  29. int i;
  30. if (in_interrupt())
  31. return __memcpy(to, from, len);
  32. p = to;
  33. i = len >> 6; /* len/64 */
  34. kernel_fpu_begin();
  35. __asm__ __volatile__ (
  36. "1: prefetch (%0)n" /* This set is 28 bytes */
  37. "   prefetch 64(%0)n"
  38. "   prefetch 128(%0)n"
  39. "   prefetch 192(%0)n"
  40. "   prefetch 256(%0)n"
  41. "2:  n"
  42. ".section .fixup, "ax"n"
  43. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  44. "   jmp 2bn"
  45. ".previousn"
  46. ".section __ex_table,"a"n"
  47. " .align 4n"
  48. " .long 1b, 3bn"
  49. ".previous"
  50. : : "r" (from) );
  51. for(; i>5; i--)
  52. {
  53. __asm__ __volatile__ (
  54. "1:  prefetch 320(%0)n"
  55. "2:  movq (%0), %%mm0n"
  56. "  movq 8(%0), %%mm1n"
  57. "  movq 16(%0), %%mm2n"
  58. "  movq 24(%0), %%mm3n"
  59. "  movq %%mm0, (%1)n"
  60. "  movq %%mm1, 8(%1)n"
  61. "  movq %%mm2, 16(%1)n"
  62. "  movq %%mm3, 24(%1)n"
  63. "  movq 32(%0), %%mm0n"
  64. "  movq 40(%0), %%mm1n"
  65. "  movq 48(%0), %%mm2n"
  66. "  movq 56(%0), %%mm3n"
  67. "  movq %%mm0, 32(%1)n"
  68. "  movq %%mm1, 40(%1)n"
  69. "  movq %%mm2, 48(%1)n"
  70. "  movq %%mm3, 56(%1)n"
  71. ".section .fixup, "ax"n"
  72. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  73. "   jmp 2bn"
  74. ".previousn"
  75. ".section __ex_table,"a"n"
  76. " .align 4n"
  77. " .long 1b, 3bn"
  78. ".previous"
  79. : : "r" (from), "r" (to) : "memory");
  80. from+=64;
  81. to+=64;
  82. }
  83. for(; i>0; i--)
  84. {
  85. __asm__ __volatile__ (
  86. "  movq (%0), %%mm0n"
  87. "  movq 8(%0), %%mm1n"
  88. "  movq 16(%0), %%mm2n"
  89. "  movq 24(%0), %%mm3n"
  90. "  movq %%mm0, (%1)n"
  91. "  movq %%mm1, 8(%1)n"
  92. "  movq %%mm2, 16(%1)n"
  93. "  movq %%mm3, 24(%1)n"
  94. "  movq 32(%0), %%mm0n"
  95. "  movq 40(%0), %%mm1n"
  96. "  movq 48(%0), %%mm2n"
  97. "  movq 56(%0), %%mm3n"
  98. "  movq %%mm0, 32(%1)n"
  99. "  movq %%mm1, 40(%1)n"
  100. "  movq %%mm2, 48(%1)n"
  101. "  movq %%mm3, 56(%1)n"
  102. : : "r" (from), "r" (to) : "memory");
  103. from+=64;
  104. to+=64;
  105. }
  106. /*
  107.  * Now do the tail of the block
  108.  */
  109. __memcpy(to, from, len&63);
  110. kernel_fpu_end();
  111. return p;
  112. }
  113. #ifdef CONFIG_MK7
  114. /*
  115.  * The K7 has streaming cache bypass load/store. The Cyrix III, K6 and
  116.  * other MMX using processors do not.
  117.  */
  118. static void fast_clear_page(void *page)
  119. {
  120. int i;
  121. kernel_fpu_begin();
  122. __asm__ __volatile__ (
  123. "  pxor %%mm0, %%mm0n" : :
  124. );
  125. for(i=0;i<4096/64;i++)
  126. {
  127. __asm__ __volatile__ (
  128. "  movntq %%mm0, (%0)n"
  129. "  movntq %%mm0, 8(%0)n"
  130. "  movntq %%mm0, 16(%0)n"
  131. "  movntq %%mm0, 24(%0)n"
  132. "  movntq %%mm0, 32(%0)n"
  133. "  movntq %%mm0, 40(%0)n"
  134. "  movntq %%mm0, 48(%0)n"
  135. "  movntq %%mm0, 56(%0)n"
  136. : : "r" (page) : "memory");
  137. page+=64;
  138. }
  139. /* since movntq is weakly-ordered, a "sfence" is needed to become
  140.  * ordered again.
  141.  */
  142. __asm__ __volatile__ (
  143. "  sfence n" : :
  144. );
  145. kernel_fpu_end();
  146. }
  147. static void fast_copy_page(void *to, void *from)
  148. {
  149. int i;
  150. kernel_fpu_begin();
  151. /* maybe the prefetch stuff can go before the expensive fnsave...
  152.  * but that is for later. -AV
  153.  */
  154. __asm__ __volatile__ (
  155. "1: prefetch (%0)n"
  156. "   prefetch 64(%0)n"
  157. "   prefetch 128(%0)n"
  158. "   prefetch 192(%0)n"
  159. "   prefetch 256(%0)n"
  160. "2:  n"
  161. ".section .fixup, "ax"n"
  162. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  163. "   jmp 2bn"
  164. ".previousn"
  165. ".section __ex_table,"a"n"
  166. " .align 4n"
  167. " .long 1b, 3bn"
  168. ".previous"
  169. : : "r" (from) );
  170. for(i=0; i<(4096-320)/64; i++)
  171. {
  172. __asm__ __volatile__ (
  173. "1: prefetch 320(%0)n"
  174. "2: movq (%0), %%mm0n"
  175. "   movntq %%mm0, (%1)n"
  176. "   movq 8(%0), %%mm1n"
  177. "   movntq %%mm1, 8(%1)n"
  178. "   movq 16(%0), %%mm2n"
  179. "   movntq %%mm2, 16(%1)n"
  180. "   movq 24(%0), %%mm3n"
  181. "   movntq %%mm3, 24(%1)n"
  182. "   movq 32(%0), %%mm4n"
  183. "   movntq %%mm4, 32(%1)n"
  184. "   movq 40(%0), %%mm5n"
  185. "   movntq %%mm5, 40(%1)n"
  186. "   movq 48(%0), %%mm6n"
  187. "   movntq %%mm6, 48(%1)n"
  188. "   movq 56(%0), %%mm7n"
  189. "   movntq %%mm7, 56(%1)n"
  190. ".section .fixup, "ax"n"
  191. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  192. "   jmp 2bn"
  193. ".previousn"
  194. ".section __ex_table,"a"n"
  195. " .align 4n"
  196. " .long 1b, 3bn"
  197. ".previous"
  198. : : "r" (from), "r" (to) : "memory");
  199. from+=64;
  200. to+=64;
  201. }
  202. for(i=(4096-320)/64; i<4096/64; i++)
  203. {
  204. __asm__ __volatile__ (
  205. "2: movq (%0), %%mm0n"
  206. "   movntq %%mm0, (%1)n"
  207. "   movq 8(%0), %%mm1n"
  208. "   movntq %%mm1, 8(%1)n"
  209. "   movq 16(%0), %%mm2n"
  210. "   movntq %%mm2, 16(%1)n"
  211. "   movq 24(%0), %%mm3n"
  212. "   movntq %%mm3, 24(%1)n"
  213. "   movq 32(%0), %%mm4n"
  214. "   movntq %%mm4, 32(%1)n"
  215. "   movq 40(%0), %%mm5n"
  216. "   movntq %%mm5, 40(%1)n"
  217. "   movq 48(%0), %%mm6n"
  218. "   movntq %%mm6, 48(%1)n"
  219. "   movq 56(%0), %%mm7n"
  220. "   movntq %%mm7, 56(%1)n"
  221. : : "r" (from), "r" (to) : "memory");
  222. from+=64;
  223. to+=64;
  224. }
  225. /* since movntq is weakly-ordered, a "sfence" is needed to become
  226.  * ordered again.
  227.  */
  228. __asm__ __volatile__ (
  229. "  sfence n" : :
  230. );
  231. kernel_fpu_end();
  232. }
  233. #else
  234. /*
  235.  * Generic MMX implementation without K7 specific streaming
  236.  */
  237.  
  238. static void fast_clear_page(void *page)
  239. {
  240. int i;
  241. kernel_fpu_begin();
  242. __asm__ __volatile__ (
  243. "  pxor %%mm0, %%mm0n" : :
  244. );
  245. for(i=0;i<4096/128;i++)
  246. {
  247. __asm__ __volatile__ (
  248. "  movq %%mm0, (%0)n"
  249. "  movq %%mm0, 8(%0)n"
  250. "  movq %%mm0, 16(%0)n"
  251. "  movq %%mm0, 24(%0)n"
  252. "  movq %%mm0, 32(%0)n"
  253. "  movq %%mm0, 40(%0)n"
  254. "  movq %%mm0, 48(%0)n"
  255. "  movq %%mm0, 56(%0)n"
  256. "  movq %%mm0, 64(%0)n"
  257. "  movq %%mm0, 72(%0)n"
  258. "  movq %%mm0, 80(%0)n"
  259. "  movq %%mm0, 88(%0)n"
  260. "  movq %%mm0, 96(%0)n"
  261. "  movq %%mm0, 104(%0)n"
  262. "  movq %%mm0, 112(%0)n"
  263. "  movq %%mm0, 120(%0)n"
  264. : : "r" (page) : "memory");
  265. page+=128;
  266. }
  267. kernel_fpu_end();
  268. }
  269. static void fast_copy_page(void *to, void *from)
  270. {
  271. int i;
  272. kernel_fpu_begin();
  273. __asm__ __volatile__ (
  274. "1: prefetch (%0)n"
  275. "   prefetch 64(%0)n"
  276. "   prefetch 128(%0)n"
  277. "   prefetch 192(%0)n"
  278. "   prefetch 256(%0)n"
  279. "2:  n"
  280. ".section .fixup, "ax"n"
  281. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  282. "   jmp 2bn"
  283. ".previousn"
  284. ".section __ex_table,"a"n"
  285. " .align 4n"
  286. " .long 1b, 3bn"
  287. ".previous"
  288. : : "r" (from) );
  289. for(i=0; i<4096/64; i++)
  290. {
  291. __asm__ __volatile__ (
  292. "1: prefetch 320(%0)n"
  293. "2: movq (%0), %%mm0n"
  294. "   movq 8(%0), %%mm1n"
  295. "   movq 16(%0), %%mm2n"
  296. "   movq 24(%0), %%mm3n"
  297. "   movq %%mm0, (%1)n"
  298. "   movq %%mm1, 8(%1)n"
  299. "   movq %%mm2, 16(%1)n"
  300. "   movq %%mm3, 24(%1)n"
  301. "   movq 32(%0), %%mm0n"
  302. "   movq 40(%0), %%mm1n"
  303. "   movq 48(%0), %%mm2n"
  304. "   movq 56(%0), %%mm3n"
  305. "   movq %%mm0, 32(%1)n"
  306. "   movq %%mm1, 40(%1)n"
  307. "   movq %%mm2, 48(%1)n"
  308. "   movq %%mm3, 56(%1)n"
  309. ".section .fixup, "ax"n"
  310. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  311. "   jmp 2bn"
  312. ".previousn"
  313. ".section __ex_table,"a"n"
  314. " .align 4n"
  315. " .long 1b, 3bn"
  316. ".previous"
  317. : : "r" (from), "r" (to) : "memory");
  318. from+=64;
  319. to+=64;
  320. }
  321. kernel_fpu_end();
  322. }
  323. #endif
  324. /*
  325.  * Favour MMX for page clear and copy. 
  326.  */
  327. static void slow_zero_page(void * page)
  328. {
  329. int d0, d1;
  330. __asm__ __volatile__( 
  331. "cldnt" 
  332. "rep ; stosl" 
  333. : "=&c" (d0), "=&D" (d1)
  334. :"a" (0),"1" (page),"0" (1024)
  335. :"memory");
  336. }
  337.  
  338. void mmx_clear_page(void * page)
  339. {
  340. if(in_interrupt())
  341. slow_zero_page(page);
  342. else
  343. fast_clear_page(page);
  344. }
  345. static void slow_copy_page(void *to, void *from)
  346. {
  347. int d0, d1, d2;
  348. __asm__ __volatile__( 
  349. "cldnt" 
  350. "rep ; movsl" 
  351. : "=&c" (d0), "=&D" (d1), "=&S" (d2) 
  352. : "0" (1024),"1" ((long) to),"2" ((long) from) 
  353. : "memory");
  354. }
  355.   
  356. void mmx_copy_page(void *to, void *from)
  357. {
  358. if(in_interrupt())
  359. slow_copy_page(to, from);
  360. else
  361. fast_copy_page(to, from);
  362. }