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