misc_32.S 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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 ([email protected])
  5. *
  6. * Largely rewritten by Cort Dougan ([email protected])
  7. * and Paul Mackerras.
  8. *
  9. */
  10. #include <linux/sys.h>
  11. #include <asm/unistd.h>
  12. #include <asm/errno.h>
  13. #include <asm/reg.h>
  14. #include <asm/page.h>
  15. #include <asm/cache.h>
  16. #include <asm/cputable.h>
  17. #include <asm/mmu.h>
  18. #include <asm/ppc_asm.h>
  19. #include <asm/thread_info.h>
  20. #include <asm/asm-offsets.h>
  21. #include <asm/processor.h>
  22. #include <asm/bug.h>
  23. #include <asm/ptrace.h>
  24. #include <asm/export.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. #ifdef CONFIG_40x
  163. /*
  164. * Do an IO access in real mode
  165. */
  166. _GLOBAL(real_readb)
  167. mfmsr r7
  168. rlwinm r0,r7,0,~MSR_DR
  169. sync
  170. mtmsr r0
  171. sync
  172. isync
  173. lbz r3,0(r3)
  174. sync
  175. mtmsr r7
  176. sync
  177. isync
  178. blr
  179. _ASM_NOKPROBE_SYMBOL(real_readb)
  180. /*
  181. * Do an IO access in real mode
  182. */
  183. _GLOBAL(real_writeb)
  184. mfmsr r7
  185. rlwinm r0,r7,0,~MSR_DR
  186. sync
  187. mtmsr r0
  188. sync
  189. isync
  190. stb r3,0(r4)
  191. sync
  192. mtmsr r7
  193. sync
  194. isync
  195. blr
  196. _ASM_NOKPROBE_SYMBOL(real_writeb)
  197. #endif /* CONFIG_40x */
  198. /*
  199. * Copy a whole page. We use the dcbz instruction on the destination
  200. * to reduce memory traffic (it eliminates the unnecessary reads of
  201. * the destination into cache). This requires that the destination
  202. * is cacheable.
  203. */
  204. #define COPY_16_BYTES \
  205. lwz r6,4(r4); \
  206. lwz r7,8(r4); \
  207. lwz r8,12(r4); \
  208. lwzu r9,16(r4); \
  209. stw r6,4(r3); \
  210. stw r7,8(r3); \
  211. stw r8,12(r3); \
  212. stwu r9,16(r3)
  213. _GLOBAL(copy_page)
  214. rlwinm r5, r3, 0, L1_CACHE_BYTES - 1
  215. addi r3,r3,-4
  216. 0: twnei r5, 0 /* WARN if r3 is not cache aligned */
  217. EMIT_WARN_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
  218. addi r4,r4,-4
  219. li r5,4
  220. #if MAX_COPY_PREFETCH > 1
  221. li r0,MAX_COPY_PREFETCH
  222. li r11,4
  223. mtctr r0
  224. 11: dcbt r11,r4
  225. addi r11,r11,L1_CACHE_BYTES
  226. bdnz 11b
  227. #else /* MAX_COPY_PREFETCH == 1 */
  228. dcbt r5,r4
  229. li r11,L1_CACHE_BYTES+4
  230. #endif /* MAX_COPY_PREFETCH */
  231. li r0,PAGE_SIZE/L1_CACHE_BYTES - MAX_COPY_PREFETCH
  232. crclr 4*cr0+eq
  233. 2:
  234. mtctr r0
  235. 1:
  236. dcbt r11,r4
  237. dcbz r5,r3
  238. COPY_16_BYTES
  239. #if L1_CACHE_BYTES >= 32
  240. COPY_16_BYTES
  241. #if L1_CACHE_BYTES >= 64
  242. COPY_16_BYTES
  243. COPY_16_BYTES
  244. #if L1_CACHE_BYTES >= 128
  245. COPY_16_BYTES
  246. COPY_16_BYTES
  247. COPY_16_BYTES
  248. COPY_16_BYTES
  249. #endif
  250. #endif
  251. #endif
  252. bdnz 1b
  253. beqlr
  254. crnot 4*cr0+eq,4*cr0+eq
  255. li r0,MAX_COPY_PREFETCH
  256. li r11,4
  257. b 2b
  258. EXPORT_SYMBOL(copy_page)
  259. /*
  260. * Extended precision shifts.
  261. *
  262. * Updated to be valid for shift counts from 0 to 63 inclusive.
  263. * -- Gabriel
  264. *
  265. * R3/R4 has 64 bit value
  266. * R5 has shift count
  267. * result in R3/R4
  268. *
  269. * ashrdi3: arithmetic right shift (sign propagation)
  270. * lshrdi3: logical right shift
  271. * ashldi3: left shift
  272. */
  273. _GLOBAL(__ashrdi3)
  274. subfic r6,r5,32
  275. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  276. addi r7,r5,32 # could be xori, or addi with -32
  277. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  278. rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
  279. sraw r7,r3,r7 # t2 = MSW >> (count-32)
  280. or r4,r4,r6 # LSW |= t1
  281. slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
  282. sraw r3,r3,r5 # MSW = MSW >> count
  283. or r4,r4,r7 # LSW |= t2
  284. blr
  285. EXPORT_SYMBOL(__ashrdi3)
  286. _GLOBAL(__ashldi3)
  287. subfic r6,r5,32
  288. slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
  289. addi r7,r5,32 # could be xori, or addi with -32
  290. srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
  291. slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
  292. or r3,r3,r6 # MSW |= t1
  293. slw r4,r4,r5 # LSW = LSW << count
  294. or r3,r3,r7 # MSW |= t2
  295. blr
  296. EXPORT_SYMBOL(__ashldi3)
  297. _GLOBAL(__lshrdi3)
  298. subfic r6,r5,32
  299. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  300. addi r7,r5,32 # could be xori, or addi with -32
  301. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  302. srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
  303. or r4,r4,r6 # LSW |= t1
  304. srw r3,r3,r5 # MSW = MSW >> count
  305. or r4,r4,r7 # LSW |= t2
  306. blr
  307. EXPORT_SYMBOL(__lshrdi3)
  308. /*
  309. * 64-bit comparison: __cmpdi2(s64 a, s64 b)
  310. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  311. */
  312. _GLOBAL(__cmpdi2)
  313. cmpw r3,r5
  314. li r3,1
  315. bne 1f
  316. cmplw r4,r6
  317. beqlr
  318. 1: li r3,0
  319. bltlr
  320. li r3,2
  321. blr
  322. EXPORT_SYMBOL(__cmpdi2)
  323. /*
  324. * 64-bit comparison: __ucmpdi2(u64 a, u64 b)
  325. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  326. */
  327. _GLOBAL(__ucmpdi2)
  328. cmplw r3,r5
  329. li r3,1
  330. bne 1f
  331. cmplw r4,r6
  332. beqlr
  333. 1: li r3,0
  334. bltlr
  335. li r3,2
  336. blr
  337. EXPORT_SYMBOL(__ucmpdi2)
  338. _GLOBAL(__bswapdi2)
  339. rotlwi r9,r4,8
  340. rotlwi r10,r3,8
  341. rlwimi r9,r4,24,0,7
  342. rlwimi r10,r3,24,0,7
  343. rlwimi r9,r4,24,16,23
  344. rlwimi r10,r3,24,16,23
  345. mr r3,r9
  346. mr r4,r10
  347. blr
  348. EXPORT_SYMBOL(__bswapdi2)
  349. #ifdef CONFIG_SMP
  350. _GLOBAL(start_secondary_resume)
  351. /* Reset stack */
  352. rlwinm r1, r1, 0, 0, 31 - THREAD_SHIFT
  353. addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
  354. li r3,0
  355. stw r3,0(r1) /* Zero the stack frame pointer */
  356. bl start_secondary
  357. b .
  358. #endif /* CONFIG_SMP */