misc.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:22k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.misc.S 1.36 12/01/01 20:09:06 benh
  3.  */
  4. /*
  5.  * This file contains miscellaneous low-level functions.
  6.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  7.  *
  8.  * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
  9.  * and Paul Mackerras.
  10.  *
  11.  * This program is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU General Public License
  13.  * as published by the Free Software Foundation; either version
  14.  * 2 of the License, or (at your option) any later version.
  15.  *
  16.  */
  17. #include <linux/config.h>
  18. #include <linux/sys.h>
  19. #include <asm/unistd.h>
  20. #include <asm/errno.h>
  21. #include <asm/processor.h>
  22. #include <asm/page.h>
  23. #include <asm/cache.h>
  24. #include <asm/cputable.h>
  25. #include "ppc_asm.h"
  26. .text
  27. .align 5
  28. _GLOBAL(__delay)
  29. cmpwi 0,r3,0
  30. mtctr r3
  31. beqlr
  32. 1: bdnz 1b
  33. blr
  34. /*
  35.  * Returns (address we're running at) - (address we were linked at)
  36.  * for use before the text and data are mapped to KERNELBASE.
  37.  */
  38. _GLOBAL(reloc_offset)
  39. mflr r0
  40. bl 1f
  41. 1: mflr r3
  42. lis r4,1b@ha
  43. addi r4,r4,1b@l
  44. subf r3,r4,r3
  45. mtlr r0
  46. blr
  47. /*
  48.  * identify_cpu,
  49.  * called with r3 = data offset and r4 = CPU number
  50.  * doesn't change r3
  51.  */
  52. _GLOBAL(identify_cpu)
  53. addis r8,r3,cpu_specs@ha
  54. addi r8,r8,cpu_specs@l
  55. mfpvr r7
  56. 1:
  57. lwz r5,CPU_SPEC_PVR_MASK(r8)
  58. and r5,r5,r7
  59. lwz r6,CPU_SPEC_PVR_VALUE(r8)
  60. cmplw 0,r6,r5
  61. beq 1f
  62. addi r8,r8,CPU_SPEC_ENTRY_SIZE
  63. b 1b
  64. 1:
  65. addis r6,r3,cur_cpu_spec@ha
  66. addi r6,r6,cur_cpu_spec@l
  67. slwi r4,r4,2
  68. sub r8,r8,r3
  69. stwx r8,r4,r6
  70. blr
  71. /*
  72.  * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
  73.  * and writes nop's over sections of code that don't apply for this cpu.
  74.  * r3 = data offset (not changed)
  75.  */
  76. _GLOBAL(do_cpu_ftr_fixups)
  77. /* Get CPU 0 features */
  78. addis r6,r3,cur_cpu_spec@ha
  79. addi r6,r6,cur_cpu_spec@l
  80. lwz r4,0(r6)
  81. add r4,r4,r3
  82. lwz r4,CPU_SPEC_FEATURES(r4)
  83. /* Get the fixup table */
  84. addis r6,r3,__start___ftr_fixup@ha
  85. addi r6,r6,__start___ftr_fixup@l
  86. addis r7,r3,__stop___ftr_fixup@ha
  87. addi r7,r7,__stop___ftr_fixup@l
  88. /* Do the fixup */
  89. 1: cmplw 0,r6,r7
  90. bgelr
  91. addi r6,r6,16
  92. lwz r8,-16(r6) /* mask */
  93. and r8,r8,r4
  94. lwz r9,-12(r6) /* value */
  95. cmplw 0,r8,r9
  96. beq 1b
  97. lwz r8,-8(r6) /* section begin */
  98. lwz r9,-4(r6) /* section end */
  99. subf. r9,r8,r9
  100. beq 1b
  101. /* write nops over the section of code */
  102. /* todo: if large section, add a branch at the start of it */
  103. srwi r9,r9,2
  104. mtctr r9
  105. add r8,r8,r3
  106. lis r0,0x60000000@h /* nop */
  107. 3: stw r0,0(r8)
  108. andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
  109. beq 2f
  110. dcbst 0,r8 /* suboptimal, but simpler */
  111. sync
  112. icbi 0,r8
  113. 2: addi r8,r8,4
  114. bdnz 3b
  115. sync /* additional sync needed on g4 */
  116. isync
  117. b 1b
  118. /*
  119.  * call_setup_cpu - call the setup_cpu function for this cpu
  120.  * r3 = data offset, r24 = cpu number
  121.  *
  122.  * Don't change register layout, the setup function may rely
  123.  * on r5 containing a relocated pointer to the current cpu spec.
  124.  */
  125. _GLOBAL(call_setup_cpu)
  126. addis r5,r3,cur_cpu_spec@ha
  127. addi r5,r5,cur_cpu_spec@l
  128. slwi r4,r24,2
  129. lwzx r5,r4,r5
  130. add r5,r5,r3
  131. lwz r6,CPU_SPEC_SETUP(r5)
  132. add r6,r6,r3
  133. mtctr r6
  134. mr r3,r24
  135. bctr
  136. /* void __save_flags_ptr(unsigned long *flags) */
  137. _GLOBAL(__save_flags_ptr)
  138. mfmsr r4
  139. stw r4,0(r3)
  140. blr
  141. /* 
  142.  * Need these nops here for taking over save/restore to
  143.  * handle lost intrs
  144.  * -- Cort
  145.  */
  146. nop
  147. nop
  148. nop
  149. nop
  150. nop
  151. nop
  152. nop
  153. nop
  154. nop
  155. nop
  156. nop
  157. nop
  158. nop
  159. nop
  160. nop
  161. nop
  162. nop
  163. _GLOBAL(__save_flags_ptr_end)
  164. /* void __restore_flags(unsigned long flags) */
  165. _GLOBAL(__restore_flags)
  166. /*
  167.  * Just set/clear the MSR_EE bit through restore/flags but do not
  168.  * change anything else.  This is needed by the RT system and makes
  169.  * sense anyway.
  170.  *    -- Cort
  171.  */
  172. mfmsr  r4
  173. /* Copy all except the MSR_EE bit from r4 (current MSR value)
  174.    to r3.  This is the sort of thing the rlwimi instruction is
  175.    designed for.  -- paulus. */
  176. rlwimi r3,r4,0,17,15
  177.  /* Check if things are setup the way we want _already_. */
  178. cmpw 0,r3,r4
  179. beqlr
  180. 1: SYNC
  181. mtmsr r3
  182. SYNC
  183. blr
  184. nop
  185. nop
  186. nop
  187. nop
  188. nop
  189. nop
  190. nop
  191. nop
  192. nop
  193. nop
  194. nop
  195. nop
  196. nop
  197. nop
  198. nop
  199. nop
  200. nop
  201. nop
  202. nop
  203. _GLOBAL(__restore_flags_end)
  204. _GLOBAL(__cli)
  205. mfmsr r0 /* Get current interrupt state */
  206. rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
  207. rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
  208. SYNC /* Some chip revs have problems here... */
  209. mtmsr r0 /* Update machine state */
  210. blr /* Done */
  211. /* 
  212.  * Need these nops here for taking over save/restore to
  213.  * handle lost intrs
  214.  * -- Cort
  215.  */
  216. nop
  217. nop
  218. nop
  219. nop
  220. nop
  221. nop
  222. nop
  223. nop
  224. nop
  225. nop
  226. nop
  227. nop
  228. nop
  229. nop
  230. nop
  231. _GLOBAL(__cli_end)
  232. _GLOBAL(__sti)
  233. mfmsr r3 /* Get current state */
  234. ori r3,r3,MSR_EE /* Turn on 'EE' bit */
  235. SYNC /* Some chip revs have problems here... */
  236. mtmsr r3 /* Update machine state */
  237. blr
  238. /* 
  239.  * Need these nops here for taking over save/restore to
  240.  * handle lost intrs
  241.  * -- Cort
  242.  */
  243. nop
  244. nop
  245. nop
  246. nop
  247. nop
  248. nop
  249. nop
  250. nop
  251. nop
  252. nop
  253. nop
  254. nop
  255. nop
  256. nop
  257. nop
  258. nop
  259. _GLOBAL(__sti_end)
  260. /*
  261.  * complement mask on the msr then "or" some values on.
  262.  *     _nmask_and_or_msr(nmask, value_to_or)
  263.  */
  264. _GLOBAL(_nmask_and_or_msr)
  265. mfmsr r0 /* Get current msr */
  266. andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
  267. or r0,r0,r4 /* Or on the bits in r4 (second parm) */
  268. SYNC /* Some chip revs have problems here... */
  269. mtmsr r0 /* Update machine state */
  270. isync
  271. blr /* Done */
  272. /*
  273.  * Flush MMU TLB
  274.  */
  275. _GLOBAL(_tlbia)
  276. #if defined(CONFIG_SMP)
  277. mfmsr r10
  278. SYNC
  279. rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
  280. mtmsr r0
  281. SYNC
  282. lis r9,hash_table_lock@h
  283. ori r9,r9,hash_table_lock@l
  284. lwz r8,PROCESSOR(r2)
  285. oris r8,r8,10
  286. 10: lwarx r7,0,r9
  287. cmpi 0,r7,0
  288. bne- 10b
  289. stwcx. r8,0,r9
  290. bne- 10b
  291. #endif /* CONFIG_SMP */
  292. sync
  293. tlbia
  294. sync
  295. #ifdef CONFIG_SMP
  296. TLBSYNC
  297. li r0,0
  298. stw r0,0(r9) /* clear hash_table_lock */
  299. mtmsr r10
  300. SYNC
  301. #endif
  302. blr
  303. /*
  304.  * Flush MMU TLB for a particular address
  305.  */
  306. _GLOBAL(_tlbie)
  307. #if defined(CONFIG_SMP)
  308. mfmsr r10
  309. SYNC
  310. rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
  311. mtmsr r0
  312. SYNC
  313. lis r9,hash_table_lock@h
  314. ori r9,r9,hash_table_lock@l
  315. lwz r8,PROCESSOR(r2)
  316. oris r8,r8,11
  317. 10: lwarx r7,0,r9
  318. cmpi 0,r7,0
  319. bne- 10b
  320. stwcx. r8,0,r9
  321. bne- 10b
  322. eieio
  323. #endif /* CONFIG_SMP */
  324. tlbie r3
  325. sync
  326. #ifdef CONFIG_SMP
  327. TLBSYNC
  328. li r0,0
  329. stw r0,0(r9) /* clear hash_table_lock */
  330. mtmsr r10
  331. SYNC
  332. #endif
  333. blr
  334. /*
  335.  * Flush instruction cache.
  336.  * This is a no-op on the 601.
  337.  */
  338. _GLOBAL(flush_instruction_cache)
  339. #if defined(CONFIG_8xx)
  340. isync
  341. lis r5, IDC_INVALL@h
  342. mtspr IC_CST, r5
  343. #elif defined(CONFIG_4xx)
  344. lis r3, KERNELBASE@h
  345. iccci 0,r3
  346. #else
  347. mfspr r3,PVR
  348. rlwinm r3,r3,16,16,31
  349. cmpi 0,r3,1
  350. beqlr /* for 601, do nothing */
  351. /* 603/604 processor - use invalidate-all bit in HID0 */
  352. mfspr r3,HID0
  353. ori r3,r3,HID0_ICFI
  354. mtspr HID0,r3
  355. #endif /* CONFIG_8xx */
  356. isync
  357. blr
  358. /*
  359.  * Write any modified data cache blocks out to memory
  360.  * and invalidate the corresponding instruction cache blocks.
  361.  * This is a no-op on the 601.
  362.  *
  363.  * flush_icache_range(unsigned long start, unsigned long stop)
  364.  */
  365. _GLOBAL(flush_icache_range)
  366. mfspr r5,PVR
  367. rlwinm r5,r5,16,16,31
  368. cmpi 0,r5,1
  369. beqlr /* for 601, do nothing */
  370. li r5,L1_CACHE_LINE_SIZE-1
  371. andc r3,r3,r5
  372. subf r4,r3,r4
  373. add r4,r4,r5
  374. srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
  375. beqlr
  376. mtctr r4
  377. mr r6,r3
  378. 1: dcbst 0,r3
  379. addi r3,r3,L1_CACHE_LINE_SIZE
  380. bdnz 1b
  381. sync /* wait for dcbst's to get to ram */
  382. mtctr r4
  383. 2: icbi 0,r6
  384. addi r6,r6,L1_CACHE_LINE_SIZE
  385. bdnz 2b
  386. sync /* additional sync needed on g4 */
  387. isync
  388. blr
  389. /*
  390.  * Write any modified data cache blocks out to memory.
  391.  * Does not invalidate the corresponding cache lines (especially for
  392.  * any corresponding instruction cache).
  393.  *
  394.  * clean_dcache_range(unsigned long start, unsigned long stop)
  395.  */
  396. _GLOBAL(clean_dcache_range)
  397. li r5,L1_CACHE_LINE_SIZE-1
  398. andc r3,r3,r5
  399. subf r4,r3,r4
  400. add r4,r4,r5
  401. srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
  402. beqlr
  403. mtctr r4
  404. 1: dcbst 0,r3
  405. addi r3,r3,L1_CACHE_LINE_SIZE
  406. bdnz 1b
  407. sync /* wait for dcbst's to get to ram */
  408. blr
  409. /*
  410.  * Write any modified data cache blocks out to memory and invalidate them.
  411.  * Does not invalidate the corresponding instruction cache blocks.
  412.  *
  413.  * flush_dcache_range(unsigned long start, unsigned long stop)
  414.  */
  415. _GLOBAL(flush_dcache_range)
  416. li r5,L1_CACHE_LINE_SIZE-1
  417. andc r3,r3,r5
  418. subf r4,r3,r4
  419. add r4,r4,r5
  420. srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
  421. beqlr
  422. mtctr r4
  423. 1: dcbf 0,r3
  424. addi r3,r3,L1_CACHE_LINE_SIZE
  425. bdnz 1b
  426. sync /* wait for dcbst's to get to ram */
  427. blr
  428. /*
  429.  * Like above, but invalidate the D-cache.  This is used by the 8xx
  430.  * to invalidate the cache so the PPC core doesn't get stale data
  431.  * from the CPM (no cache snooping here :-).
  432.  *
  433.  * invalidate_dcache_range(unsigned long start, unsigned long stop)
  434.  */
  435. _GLOBAL(invalidate_dcache_range)
  436. li r5,L1_CACHE_LINE_SIZE-1
  437. andc r3,r3,r5
  438. subf r4,r3,r4
  439. add r4,r4,r5
  440. srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
  441. beqlr
  442. mtctr r4
  443. 1: dcbi 0,r3
  444. addi r3,r3,L1_CACHE_LINE_SIZE
  445. bdnz 1b
  446. sync /* wait for dcbi's to get to ram */
  447. blr
  448. /*
  449.  * Flush a particular page from the data cache to RAM.
  450.  * Note: this is necessary because the instruction cache does *not*
  451.  * snoop from the data cache.
  452.  * This is a no-op on the 601 which has a unified cache.
  453.  *
  454.  * void __flush_page_to_ram(void *page)
  455.  */
  456. _GLOBAL(__flush_page_to_ram)
  457. mfspr r5,PVR
  458. rlwinm r5,r5,16,16,31
  459. cmpi 0,r5,1
  460. beqlr /* for 601, do nothing */
  461. rlwinm r3,r3,0,0,19 /* Get page base address */
  462. li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
  463. mtctr r4
  464. mr r6,r3
  465. 0: dcbst 0,r3 /* Write line to ram */
  466. addi r3,r3,L1_CACHE_LINE_SIZE
  467. bdnz 0b
  468. sync
  469. mtctr r4
  470. 1: icbi 0,r6
  471. addi r6,r6,L1_CACHE_LINE_SIZE
  472. bdnz 1b
  473. sync
  474. isync
  475. blr
  476. /*
  477.  * Flush a particular page from the instruction cache.
  478.  * Note: this is necessary because the instruction cache does *not*
  479.  * snoop from the data cache.
  480.  * This is a no-op on the 601 which has a unified cache.
  481.  *
  482.  * void __flush_icache_page(void *page)
  483.  */
  484. _GLOBAL(__flush_icache_page)
  485. mfspr r5,PVR
  486. rlwinm r5,r5,16,16,31
  487. cmpi 0,r5,1
  488. beqlr /* for 601, do nothing */
  489. li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
  490. mtctr r4
  491. 1: icbi 0,r3
  492. addi r3,r3,L1_CACHE_LINE_SIZE
  493. bdnz 1b
  494. sync
  495. isync
  496. blr
  497. /*
  498.  * Clear a page using the dcbz instruction, which doesn't cause any
  499.  * memory traffic (except to write out any cache lines which get
  500.  * displaced).  This only works on cacheable memory.
  501.  */
  502. _GLOBAL(clear_page)
  503. li r0,4096/L1_CACHE_LINE_SIZE
  504. mtctr r0
  505. #ifdef CONFIG_8xx
  506. li r4, 0
  507. 1: stw r4, 0(r3)
  508. stw r4, 4(r3)
  509. stw r4, 8(r3)
  510. stw r4, 12(r3)
  511. #else
  512. 1: dcbz 0,r3
  513. #endif
  514. addi r3,r3,L1_CACHE_LINE_SIZE
  515. bdnz 1b
  516. blr
  517. /*
  518.  * Copy a whole page.  We use the dcbz instruction on the destination
  519.  * to reduce memory traffic (it eliminates the unnecessary reads of
  520.  * the destination into cache).  This requires that the destination
  521.  * is cacheable.
  522.  */
  523. #define COPY_16_BYTES
  524. lwz r6,4(r4);
  525. lwz r7,8(r4);
  526. lwz r8,12(r4);
  527. lwzu r9,16(r4);
  528. stw r6,4(r3);
  529. stw r7,8(r3);
  530. stw r8,12(r3);
  531. stwu r9,16(r3)
  532. _GLOBAL(copy_page)
  533. addi r3,r3,-4
  534. addi r4,r4,-4
  535. li r5,4
  536. #ifndef CONFIG_8xx
  537. #if MAX_L1_COPY_PREFETCH > 1
  538. li r0,MAX_L1_COPY_PREFETCH
  539. li r11,4
  540. mtctr r0
  541. 11: dcbt r11,r4
  542. addi r11,r11,L1_CACHE_LINE_SIZE
  543. bdnz 11b
  544. #else /* MAX_L1_COPY_PREFETCH == 1 */
  545. dcbt r5,r4
  546. li r11,L1_CACHE_LINE_SIZE+4
  547. #endif /* MAX_L1_COPY_PREFETCH */
  548. #endif /* CONFIG_8xx */
  549. li r0,4096/L1_CACHE_LINE_SIZE
  550. mtctr r0
  551. 1:
  552. #ifndef CONFIG_8xx
  553. dcbt r11,r4
  554. dcbz r5,r3
  555. #endif
  556. COPY_16_BYTES
  557. #if L1_CACHE_LINE_SIZE >= 32
  558. COPY_16_BYTES
  559. #if L1_CACHE_LINE_SIZE >= 64
  560. COPY_16_BYTES
  561. COPY_16_BYTES
  562. #if L1_CACHE_LINE_SIZE >= 128
  563. COPY_16_BYTES
  564. COPY_16_BYTES
  565. COPY_16_BYTES
  566. COPY_16_BYTES
  567. #endif
  568. #endif
  569. #endif
  570. bdnz 1b
  571. blr
  572. /*
  573.  * Atomic [test&set] exchange
  574.  *
  575.  * unsigned long xchg_u32(void *ptr, unsigned long val)
  576.  * Changes the memory location '*ptr' to be val and returns
  577.  * the previous value stored there.
  578.  */
  579. _GLOBAL(xchg_u32)
  580. mr r5,r3 /* Save pointer */
  581. 10: lwarx r3,0,r5 /* Fetch old value & reserve */
  582. stwcx. r4,0,r5 /* Update with new value */
  583. bne- 10b /* Retry if "reservation" (i.e. lock) lost */
  584. blr
  585. /*
  586.  * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
  587.  * void atomic_set_mask(atomic_t mask, atomic_t *addr);
  588.  */
  589. _GLOBAL(atomic_clear_mask)
  590. 10: lwarx r5,0,r4
  591. andc r5,r5,r3
  592. stwcx. r5,0,r4
  593. bne- 10b
  594. blr
  595. _GLOBAL(atomic_set_mask)
  596. 10: lwarx r5,0,r4
  597. or r5,r5,r3
  598. stwcx. r5,0,r4
  599. bne- 10b
  600. blr
  601. /*
  602.  * I/O string operations
  603.  *
  604.  * insb(port, buf, len)
  605.  * outsb(port, buf, len)
  606.  * insw(port, buf, len)
  607.  * outsw(port, buf, len)
  608.  * insl(port, buf, len)
  609.  * outsl(port, buf, len)
  610.  * insw_ns(port, buf, len)
  611.  * outsw_ns(port, buf, len)
  612.  * insl_ns(port, buf, len)
  613.  * outsl_ns(port, buf, len)
  614.  *
  615.  * The *_ns versions don't do byte-swapping.
  616.  */
  617. _GLOBAL(_insb)
  618. cmpwi 0,r5,0
  619. mtctr r5
  620. subi r4,r4,1
  621. blelr-
  622. 00: lbz r5,0(r3)
  623. eieio
  624. stbu r5,1(r4)
  625. bdnz 00b
  626. blr
  627. _GLOBAL(_outsb)
  628. cmpwi 0,r5,0
  629. mtctr r5
  630. subi r4,r4,1
  631. blelr-
  632. 00: lbzu r5,1(r4)
  633. stb r5,0(r3)
  634. eieio
  635. bdnz 00b
  636. blr
  637. _GLOBAL(_insw)
  638. cmpwi 0,r5,0
  639. mtctr r5
  640. subi r4,r4,2
  641. blelr-
  642. 00: lhbrx r5,0,r3
  643. eieio
  644. sthu r5,2(r4)
  645. bdnz 00b
  646. blr
  647. _GLOBAL(_outsw)
  648. cmpwi 0,r5,0
  649. mtctr r5
  650. subi r4,r4,2
  651. blelr-
  652. 00: lhzu r5,2(r4)
  653. eieio
  654. sthbrx r5,0,r3
  655. bdnz 00b
  656. blr
  657. _GLOBAL(_insl)
  658. cmpwi 0,r5,0
  659. mtctr r5
  660. subi r4,r4,4
  661. blelr-
  662. 00: lwbrx r5,0,r3
  663. eieio
  664. stwu r5,4(r4)
  665. bdnz 00b
  666. blr
  667. _GLOBAL(_outsl)
  668. cmpwi 0,r5,0
  669. mtctr r5
  670. subi r4,r4,4
  671. blelr-
  672. 00: lwzu r5,4(r4)
  673. stwbrx r5,0,r3
  674. eieio
  675. bdnz 00b
  676. blr
  677. _GLOBAL(ide_insw)
  678. _GLOBAL(_insw_ns)
  679. cmpwi 0,r5,0
  680. mtctr r5
  681. subi r4,r4,2
  682. blelr-
  683. 00: lhz r5,0(r3)
  684. eieio
  685. sthu r5,2(r4)
  686. bdnz 00b
  687. blr
  688. _GLOBAL(ide_outsw)
  689. _GLOBAL(_outsw_ns)
  690. cmpwi 0,r5,0
  691. mtctr r5
  692. subi r4,r4,2
  693. blelr-
  694. 00: lhzu r5,2(r4)
  695. sth r5,0(r3)
  696. eieio
  697. bdnz 00b
  698. blr
  699. _GLOBAL(_insl_ns)
  700. cmpwi 0,r5,0
  701. mtctr r5
  702. subi r4,r4,4
  703. blelr-
  704. 00: lwz r5,0(r3)
  705. eieio
  706. stwu r5,4(r4)
  707. bdnz 00b
  708. blr
  709. _GLOBAL(_outsl_ns)
  710. cmpwi 0,r5,0
  711. mtctr r5
  712. subi r4,r4,4
  713. blelr-
  714. 00: lwzu r5,4(r4)
  715. stw r5,0(r3)
  716. eieio
  717. bdnz 00b
  718. blr
  719. /*
  720.  * Extended precision shifts.
  721.  * 
  722.  * Updated to be valid for shift counts from 0 to 63 inclusive.
  723.  * -- Gabriel
  724.  *
  725.  * R3/R4 has 64 bit value
  726.  * R5    has shift count
  727.  * result in R3/R4
  728.  *
  729.  *  ashrdi3: arithmetic right shift (sign propagation)     
  730.  *  lshrdi3: logical right shift
  731.  *  ashldi3: left shift
  732.  */
  733. _GLOBAL(__ashrdi3)
  734. subfic r6,r5,32
  735. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  736. addi r7,r5,32 # could be xori, or addi with -32
  737. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  738. rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
  739. sraw r7,r3,r7 # t2 = MSW >> (count-32)
  740. or r4,r4,r6 # LSW |= t1
  741. slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
  742. sraw r3,r3,r5 # MSW = MSW >> count
  743. or r4,r4,r7 # LSW |= t2
  744. blr
  745. _GLOBAL(__ashldi3)
  746. subfic r6,r5,32
  747. slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
  748. addi r7,r5,32 # could be xori, or addi with -32
  749. srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
  750. slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
  751. or r3,r3,r6 # MSW |= t1
  752. slw r4,r4,r5 # LSW = LSW << count
  753. or r3,r3,r7 # MSW |= t2
  754. blr
  755. _GLOBAL(__lshrdi3)
  756. subfic r6,r5,32
  757. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  758. addi r7,r5,32 # could be xori, or addi with -32
  759. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  760. srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
  761. or r4,r4,r6 # LSW |= t1
  762. srw r3,r3,r5 # MSW = MSW >> count
  763. or r4,r4,r7 # LSW |= t2 
  764. blr
  765. _GLOBAL(abs)
  766. srawi r4,r3,31
  767. xor r3,r3,r4
  768. sub r3,r3,r4
  769. blr
  770. _GLOBAL(_get_SP)
  771. mr r3,r1 /* Close enough */
  772. blr
  773. /*
  774.  * These are used in the alignment trap handler when emulating
  775.  * single-precision loads and stores.
  776.  * We restore and save the fpscr so the task gets the same result
  777.  * and exceptions as if the cpu had performed the load or store.
  778.  */
  779. #if defined(CONFIG_4xx)
  780. _GLOBAL(cvt_fd)
  781. lfs 0,0(r3)
  782. stfd 0,0(r4)
  783. blr
  784. _GLOBAL(cvt_df)
  785. lfd 0,0(r3)
  786. stfs 0,0(r4)
  787. blr
  788. #else
  789. _GLOBAL(cvt_fd)
  790. lfd 0,-4(r5) /* load up fpscr value */
  791. mtfsf 0xff,0
  792. lfs 0,0(r3)
  793. stfd 0,0(r4)
  794. mffs 0 /* save new fpscr value */
  795. stfd 0,-4(r5)
  796. blr
  797. _GLOBAL(cvt_df)
  798. lfd 0,-4(r5) /* load up fpscr value */
  799. mtfsf 0xff,0
  800. lfd 0,0(r3)
  801. stfs 0,0(r4)
  802. mffs 0 /* save new fpscr value */
  803. stfd 0,-4(r5)
  804. blr
  805. #endif
  806. /*
  807.  * Create a kernel thread
  808.  *   kernel_thread(fn, arg, flags)
  809.  */
  810. _GLOBAL(kernel_thread)
  811. mr r6,r3 /* function */
  812. ori r3,r5,CLONE_VM /* flags */
  813. li r0,__NR_clone
  814. sc
  815. cmpi 0,r3,0 /* parent or child? */
  816. bnelr /* return if parent */
  817. li r0,0 /* make top-level stack frame */
  818. stwu r0,-16(r1)
  819. mtlr r6              /* fn addr in lr */
  820. mr r3,r4         /* load arg and call fn */
  821. blrl
  822. li r0,__NR_exit /* exit after child exits */
  823. li r3,0
  824. sc
  825. /*
  826.  * This routine is just here to keep GCC happy - sigh...
  827.  */
  828. _GLOBAL(__main)
  829. blr
  830. #define SYSCALL(name) 
  831. _GLOBAL(name) 
  832. li r0,__NR_##name; 
  833. sc; 
  834. bnslr; 
  835. lis r4,errno@ha; 
  836. stw r3,errno@l(r4); 
  837. li r3,-1; 
  838. blr
  839. #define __NR__exit __NR_exit
  840. SYSCALL(sync)
  841. SYSCALL(setsid)
  842. SYSCALL(write)
  843. SYSCALL(dup)
  844. SYSCALL(execve)
  845. SYSCALL(open)
  846. SYSCALL(close)
  847. SYSCALL(waitpid)
  848. SYSCALL(fork)
  849. SYSCALL(delete_module)
  850. SYSCALL(_exit)
  851. SYSCALL(lseek)
  852. SYSCALL(read)
  853. /* Why isn't this a) automatic, b) written in 'C'? */
  854. .data
  855. .align 4
  856. _GLOBAL(sys_call_table)
  857. .long sys_ni_syscall /* 0  -  old "setup()" system call */
  858. .long sys_exit
  859. .long sys_fork
  860. .long sys_read
  861. .long sys_write
  862. .long sys_open /* 5 */
  863. .long sys_close
  864. .long sys_waitpid
  865. .long sys_creat
  866. .long sys_link
  867. .long sys_unlink /* 10 */
  868. .long sys_execve
  869. .long sys_chdir
  870. .long sys_time
  871. .long sys_mknod
  872. .long sys_chmod /* 15 */
  873. .long sys_lchown
  874. .long sys_ni_syscall /* old break syscall holder */
  875. .long sys_stat
  876. .long sys_lseek
  877. .long sys_getpid /* 20 */
  878. .long sys_mount
  879. .long sys_oldumount
  880. .long sys_setuid
  881. .long sys_getuid
  882. .long sys_stime /* 25 */
  883. .long sys_ptrace
  884. .long sys_alarm
  885. .long sys_fstat
  886. .long sys_pause
  887. .long sys_utime /* 30 */
  888. .long sys_ni_syscall /* old stty syscall holder */
  889. .long sys_ni_syscall /* old gtty syscall holder */
  890. .long sys_access
  891. .long sys_nice
  892. .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
  893. .long sys_sync
  894. .long sys_kill
  895. .long sys_rename
  896. .long sys_mkdir
  897. .long sys_rmdir /* 40 */
  898. .long sys_dup
  899. .long sys_pipe
  900. .long sys_times
  901. .long sys_ni_syscall /* old prof syscall holder */
  902. .long sys_brk /* 45 */
  903. .long sys_setgid
  904. .long sys_getgid
  905. .long sys_signal
  906. .long sys_geteuid
  907. .long sys_getegid /* 50 */
  908. .long sys_acct
  909. .long sys_umount /* recycled never used phys() */
  910. .long sys_ni_syscall /* old lock syscall holder */
  911. .long sys_ioctl
  912. .long sys_fcntl /* 55 */
  913. .long sys_ni_syscall /* old mpx syscall holder */
  914. .long sys_setpgid
  915. .long sys_ni_syscall /* old ulimit syscall holder */
  916. .long sys_olduname
  917. .long sys_umask /* 60 */
  918. .long sys_chroot
  919. .long sys_ustat
  920. .long sys_dup2
  921. .long sys_getppid
  922. .long sys_getpgrp /* 65 */
  923. .long sys_setsid
  924. .long sys_sigaction
  925. .long sys_sgetmask
  926. .long sys_ssetmask
  927. .long sys_setreuid /* 70 */
  928. .long sys_setregid
  929. .long sys_sigsuspend
  930. .long sys_sigpending
  931. .long sys_sethostname
  932. .long sys_setrlimit /* 75 */
  933. .long sys_old_getrlimit
  934. .long sys_getrusage
  935. .long sys_gettimeofday
  936. .long sys_settimeofday
  937. .long sys_getgroups /* 80 */
  938. .long sys_setgroups
  939. .long ppc_select
  940. .long sys_symlink
  941. .long sys_lstat
  942. .long sys_readlink /* 85 */
  943. .long sys_uselib
  944. .long sys_swapon
  945. .long sys_reboot
  946. .long old_readdir
  947. .long sys_mmap /* 90 */
  948. .long sys_munmap
  949. .long sys_truncate
  950. .long sys_ftruncate
  951. .long sys_fchmod
  952. .long sys_fchown /* 95 */
  953. .long sys_getpriority
  954. .long sys_setpriority
  955. .long sys_ni_syscall /* old profil syscall holder */
  956. .long sys_statfs
  957. .long sys_fstatfs /* 100 */
  958. .long sys_ioperm
  959. .long sys_socketcall
  960. .long sys_syslog
  961. .long sys_setitimer
  962. .long sys_getitimer /* 105 */
  963. .long sys_newstat
  964. .long sys_newlstat
  965. .long sys_newfstat
  966. .long sys_uname
  967. .long sys_iopl /* 110 */
  968. .long sys_vhangup
  969. .long sys_ni_syscall /* old 'idle' syscall */
  970. .long sys_vm86
  971. .long sys_wait4
  972. .long sys_swapoff /* 115 */
  973. .long sys_sysinfo
  974. .long sys_ipc
  975. .long sys_fsync
  976. .long sys_sigreturn
  977. .long sys_clone /* 120 */
  978. .long sys_setdomainname
  979. .long sys_newuname
  980. .long sys_modify_ldt
  981. .long sys_adjtimex
  982. .long sys_mprotect /* 125 */
  983. .long sys_sigprocmask
  984. .long sys_create_module
  985. .long sys_init_module
  986. .long sys_delete_module
  987. .long sys_get_kernel_syms /* 130 */
  988. .long sys_quotactl
  989. .long sys_getpgid
  990. .long sys_fchdir
  991. .long sys_bdflush
  992. .long sys_sysfs /* 135 */
  993. .long sys_personality
  994. .long sys_ni_syscall /* for afs_syscall */
  995. .long sys_setfsuid
  996. .long sys_setfsgid
  997. .long sys_llseek /* 140 */
  998. .long sys_getdents
  999. .long ppc_select
  1000. .long sys_flock
  1001. .long sys_msync
  1002. .long sys_readv /* 145 */
  1003. .long sys_writev
  1004. .long sys_getsid
  1005. .long sys_fdatasync
  1006. .long sys_sysctl
  1007. .long sys_mlock /* 150 */
  1008. .long sys_munlock
  1009. .long sys_mlockall
  1010. .long sys_munlockall
  1011. .long sys_sched_setparam
  1012. .long sys_sched_getparam /* 155 */
  1013. .long sys_sched_setscheduler
  1014. .long sys_sched_getscheduler
  1015. .long sys_sched_yield
  1016. .long sys_sched_get_priority_max
  1017. .long sys_sched_get_priority_min  /* 160 */
  1018. .long sys_sched_rr_get_interval
  1019. .long sys_nanosleep
  1020. .long sys_mremap
  1021. .long sys_setresuid
  1022. .long sys_getresuid /* 165 */
  1023. .long sys_query_module
  1024. .long sys_poll
  1025. .long sys_nfsservctl
  1026. .long sys_setresgid
  1027. .long sys_getresgid /* 170 */
  1028. .long sys_prctl
  1029. .long sys_rt_sigreturn
  1030. .long sys_rt_sigaction
  1031. .long sys_rt_sigprocmask
  1032. .long sys_rt_sigpending /* 175 */
  1033. .long sys_rt_sigtimedwait
  1034. .long sys_rt_sigqueueinfo
  1035. .long sys_rt_sigsuspend
  1036. .long sys_pread
  1037. .long sys_pwrite /* 180 */
  1038. .long sys_chown
  1039. .long sys_getcwd
  1040. .long sys_capget
  1041. .long sys_capset
  1042. .long sys_sigaltstack /* 185 */
  1043. .long sys_sendfile
  1044. .long sys_ni_syscall /* streams1 */
  1045. .long sys_ni_syscall /* streams2 */
  1046. .long sys_vfork
  1047. .long sys_getrlimit /* 190 */
  1048. .long sys_readahead
  1049. .long sys_mmap2
  1050. .long sys_truncate64
  1051. .long sys_ftruncate64
  1052. .long sys_stat64 /* 195 */
  1053. .long sys_lstat64
  1054. .long sys_fstat64
  1055. .long sys_pciconfig_read
  1056. .long sys_pciconfig_write 
  1057. .long sys_pciconfig_iobase  /* 200 */
  1058. .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */
  1059. .long sys_getdents64
  1060. .long sys_pivot_root
  1061. .long sys_fcntl64
  1062. .long sys_madvise /* 205 */
  1063. .long sys_mincore
  1064. .long sys_gettid
  1065. .rept NR_syscalls-(.-sys_call_table)/4
  1066. .long sys_ni_syscall
  1067. .endr