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

Linux/Unix编程

开发平台:

Unix_Linux

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