[PATCH] powerpc: Merge cacheflush.h and cache.h
[linux-2.6] / arch / powerpc / kernel / misc_32.S
1 /*
2  * This file contains miscellaneous low-level functions.
3  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4  *
5  * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6  * and Paul Mackerras.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version
11  * 2 of the License, or (at your option) any later version.
12  *
13  */
14
15 #include <linux/config.h>
16 #include <linux/sys.h>
17 #include <asm/unistd.h>
18 #include <asm/errno.h>
19 #include <asm/reg.h>
20 #include <asm/page.h>
21 #include <asm/cache.h>
22 #include <asm/cputable.h>
23 #include <asm/mmu.h>
24 #include <asm/ppc_asm.h>
25 #include <asm/thread_info.h>
26 #include <asm/asm-offsets.h>
27
28         .text
29
30         .align  5
31 _GLOBAL(__delay)
32         cmpwi   0,r3,0
33         mtctr   r3
34         beqlr
35 1:      bdnz    1b
36         blr
37
38 /*
39  * This returns the high 64 bits of the product of two 64-bit numbers.
40  */
41 _GLOBAL(mulhdu)
42         cmpwi   r6,0
43         cmpwi   cr1,r3,0
44         mr      r10,r4
45         mulhwu  r4,r4,r5
46         beq     1f
47         mulhwu  r0,r10,r6
48         mullw   r7,r10,r5
49         addc    r7,r0,r7
50         addze   r4,r4
51 1:      beqlr   cr1             /* all done if high part of A is 0 */
52         mr      r10,r3
53         mullw   r9,r3,r5
54         mulhwu  r3,r3,r5
55         beq     2f
56         mullw   r0,r10,r6
57         mulhwu  r8,r10,r6
58         addc    r7,r0,r7
59         adde    r4,r4,r8
60         addze   r3,r3
61 2:      addc    r4,r4,r9
62         addze   r3,r3
63         blr
64
65 /*
66  * Returns (address we're running at) - (address we were linked at)
67  * for use before the text and data are mapped to KERNELBASE.
68  */
69 _GLOBAL(reloc_offset)
70         mflr    r0
71         bl      1f
72 1:      mflr    r3
73         LOADADDR(r4,1b)
74         subf    r3,r4,r3
75         mtlr    r0
76         blr
77
78 /*
79  * add_reloc_offset(x) returns x + reloc_offset().
80  */
81 _GLOBAL(add_reloc_offset)
82         mflr    r0
83         bl      1f
84 1:      mflr    r5
85         LOADADDR(r4,1b)
86         subf    r5,r4,r5
87         add     r3,r3,r5
88         mtlr    r0
89         blr
90
91 /*
92  * sub_reloc_offset(x) returns x - reloc_offset().
93  */
94 _GLOBAL(sub_reloc_offset)
95         mflr    r0
96         bl      1f
97 1:      mflr    r5
98         lis     r4,1b@ha
99         addi    r4,r4,1b@l
100         subf    r5,r4,r5
101         subf    r3,r5,r3
102         mtlr    r0
103         blr
104
105 /*
106  * reloc_got2 runs through the .got2 section adding an offset
107  * to each entry.
108  */
109 _GLOBAL(reloc_got2)
110         mflr    r11
111         lis     r7,__got2_start@ha
112         addi    r7,r7,__got2_start@l
113         lis     r8,__got2_end@ha
114         addi    r8,r8,__got2_end@l
115         subf    r8,r7,r8
116         srwi.   r8,r8,2
117         beqlr
118         mtctr   r8
119         bl      1f
120 1:      mflr    r0
121         lis     r4,1b@ha
122         addi    r4,r4,1b@l
123         subf    r0,r4,r0
124         add     r7,r0,r7
125 2:      lwz     r0,0(r7)
126         add     r0,r0,r3
127         stw     r0,0(r7)
128         addi    r7,r7,4
129         bdnz    2b
130         mtlr    r11
131         blr
132
133 /*
134  * identify_cpu,
135  * called with r3 = data offset and r4 = CPU number
136  * doesn't change r3
137  */
138 _GLOBAL(identify_cpu)
139         addis   r8,r3,cpu_specs@ha
140         addi    r8,r8,cpu_specs@l
141         mfpvr   r7
142 1:
143         lwz     r5,CPU_SPEC_PVR_MASK(r8)
144         and     r5,r5,r7
145         lwz     r6,CPU_SPEC_PVR_VALUE(r8)
146         cmplw   0,r6,r5
147         beq     1f
148         addi    r8,r8,CPU_SPEC_ENTRY_SIZE
149         b       1b
150 1:
151         addis   r6,r3,cur_cpu_spec@ha
152         addi    r6,r6,cur_cpu_spec@l
153         sub     r8,r8,r3
154         stw     r8,0(r6)
155         blr
156
157 /*
158  * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
159  * and writes nop's over sections of code that don't apply for this cpu.
160  * r3 = data offset (not changed)
161  */
162 _GLOBAL(do_cpu_ftr_fixups)
163         /* Get CPU 0 features */
164         addis   r6,r3,cur_cpu_spec@ha
165         addi    r6,r6,cur_cpu_spec@l
166         lwz     r4,0(r6)
167         add     r4,r4,r3
168         lwz     r4,CPU_SPEC_FEATURES(r4)
169
170         /* Get the fixup table */
171         addis   r6,r3,__start___ftr_fixup@ha
172         addi    r6,r6,__start___ftr_fixup@l
173         addis   r7,r3,__stop___ftr_fixup@ha
174         addi    r7,r7,__stop___ftr_fixup@l
175
176         /* Do the fixup */
177 1:      cmplw   0,r6,r7
178         bgelr
179         addi    r6,r6,16
180         lwz     r8,-16(r6)      /* mask */
181         and     r8,r8,r4
182         lwz     r9,-12(r6)      /* value */
183         cmplw   0,r8,r9
184         beq     1b
185         lwz     r8,-8(r6)       /* section begin */
186         lwz     r9,-4(r6)       /* section end */
187         subf.   r9,r8,r9
188         beq     1b
189         /* write nops over the section of code */
190         /* todo: if large section, add a branch at the start of it */
191         srwi    r9,r9,2
192         mtctr   r9
193         add     r8,r8,r3
194         lis     r0,0x60000000@h /* nop */
195 3:      stw     r0,0(r8)
196         andi.   r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
197         beq     2f
198         dcbst   0,r8            /* suboptimal, but simpler */
199         sync
200         icbi    0,r8
201 2:      addi    r8,r8,4
202         bdnz    3b
203         sync                    /* additional sync needed on g4 */
204         isync
205         b       1b
206
207 /*
208  * call_setup_cpu - call the setup_cpu function for this cpu
209  * r3 = data offset, r24 = cpu number
210  *
211  * Setup function is called with:
212  *   r3 = data offset
213  *   r4 = ptr to CPU spec (relocated)
214  */
215 _GLOBAL(call_setup_cpu)
216         addis   r4,r3,cur_cpu_spec@ha
217         addi    r4,r4,cur_cpu_spec@l
218         lwz     r4,0(r4)
219         add     r4,r4,r3
220         lwz     r5,CPU_SPEC_SETUP(r4)
221         cmpi    0,r5,0
222         add     r5,r5,r3
223         beqlr
224         mtctr   r5
225         bctr
226
227 #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
228
229 /* This gets called by via-pmu.c to switch the PLL selection
230  * on 750fx CPU. This function should really be moved to some
231  * other place (as most of the cpufreq code in via-pmu
232  */
233 _GLOBAL(low_choose_750fx_pll)
234         /* Clear MSR:EE */
235         mfmsr   r7
236         rlwinm  r0,r7,0,17,15
237         mtmsr   r0
238
239         /* If switching to PLL1, disable HID0:BTIC */
240         cmplwi  cr0,r3,0
241         beq     1f
242         mfspr   r5,SPRN_HID0
243         rlwinm  r5,r5,0,27,25
244         sync
245         mtspr   SPRN_HID0,r5
246         isync
247         sync
248
249 1:
250         /* Calc new HID1 value */
251         mfspr   r4,SPRN_HID1    /* Build a HID1:PS bit from parameter */
252         rlwinm  r5,r3,16,15,15  /* Clear out HID1:PS from value read */
253         rlwinm  r4,r4,0,16,14   /* Could have I used rlwimi here ? */
254         or      r4,r4,r5
255         mtspr   SPRN_HID1,r4
256
257         /* Store new HID1 image */
258         rlwinm  r6,r1,0,0,18
259         lwz     r6,TI_CPU(r6)
260         slwi    r6,r6,2
261         addis   r6,r6,nap_save_hid1@ha
262         stw     r4,nap_save_hid1@l(r6)
263
264         /* If switching to PLL0, enable HID0:BTIC */
265         cmplwi  cr0,r3,0
266         bne     1f
267         mfspr   r5,SPRN_HID0
268         ori     r5,r5,HID0_BTIC
269         sync
270         mtspr   SPRN_HID0,r5
271         isync
272         sync
273
274 1:
275         /* Return */
276         mtmsr   r7
277         blr
278
279 _GLOBAL(low_choose_7447a_dfs)
280         /* Clear MSR:EE */
281         mfmsr   r7
282         rlwinm  r0,r7,0,17,15
283         mtmsr   r0
284         
285         /* Calc new HID1 value */
286         mfspr   r4,SPRN_HID1
287         insrwi  r4,r3,1,9       /* insert parameter into bit 9 */
288         sync
289         mtspr   SPRN_HID1,r4
290         sync
291         isync
292
293         /* Return */
294         mtmsr   r7
295         blr
296
297 #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
298
299 /*
300  * complement mask on the msr then "or" some values on.
301  *     _nmask_and_or_msr(nmask, value_to_or)
302  */
303 _GLOBAL(_nmask_and_or_msr)
304         mfmsr   r0              /* Get current msr */
305         andc    r0,r0,r3        /* And off the bits set in r3 (first parm) */
306         or      r0,r0,r4        /* Or on the bits in r4 (second parm) */
307         SYNC                    /* Some chip revs have problems here... */
308         mtmsr   r0              /* Update machine state */
309         isync
310         blr                     /* Done */
311
312
313 /*
314  * Flush MMU TLB
315  */
316 _GLOBAL(_tlbia)
317 #if defined(CONFIG_40x)
318         sync                    /* Flush to memory before changing mapping */
319         tlbia
320         isync                   /* Flush shadow TLB */
321 #elif defined(CONFIG_44x)
322         li      r3,0
323         sync
324
325         /* Load high watermark */
326         lis     r4,tlb_44x_hwater@ha
327         lwz     r5,tlb_44x_hwater@l(r4)
328
329 1:      tlbwe   r3,r3,PPC44x_TLB_PAGEID
330         addi    r3,r3,1
331         cmpw    0,r3,r5
332         ble     1b
333
334         isync
335 #elif defined(CONFIG_FSL_BOOKE)
336         /* Invalidate all entries in TLB0 */
337         li      r3, 0x04
338         tlbivax 0,3
339         /* Invalidate all entries in TLB1 */
340         li      r3, 0x0c
341         tlbivax 0,3
342         /* Invalidate all entries in TLB2 */
343         li      r3, 0x14
344         tlbivax 0,3
345         /* Invalidate all entries in TLB3 */
346         li      r3, 0x1c
347         tlbivax 0,3
348         msync
349 #ifdef CONFIG_SMP
350         tlbsync
351 #endif /* CONFIG_SMP */
352 #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
353 #if defined(CONFIG_SMP)
354         rlwinm  r8,r1,0,0,18
355         lwz     r8,TI_CPU(r8)
356         oris    r8,r8,10
357         mfmsr   r10
358         SYNC
359         rlwinm  r0,r10,0,17,15          /* clear bit 16 (MSR_EE) */
360         rlwinm  r0,r0,0,28,26           /* clear DR */
361         mtmsr   r0
362         SYNC_601
363         isync
364         lis     r9,mmu_hash_lock@h
365         ori     r9,r9,mmu_hash_lock@l
366         tophys(r9,r9)
367 10:     lwarx   r7,0,r9
368         cmpwi   0,r7,0
369         bne-    10b
370         stwcx.  r8,0,r9
371         bne-    10b
372         sync
373         tlbia
374         sync
375         TLBSYNC
376         li      r0,0
377         stw     r0,0(r9)                /* clear mmu_hash_lock */
378         mtmsr   r10
379         SYNC_601
380         isync
381 #else /* CONFIG_SMP */
382         sync
383         tlbia
384         sync
385 #endif /* CONFIG_SMP */
386 #endif /* ! defined(CONFIG_40x) */
387         blr
388
389 /*
390  * Flush MMU TLB for a particular address
391  */
392 _GLOBAL(_tlbie)
393 #if defined(CONFIG_40x)
394         tlbsx.  r3, 0, r3
395         bne     10f
396         sync
397         /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
398          * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
399          * the TLB entry. */
400         tlbwe   r3, r3, TLB_TAG
401         isync
402 10:
403 #elif defined(CONFIG_44x)
404         mfspr   r4,SPRN_MMUCR
405         mfspr   r5,SPRN_PID                     /* Get PID */
406         rlwimi  r4,r5,0,24,31                   /* Set TID */
407         mtspr   SPRN_MMUCR,r4
408
409         tlbsx.  r3, 0, r3
410         bne     10f
411         sync
412         /* There are only 64 TLB entries, so r3 < 64,
413          * which means bit 22, is clear.  Since 22 is
414          * the V bit in the TLB_PAGEID, loading this
415          * value will invalidate the TLB entry.
416          */
417         tlbwe   r3, r3, PPC44x_TLB_PAGEID
418         isync
419 10:
420 #elif defined(CONFIG_FSL_BOOKE)
421         rlwinm  r4, r3, 0, 0, 19
422         ori     r5, r4, 0x08    /* TLBSEL = 1 */
423         ori     r6, r4, 0x10    /* TLBSEL = 2 */
424         ori     r7, r4, 0x18    /* TLBSEL = 3 */
425         tlbivax 0, r4
426         tlbivax 0, r5
427         tlbivax 0, r6
428         tlbivax 0, r7
429         msync
430 #if defined(CONFIG_SMP)
431         tlbsync
432 #endif /* CONFIG_SMP */
433 #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
434 #if defined(CONFIG_SMP)
435         rlwinm  r8,r1,0,0,18
436         lwz     r8,TI_CPU(r8)
437         oris    r8,r8,11
438         mfmsr   r10
439         SYNC
440         rlwinm  r0,r10,0,17,15          /* clear bit 16 (MSR_EE) */
441         rlwinm  r0,r0,0,28,26           /* clear DR */
442         mtmsr   r0
443         SYNC_601
444         isync
445         lis     r9,mmu_hash_lock@h
446         ori     r9,r9,mmu_hash_lock@l
447         tophys(r9,r9)
448 10:     lwarx   r7,0,r9
449         cmpwi   0,r7,0
450         bne-    10b
451         stwcx.  r8,0,r9
452         bne-    10b
453         eieio
454         tlbie   r3
455         sync
456         TLBSYNC
457         li      r0,0
458         stw     r0,0(r9)                /* clear mmu_hash_lock */
459         mtmsr   r10
460         SYNC_601
461         isync
462 #else /* CONFIG_SMP */
463         tlbie   r3
464         sync
465 #endif /* CONFIG_SMP */
466 #endif /* ! CONFIG_40x */
467         blr
468
469 /*
470  * Flush instruction cache.
471  * This is a no-op on the 601.
472  */
473 _GLOBAL(flush_instruction_cache)
474 #if defined(CONFIG_8xx)
475         isync
476         lis     r5, IDC_INVALL@h
477         mtspr   SPRN_IC_CST, r5
478 #elif defined(CONFIG_4xx)
479 #ifdef CONFIG_403GCX
480         li      r3, 512
481         mtctr   r3
482         lis     r4, KERNELBASE@h
483 1:      iccci   0, r4
484         addi    r4, r4, 16
485         bdnz    1b
486 #else
487         lis     r3, KERNELBASE@h
488         iccci   0,r3
489 #endif
490 #elif CONFIG_FSL_BOOKE
491 BEGIN_FTR_SECTION
492         mfspr   r3,SPRN_L1CSR0
493         ori     r3,r3,L1CSR0_CFI|L1CSR0_CLFC
494         /* msync; isync recommended here */
495         mtspr   SPRN_L1CSR0,r3
496         isync
497         blr
498 END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
499         mfspr   r3,SPRN_L1CSR1
500         ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
501         mtspr   SPRN_L1CSR1,r3
502 #else
503         mfspr   r3,SPRN_PVR
504         rlwinm  r3,r3,16,16,31
505         cmpwi   0,r3,1
506         beqlr                   /* for 601, do nothing */
507         /* 603/604 processor - use invalidate-all bit in HID0 */
508         mfspr   r3,SPRN_HID0
509         ori     r3,r3,HID0_ICFI
510         mtspr   SPRN_HID0,r3
511 #endif /* CONFIG_8xx/4xx */
512         isync
513         blr
514
515 /*
516  * Write any modified data cache blocks out to memory
517  * and invalidate the corresponding instruction cache blocks.
518  * This is a no-op on the 601.
519  *
520  * flush_icache_range(unsigned long start, unsigned long stop)
521  */
522 _GLOBAL(__flush_icache_range)
523 BEGIN_FTR_SECTION
524         blr                             /* for 601, do nothing */
525 END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
526         li      r5,L1_CACHE_BYTES-1
527         andc    r3,r3,r5
528         subf    r4,r3,r4
529         add     r4,r4,r5
530         srwi.   r4,r4,L1_CACHE_SHIFT
531         beqlr
532         mtctr   r4
533         mr      r6,r3
534 1:      dcbst   0,r3
535         addi    r3,r3,L1_CACHE_BYTES
536         bdnz    1b
537         sync                            /* wait for dcbst's to get to ram */
538         mtctr   r4
539 2:      icbi    0,r6
540         addi    r6,r6,L1_CACHE_BYTES
541         bdnz    2b
542         sync                            /* additional sync needed on g4 */
543         isync
544         blr
545 /*
546  * Write any modified data cache blocks out to memory.
547  * Does not invalidate the corresponding cache lines (especially for
548  * any corresponding instruction cache).
549  *
550  * clean_dcache_range(unsigned long start, unsigned long stop)
551  */
552 _GLOBAL(clean_dcache_range)
553         li      r5,L1_CACHE_BYTES-1
554         andc    r3,r3,r5
555         subf    r4,r3,r4
556         add     r4,r4,r5
557         srwi.   r4,r4,L1_CACHE_SHIFT
558         beqlr
559         mtctr   r4
560
561 1:      dcbst   0,r3
562         addi    r3,r3,L1_CACHE_BYTES
563         bdnz    1b
564         sync                            /* wait for dcbst's to get to ram */
565         blr
566
567 /*
568  * Write any modified data cache blocks out to memory and invalidate them.
569  * Does not invalidate the corresponding instruction cache blocks.
570  *
571  * flush_dcache_range(unsigned long start, unsigned long stop)
572  */
573 _GLOBAL(flush_dcache_range)
574         li      r5,L1_CACHE_BYTES-1
575         andc    r3,r3,r5
576         subf    r4,r3,r4
577         add     r4,r4,r5
578         srwi.   r4,r4,L1_CACHE_SHIFT
579         beqlr
580         mtctr   r4
581
582 1:      dcbf    0,r3
583         addi    r3,r3,L1_CACHE_BYTES
584         bdnz    1b
585         sync                            /* wait for dcbst's to get to ram */
586         blr
587
588 /*
589  * Like above, but invalidate the D-cache.  This is used by the 8xx
590  * to invalidate the cache so the PPC core doesn't get stale data
591  * from the CPM (no cache snooping here :-).
592  *
593  * invalidate_dcache_range(unsigned long start, unsigned long stop)
594  */
595 _GLOBAL(invalidate_dcache_range)
596         li      r5,L1_CACHE_BYTES-1
597         andc    r3,r3,r5
598         subf    r4,r3,r4
599         add     r4,r4,r5
600         srwi.   r4,r4,L1_CACHE_SHIFT
601         beqlr
602         mtctr   r4
603
604 1:      dcbi    0,r3
605         addi    r3,r3,L1_CACHE_BYTES
606         bdnz    1b
607         sync                            /* wait for dcbi's to get to ram */
608         blr
609
610 /*
611  * Flush a particular page from the data cache to RAM.
612  * Note: this is necessary because the instruction cache does *not*
613  * snoop from the data cache.
614  * This is a no-op on the 601 which has a unified cache.
615  *
616  *      void __flush_dcache_icache(void *page)
617  */
618 _GLOBAL(__flush_dcache_icache)
619 BEGIN_FTR_SECTION
620         blr                                     /* for 601, do nothing */
621 END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
622         rlwinm  r3,r3,0,0,19                    /* Get page base address */
623         li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
624         mtctr   r4
625         mr      r6,r3
626 0:      dcbst   0,r3                            /* Write line to ram */
627         addi    r3,r3,L1_CACHE_BYTES
628         bdnz    0b
629         sync
630         mtctr   r4
631 1:      icbi    0,r6
632         addi    r6,r6,L1_CACHE_BYTES
633         bdnz    1b
634         sync
635         isync
636         blr
637
638 /*
639  * Flush a particular page from the data cache to RAM, identified
640  * by its physical address.  We turn off the MMU so we can just use
641  * the physical address (this may be a highmem page without a kernel
642  * mapping).
643  *
644  *      void __flush_dcache_icache_phys(unsigned long physaddr)
645  */
646 _GLOBAL(__flush_dcache_icache_phys)
647 BEGIN_FTR_SECTION
648         blr                                     /* for 601, do nothing */
649 END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
650         mfmsr   r10
651         rlwinm  r0,r10,0,28,26                  /* clear DR */
652         mtmsr   r0
653         isync
654         rlwinm  r3,r3,0,0,19                    /* Get page base address */
655         li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
656         mtctr   r4
657         mr      r6,r3
658 0:      dcbst   0,r3                            /* Write line to ram */
659         addi    r3,r3,L1_CACHE_BYTES
660         bdnz    0b
661         sync
662         mtctr   r4
663 1:      icbi    0,r6
664         addi    r6,r6,L1_CACHE_BYTES
665         bdnz    1b
666         sync
667         mtmsr   r10                             /* restore DR */
668         isync
669         blr
670
671 /*
672  * Clear pages using the dcbz instruction, which doesn't cause any
673  * memory traffic (except to write out any cache lines which get
674  * displaced).  This only works on cacheable memory.
675  *
676  * void clear_pages(void *page, int order) ;
677  */
678 _GLOBAL(clear_pages)
679         li      r0,4096/L1_CACHE_BYTES
680         slw     r0,r0,r4
681         mtctr   r0
682 #ifdef CONFIG_8xx
683         li      r4, 0
684 1:      stw     r4, 0(r3)
685         stw     r4, 4(r3)
686         stw     r4, 8(r3)
687         stw     r4, 12(r3)
688 #else
689 1:      dcbz    0,r3
690 #endif
691         addi    r3,r3,L1_CACHE_BYTES
692         bdnz    1b
693         blr
694
695 /*
696  * Copy a whole page.  We use the dcbz instruction on the destination
697  * to reduce memory traffic (it eliminates the unnecessary reads of
698  * the destination into cache).  This requires that the destination
699  * is cacheable.
700  */
701 #define COPY_16_BYTES           \
702         lwz     r6,4(r4);       \
703         lwz     r7,8(r4);       \
704         lwz     r8,12(r4);      \
705         lwzu    r9,16(r4);      \
706         stw     r6,4(r3);       \
707         stw     r7,8(r3);       \
708         stw     r8,12(r3);      \
709         stwu    r9,16(r3)
710
711 _GLOBAL(copy_page)
712         addi    r3,r3,-4
713         addi    r4,r4,-4
714
715 #ifdef CONFIG_8xx
716         /* don't use prefetch on 8xx */
717         li      r0,4096/L1_CACHE_BYTES
718         mtctr   r0
719 1:      COPY_16_BYTES
720         bdnz    1b
721         blr
722
723 #else   /* not 8xx, we can prefetch */
724         li      r5,4
725
726 #if MAX_COPY_PREFETCH > 1
727         li      r0,MAX_COPY_PREFETCH
728         li      r11,4
729         mtctr   r0
730 11:     dcbt    r11,r4
731         addi    r11,r11,L1_CACHE_BYTES
732         bdnz    11b
733 #else /* MAX_COPY_PREFETCH == 1 */
734         dcbt    r5,r4
735         li      r11,L1_CACHE_BYTES+4
736 #endif /* MAX_COPY_PREFETCH */
737         li      r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
738         crclr   4*cr0+eq
739 2:
740         mtctr   r0
741 1:
742         dcbt    r11,r4
743         dcbz    r5,r3
744         COPY_16_BYTES
745 #if L1_CACHE_BYTES >= 32
746         COPY_16_BYTES
747 #if L1_CACHE_BYTES >= 64
748         COPY_16_BYTES
749         COPY_16_BYTES
750 #if L1_CACHE_BYTES >= 128
751         COPY_16_BYTES
752         COPY_16_BYTES
753         COPY_16_BYTES
754         COPY_16_BYTES
755 #endif
756 #endif
757 #endif
758         bdnz    1b
759         beqlr
760         crnot   4*cr0+eq,4*cr0+eq
761         li      r0,MAX_COPY_PREFETCH
762         li      r11,4
763         b       2b
764 #endif  /* CONFIG_8xx */
765
766 /*
767  * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
768  * void atomic_set_mask(atomic_t mask, atomic_t *addr);
769  */
770 _GLOBAL(atomic_clear_mask)
771 10:     lwarx   r5,0,r4
772         andc    r5,r5,r3
773         PPC405_ERR77(0,r4)
774         stwcx.  r5,0,r4
775         bne-    10b
776         blr
777 _GLOBAL(atomic_set_mask)
778 10:     lwarx   r5,0,r4
779         or      r5,r5,r3
780         PPC405_ERR77(0,r4)
781         stwcx.  r5,0,r4
782         bne-    10b
783         blr
784
785 /*
786  * I/O string operations
787  *
788  * insb(port, buf, len)
789  * outsb(port, buf, len)
790  * insw(port, buf, len)
791  * outsw(port, buf, len)
792  * insl(port, buf, len)
793  * outsl(port, buf, len)
794  * insw_ns(port, buf, len)
795  * outsw_ns(port, buf, len)
796  * insl_ns(port, buf, len)
797  * outsl_ns(port, buf, len)
798  *
799  * The *_ns versions don't do byte-swapping.
800  */
801 _GLOBAL(_insb)
802         cmpwi   0,r5,0
803         mtctr   r5
804         subi    r4,r4,1
805         blelr-
806 00:     lbz     r5,0(r3)
807         eieio
808         stbu    r5,1(r4)
809         bdnz    00b
810         blr
811
812 _GLOBAL(_outsb)
813         cmpwi   0,r5,0
814         mtctr   r5
815         subi    r4,r4,1
816         blelr-
817 00:     lbzu    r5,1(r4)
818         stb     r5,0(r3)
819         eieio
820         bdnz    00b
821         blr
822
823 _GLOBAL(_insw)
824         cmpwi   0,r5,0
825         mtctr   r5
826         subi    r4,r4,2
827         blelr-
828 00:     lhbrx   r5,0,r3
829         eieio
830         sthu    r5,2(r4)
831         bdnz    00b
832         blr
833
834 _GLOBAL(_outsw)
835         cmpwi   0,r5,0
836         mtctr   r5
837         subi    r4,r4,2
838         blelr-
839 00:     lhzu    r5,2(r4)
840         eieio
841         sthbrx  r5,0,r3
842         bdnz    00b
843         blr
844
845 _GLOBAL(_insl)
846         cmpwi   0,r5,0
847         mtctr   r5
848         subi    r4,r4,4
849         blelr-
850 00:     lwbrx   r5,0,r3
851         eieio
852         stwu    r5,4(r4)
853         bdnz    00b
854         blr
855
856 _GLOBAL(_outsl)
857         cmpwi   0,r5,0
858         mtctr   r5
859         subi    r4,r4,4
860         blelr-
861 00:     lwzu    r5,4(r4)
862         stwbrx  r5,0,r3
863         eieio
864         bdnz    00b
865         blr
866
867 _GLOBAL(__ide_mm_insw)
868 _GLOBAL(_insw_ns)
869         cmpwi   0,r5,0
870         mtctr   r5
871         subi    r4,r4,2
872         blelr-
873 00:     lhz     r5,0(r3)
874         eieio
875         sthu    r5,2(r4)
876         bdnz    00b
877         blr
878
879 _GLOBAL(__ide_mm_outsw)
880 _GLOBAL(_outsw_ns)
881         cmpwi   0,r5,0
882         mtctr   r5
883         subi    r4,r4,2
884         blelr-
885 00:     lhzu    r5,2(r4)
886         sth     r5,0(r3)
887         eieio
888         bdnz    00b
889         blr
890
891 _GLOBAL(__ide_mm_insl)
892 _GLOBAL(_insl_ns)
893         cmpwi   0,r5,0
894         mtctr   r5
895         subi    r4,r4,4
896         blelr-
897 00:     lwz     r5,0(r3)
898         eieio
899         stwu    r5,4(r4)
900         bdnz    00b
901         blr
902
903 _GLOBAL(__ide_mm_outsl)
904 _GLOBAL(_outsl_ns)
905         cmpwi   0,r5,0
906         mtctr   r5
907         subi    r4,r4,4
908         blelr-
909 00:     lwzu    r5,4(r4)
910         stw     r5,0(r3)
911         eieio
912         bdnz    00b
913         blr
914
915 /*
916  * Extended precision shifts.
917  *
918  * Updated to be valid for shift counts from 0 to 63 inclusive.
919  * -- Gabriel
920  *
921  * R3/R4 has 64 bit value
922  * R5    has shift count
923  * result in R3/R4
924  *
925  *  ashrdi3: arithmetic right shift (sign propagation)  
926  *  lshrdi3: logical right shift
927  *  ashldi3: left shift
928  */
929 _GLOBAL(__ashrdi3)
930         subfic  r6,r5,32
931         srw     r4,r4,r5        # LSW = count > 31 ? 0 : LSW >> count
932         addi    r7,r5,32        # could be xori, or addi with -32
933         slw     r6,r3,r6        # t1 = count > 31 ? 0 : MSW << (32-count)
934         rlwinm  r8,r7,0,32      # t3 = (count < 32) ? 32 : 0
935         sraw    r7,r3,r7        # t2 = MSW >> (count-32)
936         or      r4,r4,r6        # LSW |= t1
937         slw     r7,r7,r8        # t2 = (count < 32) ? 0 : t2
938         sraw    r3,r3,r5        # MSW = MSW >> count
939         or      r4,r4,r7        # LSW |= t2
940         blr
941
942 _GLOBAL(__ashldi3)
943         subfic  r6,r5,32
944         slw     r3,r3,r5        # MSW = count > 31 ? 0 : MSW << count
945         addi    r7,r5,32        # could be xori, or addi with -32
946         srw     r6,r4,r6        # t1 = count > 31 ? 0 : LSW >> (32-count)
947         slw     r7,r4,r7        # t2 = count < 32 ? 0 : LSW << (count-32)
948         or      r3,r3,r6        # MSW |= t1
949         slw     r4,r4,r5        # LSW = LSW << count
950         or      r3,r3,r7        # MSW |= t2
951         blr
952
953 _GLOBAL(__lshrdi3)
954         subfic  r6,r5,32
955         srw     r4,r4,r5        # LSW = count > 31 ? 0 : LSW >> count
956         addi    r7,r5,32        # could be xori, or addi with -32
957         slw     r6,r3,r6        # t1 = count > 31 ? 0 : MSW << (32-count)
958         srw     r7,r3,r7        # t2 = count < 32 ? 0 : MSW >> (count-32)
959         or      r4,r4,r6        # LSW |= t1
960         srw     r3,r3,r5        # MSW = MSW >> count
961         or      r4,r4,r7        # LSW |= t2
962         blr
963
964 _GLOBAL(abs)
965         srawi   r4,r3,31
966         xor     r3,r3,r4
967         sub     r3,r3,r4
968         blr
969
970 _GLOBAL(_get_SP)
971         mr      r3,r1           /* Close enough */
972         blr
973
974 /*
975  * Create a kernel thread
976  *   kernel_thread(fn, arg, flags)
977  */
978 _GLOBAL(kernel_thread)
979         stwu    r1,-16(r1)
980         stw     r30,8(r1)
981         stw     r31,12(r1)
982         mr      r30,r3          /* function */
983         mr      r31,r4          /* argument */
984         ori     r3,r5,CLONE_VM  /* flags */
985         oris    r3,r3,CLONE_UNTRACED>>16
986         li      r4,0            /* new sp (unused) */
987         li      r0,__NR_clone
988         sc
989         cmpwi   0,r3,0          /* parent or child? */
990         bne     1f              /* return if parent */
991         li      r0,0            /* make top-level stack frame */
992         stwu    r0,-16(r1)
993         mtlr    r30             /* fn addr in lr */
994         mr      r3,r31          /* load arg and call fn */
995         PPC440EP_ERR42
996         blrl
997         li      r0,__NR_exit    /* exit if function returns */
998         li      r3,0
999         sc
1000 1:      lwz     r30,8(r1)
1001         lwz     r31,12(r1)
1002         addi    r1,r1,16
1003         blr
1004
1005 _GLOBAL(execve)
1006         li      r0,__NR_execve
1007         sc
1008         bnslr
1009         neg     r3,r3
1010         blr
1011
1012 /*
1013  * This routine is just here to keep GCC happy - sigh...
1014  */
1015 _GLOBAL(__main)
1016         blr