misc_32.S 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * This file contains miscellaneous low-level functions.
  4. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  5. *
  6. * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
  7. * and Paul Mackerras.
  8. *
  9. */
  10. #include <linux/export.h>
  11. #include <linux/sys.h>
  12. #include <asm/unistd.h>
  13. #include <asm/errno.h>
  14. #include <asm/reg.h>
  15. #include <asm/page.h>
  16. #include <asm/cache.h>
  17. #include <asm/cputable.h>
  18. #include <asm/mmu.h>
  19. #include <asm/ppc_asm.h>
  20. #include <asm/thread_info.h>
  21. #include <asm/asm-offsets.h>
  22. #include <asm/processor.h>
  23. #include <asm/bug.h>
  24. #include <asm/ptrace.h>
  25. #include <asm/feature-fixups.h>
  26. .text
  27. /*
  28. * This returns the high 64 bits of the product of two 64-bit numbers.
  29. */
  30. _GLOBAL(mulhdu)
  31. cmpwi r6,0
  32. cmpwi cr1,r3,0
  33. mr r10,r4
  34. mulhwu r4,r4,r5
  35. beq 1f
  36. mulhwu r0,r10,r6
  37. mullw r7,r10,r5
  38. addc r7,r0,r7
  39. addze r4,r4
  40. 1: beqlr cr1 /* all done if high part of A is 0 */
  41. mullw r9,r3,r5
  42. mulhwu r10,r3,r5
  43. beq 2f
  44. mullw r0,r3,r6
  45. mulhwu r8,r3,r6
  46. addc r7,r0,r7
  47. adde r4,r4,r8
  48. addze r10,r10
  49. 2: addc r4,r4,r9
  50. addze r3,r10
  51. blr
  52. /*
  53. * reloc_got2 runs through the .got2 section adding an offset
  54. * to each entry.
  55. */
  56. _GLOBAL(reloc_got2)
  57. mflr r11
  58. lis r7,__got2_start@ha
  59. addi r7,r7,__got2_start@l
  60. lis r8,__got2_end@ha
  61. addi r8,r8,__got2_end@l
  62. subf r8,r7,r8
  63. srwi. r8,r8,2
  64. beqlr
  65. mtctr r8
  66. bcl 20,31,$+4
  67. 1: mflr r0
  68. lis r4,1b@ha
  69. addi r4,r4,1b@l
  70. subf r0,r4,r0
  71. add r7,r0,r7
  72. 2: lwz r0,0(r7)
  73. add r0,r0,r3
  74. stw r0,0(r7)
  75. addi r7,r7,4
  76. bdnz 2b
  77. mtlr r11
  78. blr
  79. /*
  80. * call_setup_cpu - call the setup_cpu function for this cpu
  81. * r3 = data offset, r24 = cpu number
  82. *
  83. * Setup function is called with:
  84. * r3 = data offset
  85. * r4 = ptr to CPU spec (relocated)
  86. */
  87. _GLOBAL(call_setup_cpu)
  88. addis r4,r3,cur_cpu_spec@ha
  89. addi r4,r4,cur_cpu_spec@l
  90. lwz r4,0(r4)
  91. add r4,r4,r3
  92. lwz r5,CPU_SPEC_SETUP(r4)
  93. cmpwi 0,r5,0
  94. add r5,r5,r3
  95. beqlr
  96. mtctr r5
  97. bctr
  98. #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_PPC_BOOK3S_32)
  99. /* This gets called by via-pmu.c to switch the PLL selection
  100. * on 750fx CPU. This function should really be moved to some
  101. * other place (as most of the cpufreq code in via-pmu
  102. */
  103. _GLOBAL(low_choose_750fx_pll)
  104. /* Clear MSR:EE */
  105. mfmsr r7
  106. rlwinm r0,r7,0,17,15
  107. mtmsr r0
  108. /* If switching to PLL1, disable HID0:BTIC */
  109. cmplwi cr0,r3,0
  110. beq 1f
  111. mfspr r5,SPRN_HID0
  112. rlwinm r5,r5,0,27,25
  113. sync
  114. mtspr SPRN_HID0,r5
  115. isync
  116. sync
  117. 1:
  118. /* Calc new HID1 value */
  119. mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
  120. rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
  121. rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
  122. or r4,r4,r5
  123. mtspr SPRN_HID1,r4
  124. #ifdef CONFIG_SMP
  125. /* Store new HID1 image */
  126. lwz r6,TASK_CPU(r2)
  127. slwi r6,r6,2
  128. #else
  129. li r6, 0
  130. #endif
  131. addis r6,r6,nap_save_hid1@ha
  132. stw r4,nap_save_hid1@l(r6)
  133. /* If switching to PLL0, enable HID0:BTIC */
  134. cmplwi cr0,r3,0
  135. bne 1f
  136. mfspr r5,SPRN_HID0
  137. ori r5,r5,HID0_BTIC
  138. sync
  139. mtspr SPRN_HID0,r5
  140. isync
  141. sync
  142. 1:
  143. /* Return */
  144. mtmsr r7
  145. blr
  146. _GLOBAL(low_choose_7447a_dfs)
  147. /* Clear MSR:EE */
  148. mfmsr r7
  149. rlwinm r0,r7,0,17,15
  150. mtmsr r0
  151. /* Calc new HID1 value */
  152. mfspr r4,SPRN_HID1
  153. insrwi r4,r3,1,9 /* insert parameter into bit 9 */
  154. sync
  155. mtspr SPRN_HID1,r4
  156. sync
  157. isync
  158. /* Return */
  159. mtmsr r7
  160. blr
  161. #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_PPC_BOOK3S_32 */
  162. /*
  163. * Copy a whole page. We use the dcbz instruction on the destination
  164. * to reduce memory traffic (it eliminates the unnecessary reads of
  165. * the destination into cache). This requires that the destination
  166. * is cacheable.
  167. */
  168. #define COPY_16_BYTES \
  169. lwz r6,4(r4); \
  170. lwz r7,8(r4); \
  171. lwz r8,12(r4); \
  172. lwzu r9,16(r4); \
  173. stw r6,4(r3); \
  174. stw r7,8(r3); \
  175. stw r8,12(r3); \
  176. stwu r9,16(r3)
  177. _GLOBAL(copy_page)
  178. rlwinm r5, r3, 0, L1_CACHE_BYTES - 1
  179. addi r3,r3,-4
  180. 0: twnei r5, 0 /* WARN if r3 is not cache aligned */
  181. EMIT_WARN_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
  182. addi r4,r4,-4
  183. li r5,4
  184. #if MAX_COPY_PREFETCH > 1
  185. li r0,MAX_COPY_PREFETCH
  186. li r11,4
  187. mtctr r0
  188. 11: dcbt r11,r4
  189. addi r11,r11,L1_CACHE_BYTES
  190. bdnz 11b
  191. #else /* MAX_COPY_PREFETCH == 1 */
  192. dcbt r5,r4
  193. li r11,L1_CACHE_BYTES+4
  194. #endif /* MAX_COPY_PREFETCH */
  195. li r0,PAGE_SIZE/L1_CACHE_BYTES - MAX_COPY_PREFETCH
  196. crclr 4*cr0+eq
  197. 2:
  198. mtctr r0
  199. 1:
  200. dcbt r11,r4
  201. dcbz r5,r3
  202. COPY_16_BYTES
  203. #if L1_CACHE_BYTES >= 32
  204. COPY_16_BYTES
  205. #if L1_CACHE_BYTES >= 64
  206. COPY_16_BYTES
  207. COPY_16_BYTES
  208. #if L1_CACHE_BYTES >= 128
  209. COPY_16_BYTES
  210. COPY_16_BYTES
  211. COPY_16_BYTES
  212. COPY_16_BYTES
  213. #endif
  214. #endif
  215. #endif
  216. bdnz 1b
  217. beqlr
  218. crnot 4*cr0+eq,4*cr0+eq
  219. li r0,MAX_COPY_PREFETCH
  220. li r11,4
  221. b 2b
  222. EXPORT_SYMBOL(copy_page)
  223. /*
  224. * Extended precision shifts.
  225. *
  226. * Updated to be valid for shift counts from 0 to 63 inclusive.
  227. * -- Gabriel
  228. *
  229. * R3/R4 has 64 bit value
  230. * R5 has shift count
  231. * result in R3/R4
  232. *
  233. * ashrdi3: arithmetic right shift (sign propagation)
  234. * lshrdi3: logical right shift
  235. * ashldi3: left shift
  236. */
  237. _GLOBAL(__ashrdi3)
  238. subfic r6,r5,32
  239. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  240. addi r7,r5,32 # could be xori, or addi with -32
  241. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  242. rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
  243. sraw r7,r3,r7 # t2 = MSW >> (count-32)
  244. or r4,r4,r6 # LSW |= t1
  245. slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
  246. sraw r3,r3,r5 # MSW = MSW >> count
  247. or r4,r4,r7 # LSW |= t2
  248. blr
  249. EXPORT_SYMBOL(__ashrdi3)
  250. _GLOBAL(__ashldi3)
  251. subfic r6,r5,32
  252. slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
  253. addi r7,r5,32 # could be xori, or addi with -32
  254. srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
  255. slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
  256. or r3,r3,r6 # MSW |= t1
  257. slw r4,r4,r5 # LSW = LSW << count
  258. or r3,r3,r7 # MSW |= t2
  259. blr
  260. EXPORT_SYMBOL(__ashldi3)
  261. _GLOBAL(__lshrdi3)
  262. subfic r6,r5,32
  263. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  264. addi r7,r5,32 # could be xori, or addi with -32
  265. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  266. srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
  267. or r4,r4,r6 # LSW |= t1
  268. srw r3,r3,r5 # MSW = MSW >> count
  269. or r4,r4,r7 # LSW |= t2
  270. blr
  271. EXPORT_SYMBOL(__lshrdi3)
  272. /*
  273. * 64-bit comparison: __cmpdi2(s64 a, s64 b)
  274. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  275. */
  276. _GLOBAL(__cmpdi2)
  277. cmpw r3,r5
  278. li r3,1
  279. bne 1f
  280. cmplw r4,r6
  281. beqlr
  282. 1: li r3,0
  283. bltlr
  284. li r3,2
  285. blr
  286. EXPORT_SYMBOL(__cmpdi2)
  287. /*
  288. * 64-bit comparison: __ucmpdi2(u64 a, u64 b)
  289. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  290. */
  291. _GLOBAL(__ucmpdi2)
  292. cmplw r3,r5
  293. li r3,1
  294. bne 1f
  295. cmplw r4,r6
  296. beqlr
  297. 1: li r3,0
  298. bltlr
  299. li r3,2
  300. blr
  301. EXPORT_SYMBOL(__ucmpdi2)
  302. _GLOBAL(__bswapdi2)
  303. rotlwi r9,r4,8
  304. rotlwi r10,r3,8
  305. rlwimi r9,r4,24,0,7
  306. rlwimi r10,r3,24,0,7
  307. rlwimi r9,r4,24,16,23
  308. rlwimi r10,r3,24,16,23
  309. mr r3,r9
  310. mr r4,r10
  311. blr
  312. EXPORT_SYMBOL(__bswapdi2)
  313. #ifdef CONFIG_SMP
  314. _GLOBAL(start_secondary_resume)
  315. /* Reset stack */
  316. rlwinm r1, r1, 0, 0, 31 - THREAD_SHIFT
  317. addi r1,r1,THREAD_SIZE-STACK_FRAME_MIN_SIZE
  318. li r3,0
  319. stw r3,0(r1) /* Zero the stack frame pointer */
  320. bl start_secondary
  321. b .
  322. #endif /* CONFIG_SMP */