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