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