]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/sparc64/sparc64/support.S
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / sys / sparc64 / sparc64 / support.S
1 /*-
2  * Copyright (c) 2001 Jake Burkholder.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/errno.h>
31
32 #include <machine/asi.h>
33 #include <machine/asmacros.h>
34 #include <machine/fsr.h>
35 #include <machine/intr_machdep.h>
36 #include <machine/ktr.h>
37 #include <machine/pcb.h>
38 #include <machine/pstate.h>
39 #include <machine/wstate.h>
40
41 #include "assym.s"
42
43         .register %g2, #ignore
44         .register %g3, #ignore
45         .register %g6, #ignore
46
47 /*
48  * Common code for copy routines.
49  *
50  * We use large macros to generate functions for each of the copy routines.
51  * This allows the load and store instructions to be generated for the right
52  * operation, asi or not.  It is possible to write an asi independent function
53  * but this would require 2 expensive wrs in the main loop to switch %asi.
54  * It would also screw up profiling (if we ever get it), but may save some I$.
55  * We assume that either one of dasi and sasi is empty, or that they are both
56  * the same (empty or non-empty).  It is up to the caller to set %asi.
57  */
58
59 /*
60  * ASI independent implementation of copystr(9).
61  * Used to implement copyinstr() and copystr().
62  *
63  * Return value is in %g1.
64  */
65 #define _COPYSTR(src, dst, len, done, sa, sasi, da, dasi) \
66         brz     len, 4f ; \
67          mov    src, %g2 ; \
68 1:      deccc   1, len ; \
69         bl,a,pn %xcc, 3f ; \
70          nop ; \
71         LD(ub, sa) [src] sasi, %g1 ; \
72         ST(b, da) %g1, [dst] dasi ; \
73         brz,pn  %g1, 3f ; \
74          inc    src ; \
75         ba      %xcc, 1b ; \
76          inc    dst ; \
77 2:      mov     ENAMETOOLONG, %g1 ; \
78 3:      sub     src, %g2, %g2 ; \
79         brnz,a  done, 4f ; \
80          stx    %g2, [done] ; \
81 4:
82
83 /*
84  * ASI independent implementation of memset(3).
85  * Used to implement bzero(), memset() and aszero().
86  *
87  * If the pattern is non-zero, duplicate it to fill 64 bits.
88  * Store bytes until dst is 8-byte aligned, then store 8 bytes.
89  * It has yet to be determined how much unrolling is beneficial.
90  * Could also read and compare before writing to minimize snoop traffic.
91  *
92  * XXX bzero() should be implemented as
93  * #define bzero(dst, len) (void)memset((dst), 0, (len))
94  * if at all.
95  */
96 #define _MEMSET(dst, pat, len, da, dasi) \
97         brlez,pn len, 5f ; \
98          and    pat, 0xff, pat ; \
99         brz,pt  pat, 1f ; \
100          sllx   pat, 8, %g1 ; \
101         or      pat, %g1, pat ; \
102         sllx    pat, 16, %g1 ; \
103         or      pat, %g1, pat ; \
104         sllx    pat, 32, %g1 ; \
105         or      pat, %g1, pat ; \
106         .align 16 ; \
107 1:      deccc   1, len ; \
108         bl,pn   %xcc, 5f ; \
109          btst   7, dst ; \
110         bz,a,pt %xcc, 2f ; \
111          inc    1, len ; \
112         ST(b, da) pat, [dst] dasi ; \
113         ba      %xcc, 1b ; \
114          inc    dst ; \
115         .align 16 ; \
116 2:      deccc   32, len ; \
117         bl,a,pn %xcc, 3f ; \
118          inc    32, len ; \
119         ST(x, da) pat, [dst] dasi ; \
120         ST(x, da) pat, [dst + 8] dasi ; \
121         ST(x, da) pat, [dst + 16] dasi ; \
122         ST(x, da) pat, [dst + 24] dasi ; \
123         ba      %xcc, 2b ; \
124          inc    32, dst ; \
125         .align 16 ; \
126 3:      deccc   8, len ; \
127         bl,a,pn %xcc, 4f ; \
128          inc    8, len ; \
129         ST(x, da) pat, [dst] dasi ; \
130         ba      %xcc, 3b ; \
131          inc    8, dst ; \
132         .align 16 ; \
133 4:      deccc   1, len ; \
134         bl,a,pn %xcc, 5f ; \
135          nop ; \
136         ST(b, da) pat, [dst] dasi ; \
137         ba      %xcc, 4b ; \
138          inc    1, dst ; \
139 5:
140
141 /*
142  * ASI independent implementation of memcpy(3).
143  * Used to implement bcopy(), copyin(), copyout(), memcpy(), ascopy(),
144  * ascopyfrom() and ascopyto().
145  *
146  * Transfer bytes until dst is 8-byte aligned.  If src is then also 8 byte
147  * aligned, transfer 8 bytes, otherwise finish with bytes.  The unaligned
148  * case could be optimized, but it is expected that this is the uncommon
149  * case and of questionable value.  The code to do so is also rather large
150  * and ugly.  It has yet to be determined how much unrolling is beneficial.
151  *
152  * XXX bcopy() must also check for overlap.  This is stupid.
153  * XXX bcopy() should be implemented as
154  * #define bcopy(src, dst, len) (void)memcpy((dst), (src), (len))
155  * if at all.
156  */
157 #define _MEMCPY(dst, src, len, da, dasi, sa, sasi) \
158 1:      deccc   1, len ; \
159         bl,pn   %xcc, 6f ; \
160          btst   7, dst ; \
161         bz,a,pt %xcc, 2f ; \
162          inc    1, len ; \
163         LD(ub, sa) [src] sasi, %g1 ; \
164         ST(b, da) %g1, [dst] dasi ; \
165         inc     1, src ; \
166         ba      %xcc, 1b ; \
167          inc    1, dst ; \
168         .align 16 ; \
169 2:      btst    7, src ; \
170         bz,a,pt %xcc, 3f ; \
171          nop ; \
172         ba,a    %xcc, 5f ; \
173         .align 16 ; \
174 3:      deccc   32, len ; \
175         bl,a,pn %xcc, 4f ; \
176          inc    32, len ; \
177         LD(x, sa) [src] sasi, %g1 ; \
178         LD(x, sa) [src + 8] sasi, %g2 ; \
179         LD(x, sa) [src + 16] sasi, %g3 ; \
180         LD(x, sa) [src + 24] sasi, %g4 ; \
181         ST(x, da) %g1, [dst] dasi ; \
182         ST(x, da) %g2, [dst + 8] dasi ; \
183         ST(x, da) %g3, [dst + 16] dasi ; \
184         ST(x, da) %g4, [dst + 24] dasi ; \
185         inc     32, src ; \
186         ba      %xcc, 3b ; \
187          inc    32, dst ; \
188         .align 16 ; \
189 4:      deccc   8, len ; \
190         bl,a,pn %xcc, 5f ; \
191          inc    8, len ; \
192         LD(x, sa) [src] sasi, %g1 ; \
193         ST(x, da) %g1, [dst] dasi ; \
194         inc     8, src ; \
195         ba      %xcc, 4b ; \
196          inc    8, dst ; \
197         .align 16 ; \
198 5:      deccc   1, len ; \
199         bl,a,pn %xcc, 6f ; \
200          nop ; \
201         LD(ub, sa) [src] sasi, %g1 ; \
202         ST(b, da) %g1, [dst] dasi ; \
203         inc     src ; \
204         ba      %xcc, 5b ; \
205          inc    dst ; \
206 6:
207
208 /*
209  * void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len)
210  */
211 ENTRY(ascopy)
212         wr      %o0, 0, %asi
213         _MEMCPY(%o2, %o1, %o3, a, %asi, a, %asi)
214         retl
215          nop
216 END(ascopy)
217
218 /*
219  * void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len)
220  */
221 ENTRY(ascopyfrom)
222         wr      %o0, 0, %asi
223         _MEMCPY(%o2, %o1, %o3, EMPTY, EMPTY, a, %asi)
224         retl
225          nop
226 END(ascopyfrom)
227
228 /*
229  * void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len)
230  */
231 ENTRY(ascopyto)
232         wr      %o1, 0, %asi
233         _MEMCPY(%o2, %o0, %o3, a, %asi, EMPTY, EMPTY)
234         retl
235          nop
236 END(ascopyto)
237
238 /*
239  * void aszero(u_long asi, vm_offset_t pa, size_t len)
240  */
241 ENTRY(aszero)
242         wr      %o0, 0, %asi
243         _MEMSET(%o1, %g0, %o2, a, %asi)
244         retl
245          nop
246 END(aszero)
247
248 /*
249  * int bcmp(const void *b1, const void *b2, size_t len)
250  */
251 ENTRY(bcmp)
252         brz,pn  %o2, 2f
253          clr    %o3
254 1:      ldub    [%o0 + %o3], %o4
255         ldub    [%o1 + %o3], %o5
256         cmp     %o4, %o5
257         bne,pn  %xcc, 2f
258          inc    %o3
259         deccc   %o2
260         bne,pt  %xcc, 1b
261          nop
262 2:      retl
263          mov    %o2, %o0
264 END(bcmp)
265
266 /*
267  * void bcopy(const void *src, void *dst, size_t len)
268  */
269 ENTRY(bcopy)
270         /*
271          * Check for overlap, and copy backwards if so.
272          */
273         sub     %o1, %o0, %g1
274         cmp     %g1, %o2
275         bgeu,a,pt %xcc, 3f
276          nop
277
278         /*
279          * Copy backwards.
280          */
281         add     %o0, %o2, %o0
282         add     %o1, %o2, %o1
283 1:      deccc   1, %o2
284         bl,a,pn %xcc, 2f
285          nop
286         dec     1, %o0
287         ldub    [%o0], %g1
288         dec     1, %o1
289         ba      %xcc, 1b
290          stb    %g1, [%o1]
291 2:      retl
292          nop
293
294         /*
295          * Do the fast version.
296          */
297 3:      _MEMCPY(%o1, %o0, %o2, EMPTY, EMPTY, EMPTY, EMPTY)
298         retl
299          nop
300 END(bcopy)
301
302 /*
303  * void bzero(void *b, size_t len)
304  */
305 ENTRY(bzero)
306         _MEMSET(%o0, %g0, %o1, EMPTY, EMPTY)
307         retl
308          nop
309 END(bzero)
310
311 /*
312  * int copystr(const void *src, void *dst, size_t len, size_t *done)
313  */
314 ENTRY(copystr)
315         _COPYSTR(%o0, %o1, %o2, %o3, EMPTY, EMPTY, EMPTY, EMPTY)
316         retl
317          mov    %g1, %o0
318 END(copystr)
319
320 /*
321  * void *memcpy(void *dst, const void *src, size_t len)
322  */
323 ENTRY(memcpy)
324         mov     %o0, %o3
325         _MEMCPY(%o3, %o1, %o2, EMPTY, EMPTY, EMPTY, EMPTY)
326         retl
327          nop
328 END(memcpy)
329
330 /*
331  * void *memset(void *b, int c, size_t len)
332  */
333 ENTRY(memset)
334         mov     %o0, %o3
335         _MEMSET(%o3, %o1, %o2, EMPTY, EMPTY)
336         retl
337          nop
338 END(memset)
339
340         .globl  copy_nofault_begin
341 copy_nofault_begin:
342         nop
343
344 /*
345  * int copyin(const void *uaddr, void *kaddr, size_t len)
346  */
347 ENTRY(copyin)
348         wr      %g0, ASI_AIUP, %asi
349         _MEMCPY(%o1, %o0, %o2, EMPTY, EMPTY, a, %asi)
350         retl
351          clr    %o0
352 END(copyin)
353
354 /*
355  * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
356  */
357 ENTRY(copyinstr)
358         wr      %g0, ASI_AIUP, %asi
359         _COPYSTR(%o0, %o1, %o2, %o3, a, %asi, EMPTY, EMPTY)
360         retl
361          mov    %g1, %o0
362 END(copyinstr)
363
364 /*
365  * int copyout(const void *kaddr, void *uaddr, size_t len)
366  */
367 ENTRY(copyout)
368         wr      %g0, ASI_AIUP, %asi
369         _MEMCPY(%o1, %o0, %o2, a, %asi, EMPTY, EMPTY)
370         retl
371          clr    %o0
372 END(copyout)
373
374         .globl  copy_nofault_end
375 copy_nofault_end:
376         nop
377
378 ENTRY(copy_fault)
379         retl
380          mov    EFAULT, %o0
381 END(copy_fault)
382
383         .globl  fs_nofault_begin
384 fs_nofault_begin:
385         nop
386
387 /*
388  * Chatty aliases for fetch, store functions.
389  */
390         .globl  fubyte, fusword, fuword, subyte, susword, suword
391         .set    fubyte, fuword8
392         .set    fusword, fuword16
393         .set    fuword, fuword64
394         .set    subyte, suword8
395         .set    susword, suword16
396         .set    suword, suword64
397
398         .globl  casuword32, casuword, fuptr, suptr
399         .set    casuword, casuword64
400         .set    fuptr, fuword64
401         .set    suptr, suword64
402
403 /*
404  * int32_t casuword32(volatile int32_t *p, int32_t e, int32_t s)
405  */
406 ENTRY(casuword32)
407         casa    [%o0] ASI_AIUP, %o1, %o2
408         retl
409          mov    %o2, %o0
410 END(casuword32)
411
412 /*
413  * int64_t casuword64(volatile int64_t *p, int64_t e, int64_t s)
414  */
415 ENTRY(casuword64)
416         casxa   [%o0] ASI_AIUP, %o1, %o2
417         retl
418          mov    %o2, %o0
419 END(casuword64)
420
421 /*
422  * int fuword8(const void *base)
423  */
424 ENTRY(fuword8)
425         retl
426          lduba  [%o0] ASI_AIUP, %o0
427 END(fuword8)
428
429 /*
430  * int fuword16(const void *base)
431  */
432 ENTRY(fuword16)
433         retl
434          lduha  [%o0] ASI_AIUP, %o0
435 END(fuword16)
436
437 /*
438  * int32_t fuword32(const void *base)
439  */
440 ENTRY(fuword32)
441         retl
442          lduwa  [%o0] ASI_AIUP, %o0
443 END(fuword32)
444
445 /*
446  * int64_t fuword64(const void *base)
447  */
448 ENTRY(fuword64)
449         retl
450          ldxa   [%o0] ASI_AIUP, %o0
451 END(fuword64)
452
453 /*
454  * int suword8(const void *base, int word)
455  */
456 ENTRY(suword8)
457         stba    %o1, [%o0] ASI_AIUP
458         retl
459          clr    %o0
460 END(suword8)
461
462 /*
463  * int suword16(const void *base, int word)
464  */
465 ENTRY(suword16)
466         stha    %o1, [%o0] ASI_AIUP
467         retl
468          clr    %o0
469 END(suword16)
470
471 /*
472  * int suword32(const void *base, int32_t word)
473  */
474 ENTRY(suword32)
475         stwa    %o1, [%o0] ASI_AIUP
476         retl
477          clr    %o0
478 END(suword32)
479
480 /*
481  * int suword64(const void *base, int64_t word)
482  */
483 ENTRY(suword64)
484         stxa    %o1, [%o0] ASI_AIUP
485         retl
486          clr    %o0
487 END(suword64)
488
489         .globl  fs_nofault_intr_begin
490 fs_nofault_intr_begin:
491         nop
492
493 /*
494  * int fuswintr(const void *base)
495  */
496 ENTRY(fuswintr)
497         retl
498          lduha  [%o0] ASI_AIUP, %o0
499 END(fuswintr)
500
501 /*
502  * int suswintr(const void *base, int word)
503  */
504 ENTRY(suswintr)
505         stha    %o1, [%o0] ASI_AIUP
506         retl
507          clr    %o0
508 END(suswintr)
509
510         .globl  fs_nofault_intr_end
511 fs_nofault_intr_end:
512         nop
513
514         .globl  fs_nofault_end
515 fs_nofault_end:
516         nop
517
518 ENTRY(fs_fault)
519         retl
520          mov    -1, %o0
521 END(fsfault)
522
523         .globl  fas_nofault_begin
524 fas_nofault_begin:
525
526 /*
527  * int fasword8(u_long asi, uint64_t addr, uint8_t *val)
528  */
529 ENTRY(fasword8)
530         wr      %o0, 0, %asi
531         membar  #Sync
532         lduba   [%o1] %asi, %o3
533         membar  #Sync
534         stb     %o3, [%o2]
535         retl
536          clr    %o0
537 END(fasword8)
538
539 /*
540  * int fasword16(u_long asi, uint64_t addr, uint16_t *val)
541  */
542 ENTRY(fasword16)
543         wr      %o0, 0, %asi
544         membar  #Sync
545         lduha   [%o1] %asi, %o3
546         membar  #Sync
547         sth     %o3, [%o2]
548         retl
549          clr    %o0
550 END(fasword16)
551
552 /*
553  * int fasword32(u_long asi, uint64_t addr, uint32_t *val)
554  */
555 ENTRY(fasword32)
556         wr      %o0, 0, %asi
557         membar  #Sync
558         lduwa   [%o1] %asi, %o3
559         membar  #Sync
560         stw     %o3, [%o2]
561         retl
562          clr    %o0
563 END(fasword32)
564
565         .globl  fas_nofault_end
566 fas_nofault_end:
567         nop
568
569         .globl  fas_fault
570 ENTRY(fas_fault)
571         retl
572          mov    -1, %o0
573 END(fas_fault)
574
575         .globl  fpu_fault_begin
576 fpu_fault_begin:
577         nop
578
579 /*
580  * void spitfire_block_copy(void *src, void *dst, size_t len)
581  */
582 ENTRY(spitfire_block_copy)
583         rdpr    %pil, %o3
584         wrpr    %g0, PIL_TICK, %pil
585
586         wr      %g0, ASI_BLK_S, %asi
587         wr      %g0, FPRS_FEF, %fprs
588
589         sub     PCB_REG, TF_SIZEOF, %o4
590         ldx     [%o4 + TF_FPRS], %o5
591         andcc   %o5, FPRS_FEF, %g0
592         bz,a,pt %xcc, 1f
593          nop
594         stda    %f0, [PCB_REG + PCB_UFP + (0 * 64)] %asi
595         stda    %f16, [PCB_REG + PCB_UFP + (1 * 64)] %asi
596         stda    %f32, [PCB_REG + PCB_UFP + (2 * 64)] %asi
597         stda    %f48, [PCB_REG + PCB_UFP + (3 * 64)] %asi
598         membar  #Sync
599
600         andn    %o5, FPRS_FEF, %o5
601         stx     %o5, [%o4 + TF_FPRS]
602         ldx     [PCB_REG + PCB_FLAGS], %o4
603         or      %o4, PCB_FEF, %o4
604         stx     %o4, [PCB_REG + PCB_FLAGS]
605
606 1:      wrpr    %o3, 0, %pil
607
608         ldda    [%o0] %asi, %f0
609         add     %o0, 64, %o0
610         sub     %o2, 64, %o2
611
612 2:      ldda    [%o0] %asi, %f16
613         fsrc1   %f0, %f32
614         fsrc1   %f2, %f34
615         fsrc1   %f4, %f36
616         fsrc1   %f6, %f38
617         fsrc1   %f8, %f40
618         fsrc1   %f10, %f42
619         fsrc1   %f12, %f44
620         fsrc1   %f14, %f46
621         stda    %f32, [%o1] %asi
622         add     %o0, 64, %o0
623         subcc   %o2, 64, %o2
624         bz,pn   %xcc, 3f
625          add    %o1, 64, %o1
626         ldda    [%o0] %asi, %f0
627         fsrc1   %f16, %f32
628         fsrc1   %f18, %f34
629         fsrc1   %f20, %f36
630         fsrc1   %f22, %f38
631         fsrc1   %f24, %f40
632         fsrc1   %f26, %f42
633         fsrc1   %f28, %f44
634         fsrc1   %f30, %f46
635         stda    %f32, [%o1] %asi
636         add     %o0, 64, %o0
637         sub     %o2, 64, %o2
638         ba,pt   %xcc, 2b
639          add    %o1, 64, %o1
640
641 3:      membar  #Sync
642
643         stda    %f16, [%o1] %asi
644         membar  #Sync
645
646         retl
647          wr     %g0, 0, %fprs
648 END(spitfire_block_copy)
649
650 /*
651  * void zeus_block_copy(void *src, void *dst, size_t len)
652  */
653 ENTRY(zeus_block_copy)
654         prefetch [%o0 + (0 * 64)], 0
655
656         rdpr    %pil, %o3
657         wrpr    %g0, PIL_TICK, %pil
658
659         wr      %g0, ASI_BLK_S, %asi
660         wr      %g0, FPRS_FEF, %fprs
661
662         sub     PCB_REG, TF_SIZEOF, %o4
663         ldx     [%o4 + TF_FPRS], %o5
664         andcc   %o5, FPRS_FEF, %g0
665         bz,a,pt %xcc, 1f
666          nop
667         stda    %f0, [PCB_REG + PCB_UFP + (0 * 64)] %asi
668         stda    %f16, [PCB_REG + PCB_UFP + (1 * 64)] %asi
669         stda    %f32, [PCB_REG + PCB_UFP + (2 * 64)] %asi
670         stda    %f48, [PCB_REG + PCB_UFP + (3 * 64)] %asi
671         membar  #Sync
672
673         andn    %o5, FPRS_FEF, %o5
674         stx     %o5, [%o4 + TF_FPRS]
675         ldx     [PCB_REG + PCB_FLAGS], %o4
676         or      %o4, PCB_FEF, %o4
677         stx     %o4, [PCB_REG + PCB_FLAGS]
678
679 1:      wrpr    %o3, 0, %pil
680
681         ldd     [%o0 + (0 * 8)], %f0
682         prefetch [%o0 + (1 * 64)], 0
683         ldd     [%o0 + (1 * 8)], %f2
684         prefetch [%o0 + (2 * 64)], 0
685         fmovd   %f0, %f32
686         ldd     [%o0 + (2 * 8)], %f4
687         prefetch [%o0 + (3 * 64)], 0
688         fmovd   %f2, %f34
689         ldd     [%o0 + (3 * 8)], %f6
690         prefetch [%o0 + (4 * 64)], 1
691         fmovd   %f4, %f36
692         ldd     [%o0 + (4 * 8)], %f8
693         prefetch [%o0 + (8 * 64)], 1
694         fmovd   %f6, %f38
695         ldd     [%o0 + (5 * 8)], %f10
696         prefetch [%o0 + (12 * 64)], 1
697         fmovd   %f8, %f40
698         ldd     [%o0 + (6 * 8)], %f12
699         prefetch [%o0 + (16 * 64)], 1
700         fmovd   %f10, %f42
701         ldd     [%o0 + (7 * 8)], %f14
702         ldd     [%o0 + (8 * 8)], %f0
703         sub     %o2, 64, %o2
704         add     %o0, 64, %o0
705         prefetch [%o0 + (19 * 64)], 1
706         ba,pt   %xcc, 2f
707          prefetch [%o0 + (23 * 64)], 1
708         .align  32
709
710 2:      ldd     [%o0 + (1 * 8)], %f2
711         fmovd   %f12, %f44
712         ldd     [%o0 + (2 * 8)], %f4
713         fmovd   %f14, %f46
714         stda    %f32, [%o1] %asi
715         ldd     [%o0 + (3 * 8)], %f6
716         fmovd   %f0, %f32
717         ldd     [%o0 + (4 * 8)], %f8
718         fmovd   %f2, %f34
719         ldd     [%o0 + (5 * 8)], %f10
720         fmovd   %f4, %f36
721         ldd     [%o0 + (6 * 8)], %f12
722         fmovd   %f6, %f38
723         ldd     [%o0 + (7 * 8)], %f14
724         fmovd   %f8, %f40
725         ldd     [%o0 + (8 * 8)], %f0
726         fmovd   %f10, %f42
727         sub     %o2, 64, %o2
728         prefetch [%o0 + (3 * 64)], 0
729         add     %o1, 64, %o1
730         prefetch [%o0 + (24 * 64)], 1
731         add     %o0, 64, %o0
732         cmp     %o2, 64 + 8
733         bgu,pt  %xcc, 2b
734          prefetch [%o0 + (12 * 64)], 1
735         ldd     [%o0 + (1 * 8)], %f2
736         fsrc1   %f12, %f44
737         ldd     [%o0 + (2 * 8)], %f4
738         fsrc1   %f14, %f46
739         stda    %f32, [%o1] %asi
740         ldd     [%o0 + (3 * 8)], %f6
741         fsrc1   %f0, %f32
742         ldd     [%o0 + (4 * 8)], %f8
743         fsrc1   %f2, %f34
744         ldd     [%o0 + (5 * 8)], %f10
745         fsrc1   %f4, %f36
746         ldd     [%o0 + (6 * 8)], %f12
747         fsrc1   %f6, %f38
748         ldd     [%o0 + (7 * 8)], %f14
749         fsrc1   %f8, %f40
750         add     %o1, 64, %o1
751         fsrc1   %f10, %f42
752         fsrc1   %f12, %f44
753         fsrc1   %f14, %f46
754         stda    %f32, [%o1] %asi
755         membar  #Sync
756
757         retl
758          wr     %g0, 0, %fprs
759 END(zeus_block_copy)
760
761 /*
762  * void spitfire_block_zero(void *dst, size_t len)
763  * void zeus_block_zero(void *dst, size_t len)
764  */
765 ALTENTRY(zeus_block_zero)
766 ENTRY(spitfire_block_zero)
767         rdpr    %pil, %o3
768         wrpr    %g0, PIL_TICK, %pil
769
770         wr      %g0, ASI_BLK_S, %asi
771         wr      %g0, FPRS_FEF, %fprs
772
773         sub     PCB_REG, TF_SIZEOF, %o4
774         ldx     [%o4 + TF_FPRS], %o5
775         andcc   %o5, FPRS_FEF, %g0
776         bz,a,pt %xcc, 1f
777          nop
778         stda    %f0, [PCB_REG + PCB_UFP + (0 * 64)] %asi
779         stda    %f16, [PCB_REG + PCB_UFP + (1 * 64)] %asi
780         stda    %f32, [PCB_REG + PCB_UFP + (2 * 64)] %asi
781         stda    %f48, [PCB_REG + PCB_UFP + (3 * 64)] %asi
782         membar  #Sync
783
784         andn    %o5, FPRS_FEF, %o5
785         stx     %o5, [%o4 + TF_FPRS]
786         ldx     [PCB_REG + PCB_FLAGS], %o4
787         or      %o4, PCB_FEF, %o4
788         stx     %o4, [PCB_REG + PCB_FLAGS]
789
790 1:      wrpr    %o3, 0, %pil
791
792         fzero   %f0
793         fzero   %f2
794         fzero   %f4
795         fzero   %f6
796         fzero   %f8
797         fzero   %f10
798         fzero   %f12
799         fzero   %f14
800
801 1:      stda    %f0, [%o0] %asi
802         stda    %f0, [%o0 + 64] %asi
803         stda    %f0, [%o0 + 128] %asi
804         stda    %f0, [%o0 + 192] %asi
805         sub     %o1, 256, %o1
806         brnz,pt %o1, 1b
807          add    %o0, 256, %o0
808         membar  #Sync
809
810         retl
811          wr     %g0, 0, %fprs
812 END(spitfire_block_zero)
813
814         .globl  fpu_fault_end
815 fpu_fault_end:
816         nop
817
818         .globl  fpu_fault_size
819         .set    fpu_fault_size, fpu_fault_end - fpu_fault_begin
820
821 ENTRY(longjmp)
822         set     1, %g3
823         movrz   %o1, %o1, %g3
824         mov     %o0, %g1
825         ldx     [%g1 + _JB_FP], %g2
826 1:      cmp     %fp, %g2
827         bl,a,pt %xcc, 1b
828          restore
829         bne,pn  %xcc, 2f
830          ldx    [%g1 + _JB_SP], %o2
831         cmp     %o2, %sp
832         blt,pn  %xcc, 2f
833          movge  %xcc, %o2, %sp
834         ldx     [%g1 + _JB_PC], %o7
835         retl
836          mov    %g3, %o0
837 2:      PANIC("longjmp botch", %l1)
838 END(longjmp)
839
840 ENTRY(setjmp)
841         stx     %sp, [%o0 + _JB_SP]
842         stx     %o7, [%o0 + _JB_PC]
843         stx     %fp, [%o0 + _JB_FP]
844         retl
845          clr    %o0
846 END(setjmp)
847
848 /*
849  * void ofw_entry(cell_t args[])
850  */
851 ENTRY(ofw_entry)
852         save    %sp, -CCFSZ, %sp
853         SET(ofw_vec, %l7, %l6)
854         ldx     [%l6], %l6
855         rdpr    %pstate, %l7
856         andn    %l7, PSTATE_AM | PSTATE_IE, %l5
857         wrpr    %l5, 0, %pstate
858         SET(tba_taken_over, %l5, %l4)
859         brz,pn  %l4, 1f
860          rdpr   %wstate, %l5
861         andn    %l5, WSTATE_PROM_MASK, %l3
862         wrpr    %l3, WSTATE_PROM_KMIX, %wstate
863 1:      call    %l6
864          mov    %i0, %o0
865         brz,pn  %l4, 1f
866          nop
867         wrpr    %g0, %l5, %wstate
868 1:      wrpr    %l7, 0, %pstate
869         ret
870          restore %o0, %g0, %o0
871 END(ofw_entry)
872
873 /*
874  * void ofw_exit(cell_t args[])
875  */
876 ENTRY(ofw_exit)
877         save    %sp, -CCFSZ, %sp
878         flushw
879         SET(ofw_tba, %l7, %l5)
880         ldx     [%l5], %l5
881         rdpr    %pstate, %l7
882         andn    %l7, PSTATE_AM | PSTATE_IE, %l7
883         wrpr    %l7, 0, %pstate
884         rdpr    %wstate, %l7
885         andn    %l7, WSTATE_PROM_MASK, %l7
886         wrpr    %l7, WSTATE_PROM_KMIX, %wstate
887         wrpr    %l5, 0, %tba                    ! restore the OFW trap table
888         SET(ofw_vec, %l7, %l6)
889         ldx     [%l6], %l6
890         SET(kstack0 + KSTACK_PAGES * PAGE_SIZE - PCB_SIZEOF, %l7, %l0)
891         sub     %l0, SPOFF, %fp                 ! setup a stack in a locked page
892         sub     %l0, SPOFF + CCFSZ, %sp
893         mov     AA_DMMU_PCXR, %l3               ! force primary DMMU context 0
894         sethi   %hi(KERNBASE), %l5
895         stxa    %g0, [%l3] ASI_DMMU
896         flush   %l5
897         wrpr    %g0, 0, %tl                     ! force trap level 0
898         call    %l6
899          mov    %i0, %o0
900         ! never to return
901 END(ofw_exit)
902
903 #ifdef GPROF
904
905 ENTRY(user)
906         nop
907
908 ENTRY(btrap)
909         nop
910
911 ENTRY(etrap)
912         nop
913
914 ENTRY(bintr)
915         nop
916
917 ENTRY(eintr)
918         nop
919
920 /*
921  * XXX including sys/gmon.h in genassym.c is not possible due to uintfptr_t
922  * badness.
923  */
924 #define GM_STATE        0x0
925 #define GMON_PROF_OFF   3
926 #define GMON_PROF_HIRES 4
927
928         .globl  _mcount
929         .set    _mcount, __cyg_profile_func_enter
930
931 ENTRY(__cyg_profile_func_enter)
932         SET(_gmonparam, %o3, %o2)
933         lduw    [%o2 + GM_STATE], %o3
934         cmp     %o3, GMON_PROF_OFF
935         be,a,pn %icc, 1f
936          nop
937         SET(mcount, %o3, %o2)
938         jmpl    %o2, %g0
939          nop
940 1:      retl
941          nop
942 END(__cyg_profile_func_enter)
943
944 #ifdef GUPROF
945
946 ENTRY(__cyg_profile_func_exit)
947         SET(_gmonparam, %o3, %o2)
948         lduw    [%o2 + GM_STATE], %o3
949         cmp     %o3, GMON_PROF_HIRES
950         be,a,pn %icc, 1f
951          nop
952         SET(mexitcount, %o3, %o2)
953         jmpl    %o2, %g0
954          nop
955 1:      retl
956          nop
957 END(__cyg_profile_func_exit)
958
959 #endif /* GUPROF */
960
961 #endif /* GPROF */