misc_32.S 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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/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. * We store the saved ksp_limit in the unused part
  29. * of the STACK_FRAME_OVERHEAD
  30. */
  31. _GLOBAL(call_do_softirq)
  32. mflr r0
  33. stw r0,4(r1)
  34. lwz r10,THREAD+KSP_LIMIT(r2)
  35. stw r3, THREAD+KSP_LIMIT(r2)
  36. stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
  37. mr r1,r3
  38. stw r10,8(r1)
  39. bl __do_softirq
  40. lwz r10,8(r1)
  41. lwz r1,0(r1)
  42. lwz r0,4(r1)
  43. stw r10,THREAD+KSP_LIMIT(r2)
  44. mtlr r0
  45. blr
  46. /*
  47. * void call_do_irq(struct pt_regs *regs, void *sp);
  48. */
  49. _GLOBAL(call_do_irq)
  50. mflr r0
  51. stw r0,4(r1)
  52. lwz r10,THREAD+KSP_LIMIT(r2)
  53. stw r4, THREAD+KSP_LIMIT(r2)
  54. stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
  55. mr r1,r4
  56. stw r10,8(r1)
  57. bl __do_irq
  58. lwz r10,8(r1)
  59. lwz r1,0(r1)
  60. lwz r0,4(r1)
  61. stw r10,THREAD+KSP_LIMIT(r2)
  62. mtlr r0
  63. blr
  64. /*
  65. * This returns the high 64 bits of the product of two 64-bit numbers.
  66. */
  67. _GLOBAL(mulhdu)
  68. cmpwi r6,0
  69. cmpwi cr1,r3,0
  70. mr r10,r4
  71. mulhwu r4,r4,r5
  72. beq 1f
  73. mulhwu r0,r10,r6
  74. mullw r7,r10,r5
  75. addc r7,r0,r7
  76. addze r4,r4
  77. 1: beqlr cr1 /* all done if high part of A is 0 */
  78. mullw r9,r3,r5
  79. mulhwu r10,r3,r5
  80. beq 2f
  81. mullw r0,r3,r6
  82. mulhwu r8,r3,r6
  83. addc r7,r0,r7
  84. adde r4,r4,r8
  85. addze r10,r10
  86. 2: addc r4,r4,r9
  87. addze r3,r10
  88. blr
  89. /*
  90. * reloc_got2 runs through the .got2 section adding an offset
  91. * to each entry.
  92. */
  93. _GLOBAL(reloc_got2)
  94. mflr r11
  95. lis r7,__got2_start@ha
  96. addi r7,r7,__got2_start@l
  97. lis r8,__got2_end@ha
  98. addi r8,r8,__got2_end@l
  99. subf r8,r7,r8
  100. srwi. r8,r8,2
  101. beqlr
  102. mtctr r8
  103. bl 1f
  104. 1: mflr r0
  105. lis r4,1b@ha
  106. addi r4,r4,1b@l
  107. subf r0,r4,r0
  108. add r7,r0,r7
  109. 2: lwz r0,0(r7)
  110. add r0,r0,r3
  111. stw r0,0(r7)
  112. addi r7,r7,4
  113. bdnz 2b
  114. mtlr r11
  115. blr
  116. /*
  117. * call_setup_cpu - call the setup_cpu function for this cpu
  118. * r3 = data offset, r24 = cpu number
  119. *
  120. * Setup function is called with:
  121. * r3 = data offset
  122. * r4 = ptr to CPU spec (relocated)
  123. */
  124. _GLOBAL(call_setup_cpu)
  125. addis r4,r3,cur_cpu_spec@ha
  126. addi r4,r4,cur_cpu_spec@l
  127. lwz r4,0(r4)
  128. add r4,r4,r3
  129. lwz r5,CPU_SPEC_SETUP(r4)
  130. cmpwi 0,r5,0
  131. add r5,r5,r3
  132. beqlr
  133. mtctr r5
  134. bctr
  135. #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_PPC_BOOK3S_32)
  136. /* This gets called by via-pmu.c to switch the PLL selection
  137. * on 750fx CPU. This function should really be moved to some
  138. * other place (as most of the cpufreq code in via-pmu
  139. */
  140. _GLOBAL(low_choose_750fx_pll)
  141. /* Clear MSR:EE */
  142. mfmsr r7
  143. rlwinm r0,r7,0,17,15
  144. mtmsr r0
  145. /* If switching to PLL1, disable HID0:BTIC */
  146. cmplwi cr0,r3,0
  147. beq 1f
  148. mfspr r5,SPRN_HID0
  149. rlwinm r5,r5,0,27,25
  150. sync
  151. mtspr SPRN_HID0,r5
  152. isync
  153. sync
  154. 1:
  155. /* Calc new HID1 value */
  156. mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
  157. rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
  158. rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
  159. or r4,r4,r5
  160. mtspr SPRN_HID1,r4
  161. #ifdef CONFIG_SMP
  162. /* Store new HID1 image */
  163. lwz r6,TASK_CPU(r2)
  164. slwi r6,r6,2
  165. #else
  166. li r6, 0
  167. #endif
  168. addis r6,r6,nap_save_hid1@ha
  169. stw r4,nap_save_hid1@l(r6)
  170. /* If switching to PLL0, enable HID0:BTIC */
  171. cmplwi cr0,r3,0
  172. bne 1f
  173. mfspr r5,SPRN_HID0
  174. ori r5,r5,HID0_BTIC
  175. sync
  176. mtspr SPRN_HID0,r5
  177. isync
  178. sync
  179. 1:
  180. /* Return */
  181. mtmsr r7
  182. blr
  183. _GLOBAL(low_choose_7447a_dfs)
  184. /* Clear MSR:EE */
  185. mfmsr r7
  186. rlwinm r0,r7,0,17,15
  187. mtmsr r0
  188. /* Calc new HID1 value */
  189. mfspr r4,SPRN_HID1
  190. insrwi r4,r3,1,9 /* insert parameter into bit 9 */
  191. sync
  192. mtspr SPRN_HID1,r4
  193. sync
  194. isync
  195. /* Return */
  196. mtmsr r7
  197. blr
  198. #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_PPC_BOOK3S_32 */
  199. #ifdef CONFIG_40x
  200. /*
  201. * Do an IO access in real mode
  202. */
  203. _GLOBAL(real_readb)
  204. mfmsr r7
  205. rlwinm r0,r7,0,~MSR_DR
  206. sync
  207. mtmsr r0
  208. sync
  209. isync
  210. lbz r3,0(r3)
  211. sync
  212. mtmsr r7
  213. sync
  214. isync
  215. blr
  216. _ASM_NOKPROBE_SYMBOL(real_readb)
  217. /*
  218. * Do an IO access in real mode
  219. */
  220. _GLOBAL(real_writeb)
  221. mfmsr r7
  222. rlwinm r0,r7,0,~MSR_DR
  223. sync
  224. mtmsr r0
  225. sync
  226. isync
  227. stb r3,0(r4)
  228. sync
  229. mtmsr r7
  230. sync
  231. isync
  232. blr
  233. _ASM_NOKPROBE_SYMBOL(real_writeb)
  234. #endif /* CONFIG_40x */
  235. /*
  236. * Copy a whole page. We use the dcbz instruction on the destination
  237. * to reduce memory traffic (it eliminates the unnecessary reads of
  238. * the destination into cache). This requires that the destination
  239. * is cacheable.
  240. */
  241. #define COPY_16_BYTES \
  242. lwz r6,4(r4); \
  243. lwz r7,8(r4); \
  244. lwz r8,12(r4); \
  245. lwzu r9,16(r4); \
  246. stw r6,4(r3); \
  247. stw r7,8(r3); \
  248. stw r8,12(r3); \
  249. stwu r9,16(r3)
  250. _GLOBAL(copy_page)
  251. rlwinm r5, r3, 0, L1_CACHE_BYTES - 1
  252. addi r3,r3,-4
  253. 0: twnei r5, 0 /* WARN if r3 is not cache aligned */
  254. EMIT_BUG_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
  255. addi r4,r4,-4
  256. li r5,4
  257. #if MAX_COPY_PREFETCH > 1
  258. li r0,MAX_COPY_PREFETCH
  259. li r11,4
  260. mtctr r0
  261. 11: dcbt r11,r4
  262. addi r11,r11,L1_CACHE_BYTES
  263. bdnz 11b
  264. #else /* MAX_COPY_PREFETCH == 1 */
  265. dcbt r5,r4
  266. li r11,L1_CACHE_BYTES+4
  267. #endif /* MAX_COPY_PREFETCH */
  268. li r0,PAGE_SIZE/L1_CACHE_BYTES - MAX_COPY_PREFETCH
  269. crclr 4*cr0+eq
  270. 2:
  271. mtctr r0
  272. 1:
  273. dcbt r11,r4
  274. dcbz r5,r3
  275. COPY_16_BYTES
  276. #if L1_CACHE_BYTES >= 32
  277. COPY_16_BYTES
  278. #if L1_CACHE_BYTES >= 64
  279. COPY_16_BYTES
  280. COPY_16_BYTES
  281. #if L1_CACHE_BYTES >= 128
  282. COPY_16_BYTES
  283. COPY_16_BYTES
  284. COPY_16_BYTES
  285. COPY_16_BYTES
  286. #endif
  287. #endif
  288. #endif
  289. bdnz 1b
  290. beqlr
  291. crnot 4*cr0+eq,4*cr0+eq
  292. li r0,MAX_COPY_PREFETCH
  293. li r11,4
  294. b 2b
  295. EXPORT_SYMBOL(copy_page)
  296. /*
  297. * Extended precision shifts.
  298. *
  299. * Updated to be valid for shift counts from 0 to 63 inclusive.
  300. * -- Gabriel
  301. *
  302. * R3/R4 has 64 bit value
  303. * R5 has shift count
  304. * result in R3/R4
  305. *
  306. * ashrdi3: arithmetic right shift (sign propagation)
  307. * lshrdi3: logical right shift
  308. * ashldi3: left shift
  309. */
  310. _GLOBAL(__ashrdi3)
  311. subfic r6,r5,32
  312. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  313. addi r7,r5,32 # could be xori, or addi with -32
  314. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  315. rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
  316. sraw r7,r3,r7 # t2 = MSW >> (count-32)
  317. or r4,r4,r6 # LSW |= t1
  318. slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
  319. sraw r3,r3,r5 # MSW = MSW >> count
  320. or r4,r4,r7 # LSW |= t2
  321. blr
  322. EXPORT_SYMBOL(__ashrdi3)
  323. _GLOBAL(__ashldi3)
  324. subfic r6,r5,32
  325. slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
  326. addi r7,r5,32 # could be xori, or addi with -32
  327. srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
  328. slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
  329. or r3,r3,r6 # MSW |= t1
  330. slw r4,r4,r5 # LSW = LSW << count
  331. or r3,r3,r7 # MSW |= t2
  332. blr
  333. EXPORT_SYMBOL(__ashldi3)
  334. _GLOBAL(__lshrdi3)
  335. subfic r6,r5,32
  336. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  337. addi r7,r5,32 # could be xori, or addi with -32
  338. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  339. srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
  340. or r4,r4,r6 # LSW |= t1
  341. srw r3,r3,r5 # MSW = MSW >> count
  342. or r4,r4,r7 # LSW |= t2
  343. blr
  344. EXPORT_SYMBOL(__lshrdi3)
  345. /*
  346. * 64-bit comparison: __cmpdi2(s64 a, s64 b)
  347. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  348. */
  349. _GLOBAL(__cmpdi2)
  350. cmpw r3,r5
  351. li r3,1
  352. bne 1f
  353. cmplw r4,r6
  354. beqlr
  355. 1: li r3,0
  356. bltlr
  357. li r3,2
  358. blr
  359. EXPORT_SYMBOL(__cmpdi2)
  360. /*
  361. * 64-bit comparison: __ucmpdi2(u64 a, u64 b)
  362. * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  363. */
  364. _GLOBAL(__ucmpdi2)
  365. cmplw r3,r5
  366. li r3,1
  367. bne 1f
  368. cmplw r4,r6
  369. beqlr
  370. 1: li r3,0
  371. bltlr
  372. li r3,2
  373. blr
  374. EXPORT_SYMBOL(__ucmpdi2)
  375. _GLOBAL(__bswapdi2)
  376. rotlwi r9,r4,8
  377. rotlwi r10,r3,8
  378. rlwimi r9,r4,24,0,7
  379. rlwimi r10,r3,24,0,7
  380. rlwimi r9,r4,24,16,23
  381. rlwimi r10,r3,24,16,23
  382. mr r3,r9
  383. mr r4,r10
  384. blr
  385. EXPORT_SYMBOL(__bswapdi2)
  386. #ifdef CONFIG_SMP
  387. _GLOBAL(start_secondary_resume)
  388. /* Reset stack */
  389. rlwinm r1, r1, 0, 0, 31 - THREAD_SHIFT
  390. addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
  391. li r3,0
  392. stw r3,0(r1) /* Zero the stack frame pointer */
  393. bl start_secondary
  394. b .
  395. #endif /* CONFIG_SMP */
  396. /*
  397. * This routine is just here to keep GCC happy - sigh...
  398. */
  399. _GLOBAL(__main)
  400. blr