]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sparc64/support.S
file: update to 5.34
[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  * void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len)
211  */
212 ENTRY(ascopy)
213         wr      %o0, 0, %asi
214         _MEMCPY(%o2, %o1, %o3, a, %asi, a, %asi)
215         retl
216          nop
217 END(ascopy)
218
219 /*
220  * void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len)
221  */
222 ENTRY(ascopyfrom)
223         wr      %o0, 0, %asi
224         _MEMCPY(%o2, %o1, %o3, EMPTY, EMPTY, a, %asi)
225         retl
226          nop
227 END(ascopyfrom)
228
229 /*
230  * void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len)
231  */
232 ENTRY(ascopyto)
233         wr      %o1, 0, %asi
234         _MEMCPY(%o2, %o0, %o3, a, %asi, EMPTY, EMPTY)
235         retl
236          nop
237 END(ascopyto)
238
239 /*
240  * void aszero(u_long asi, vm_offset_t pa, size_t len)
241  */
242 ENTRY(aszero)
243         wr      %o0, 0, %asi
244         _MEMSET(%o1, %g0, %o2, a, %asi)
245         retl
246          nop
247 END(aszero)
248
249 /*
250  * int bcmp(const void *b1, const void *b2, size_t len)
251  */
252 ENTRY(bcmp)
253         brz,pn  %o2, 2f
254          clr    %o3
255 1:      ldub    [%o0 + %o3], %o4
256         ldub    [%o1 + %o3], %o5
257         cmp     %o4, %o5
258         bne,pn  %xcc, 2f
259          inc    %o3
260         deccc   %o2
261         bne,pt  %xcc, 1b
262          nop
263 2:      retl
264          mov    %o2, %o0
265 END(bcmp)
266
267 /*
268  * void *memmove(void *dst, const void *src, size_t len)
269  * void bcopy(const void *src, void *dst, size_t len)
270  */
271 ENTRY(memmove)
272         /*
273          * Swap src/dst for memmove/bcopy differences
274          */
275         mov     %o0, %o6
276         mov     %o1, %o0
277         mov     %o6, %o1
278 ALTENTRY(bcopy)
279         /*
280          * Check for overlap, and copy backwards if so.
281          */
282         sub     %o1, %o0, %g1
283         cmp     %g1, %o2
284         bgeu,a,pt %xcc, 3f
285          nop
286
287         /*
288          * Copy backwards.
289          */
290         add     %o0, %o2, %o0
291         add     %o1, %o2, %o1
292 1:      deccc   1, %o2
293         bl,a,pn %xcc, 2f
294          nop
295         dec     1, %o0
296         ldub    [%o0], %g1
297         dec     1, %o1
298         ba      %xcc, 1b
299          stb    %g1, [%o1]
300 2:      retl
301          mov    %o6, %o0
302
303         /*
304          * Do the fast version.
305          */
306 3:      _MEMCPY(%o1, %o0, %o2, EMPTY, EMPTY, EMPTY, EMPTY)
307         retl
308          mov    %o6, %o0
309 END(memmove)
310
311 /*
312  * void bzero(void *b, size_t len)
313  */
314 ENTRY(bzero)
315         _MEMSET(%o0, %g0, %o1, EMPTY, EMPTY)
316         retl
317          nop
318 END(bzero)
319
320 /*
321  * int copystr(const void *src, void *dst, size_t len, size_t *done)
322  */
323 ENTRY(copystr)
324         _COPYSTR(%o0, %o1, %o2, %o3, EMPTY, EMPTY, EMPTY, EMPTY)
325         retl
326          mov    %g1, %o0
327 END(copystr)
328
329 /*
330  * void *memcpy(void *dst, const void *src, size_t len)
331  */
332 ENTRY(memcpy)
333         mov     %o0, %o3
334         _MEMCPY(%o3, %o1, %o2, EMPTY, EMPTY, EMPTY, EMPTY)
335         retl
336          nop
337 END(memcpy)
338
339 /*
340  * void *memset(void *b, int c, size_t len)
341  */
342 ENTRY(memset)
343         mov     %o0, %o3
344         _MEMSET(%o3, %o1, %o2, EMPTY, EMPTY)
345         retl
346          nop
347 END(memset)
348
349         .globl  copy_nofault_begin
350 copy_nofault_begin:
351         nop
352
353 /*
354  * int copyin(const void *uaddr, void *kaddr, size_t len)
355  */
356 ENTRY(copyin)
357         wr      %g0, ASI_AIUP, %asi
358         _MEMCPY(%o1, %o0, %o2, EMPTY, EMPTY, a, %asi)
359         retl
360          clr    %o0
361 END(copyin)
362
363 /*
364  * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
365  */
366 ENTRY(copyinstr)
367         wr      %g0, ASI_AIUP, %asi
368         _COPYSTR(%o0, %o1, %o2, %o3, a, %asi, EMPTY, EMPTY)
369         retl
370          mov    %g1, %o0
371 END(copyinstr)
372
373 /*
374  * int copyout(const void *kaddr, void *uaddr, size_t len)
375  */
376 ENTRY(copyout)
377         wr      %g0, ASI_AIUP, %asi
378         _MEMCPY(%o1, %o0, %o2, a, %asi, EMPTY, EMPTY)
379         retl
380          clr    %o0
381 END(copyout)
382
383         .globl  copy_nofault_end
384 copy_nofault_end:
385         nop
386
387 ENTRY(copy_fault)
388         retl
389          mov    EFAULT, %o0
390 END(copy_fault)
391
392         .globl  fs_nofault_begin
393 fs_nofault_begin:
394         nop
395
396 /*
397  * Chatty aliases for fetch, store functions.
398  */
399         .globl  fubyte, fusword, fuword, subyte, susword, suword
400         .set    fubyte, fuword8
401         .set    fusword, fuword16
402         .set    fuword, fuword64
403         .set    subyte, suword8
404         .set    susword, suword16
405         .set    suword, suword64
406
407         .globl  casuword32, casuword, fuptr, suptr
408         .set    casuword, casuword64
409         .set    fuptr, fuword64
410         .set    suptr, suword64
411
412 /*
413  * int32_t casuword32(volatile int32_t *p, int32_t e, int32_t s)
414  */
415 ENTRY(casuword32)
416         casa    [%o0] ASI_AIUP, %o1, %o2
417         retl
418          mov    %o2, %o0
419 END(casuword32)
420
421 /*
422  * int64_t casuword64(volatile int64_t *p, int64_t e, int64_t s)
423  */
424 ENTRY(casuword64)
425         casxa   [%o0] ASI_AIUP, %o1, %o2
426         retl
427          mov    %o2, %o0
428 END(casuword64)
429
430 /*
431  * int fuword8(const void *base)
432  */
433 ENTRY(fuword8)
434         retl
435          lduba  [%o0] ASI_AIUP, %o0
436 END(fuword8)
437
438 /*
439  * int fuword16(const void *base)
440  */
441 ENTRY(fuword16)
442         retl
443          lduha  [%o0] ASI_AIUP, %o0
444 END(fuword16)
445
446 /*
447  * int32_t fuword32(const void *base)
448  */
449 ENTRY(fuword32)
450         retl
451          lduwa  [%o0] ASI_AIUP, %o0
452 END(fuword32)
453
454 /*
455  * int64_t fuword64(const void *base)
456  */
457 ENTRY(fuword64)
458         retl
459          ldxa   [%o0] ASI_AIUP, %o0
460 END(fuword64)
461
462 /*
463  * int suword8(const void *base, int word)
464  */
465 ENTRY(suword8)
466         stba    %o1, [%o0] ASI_AIUP
467         retl
468          clr    %o0
469 END(suword8)
470
471 /*
472  * int suword16(const void *base, int word)
473  */
474 ENTRY(suword16)
475         stha    %o1, [%o0] ASI_AIUP
476         retl
477          clr    %o0
478 END(suword16)
479
480 /*
481  * int suword32(const void *base, int32_t word)
482  */
483 ENTRY(suword32)
484         stwa    %o1, [%o0] ASI_AIUP
485         retl
486          clr    %o0
487 END(suword32)
488
489 /*
490  * int suword64(const void *base, int64_t word)
491  */
492 ENTRY(suword64)
493         stxa    %o1, [%o0] ASI_AIUP
494         retl
495          clr    %o0
496 END(suword64)
497
498         .globl  fs_nofault_end
499 fs_nofault_end:
500         nop
501
502 ENTRY(fs_fault)
503         retl
504          mov    -1, %o0
505 END(fs_fault)
506
507         .globl  fas_nofault_begin
508 fas_nofault_begin:
509
510 /*
511  * int fasword8(u_long asi, uint64_t addr, uint8_t *val)
512  */
513 ENTRY(fasword8)
514         wr      %o0, 0, %asi
515         membar  #Sync
516         lduba   [%o1] %asi, %o3
517         membar  #Sync
518         stb     %o3, [%o2]
519         retl
520          clr    %o0
521 END(fasword8)
522
523 /*
524  * int fasword16(u_long asi, uint64_t addr, uint16_t *val)
525  */
526 ENTRY(fasword16)
527         wr      %o0, 0, %asi
528         membar  #Sync
529         lduha   [%o1] %asi, %o3
530         membar  #Sync
531         sth     %o3, [%o2]
532         retl
533          clr    %o0
534 END(fasword16)
535
536 /*
537  * int fasword32(u_long asi, uint64_t addr, uint32_t *val)
538  */
539 ENTRY(fasword32)
540         wr      %o0, 0, %asi
541         membar  #Sync
542         lduwa   [%o1] %asi, %o3
543         membar  #Sync
544         stw     %o3, [%o2]
545         retl
546          clr    %o0
547 END(fasword32)
548
549         .globl  fas_nofault_end
550 fas_nofault_end:
551         nop
552
553         .globl  fas_fault
554 ENTRY(fas_fault)
555         retl
556          mov    -1, %o0
557 END(fas_fault)
558
559         .globl  fpu_fault_begin
560 fpu_fault_begin:
561         nop
562
563 /*
564  * void spitfire_block_copy(void *src, void *dst, size_t len)
565  */
566 ENTRY(spitfire_block_copy)
567         rdpr    %pstate, %o3
568         wrpr    %g0, PSTATE_NORMAL, %pstate
569
570         wr      %g0, ASI_BLK_S, %asi
571         wr      %g0, FPRS_FEF, %fprs
572
573         sub     PCB_REG, TF_SIZEOF, %o4
574         ldx     [%o4 + TF_FPRS], %o5
575         andcc   %o5, FPRS_FEF, %g0
576         bz,a,pt %xcc, 1f
577          nop
578         stda    %f0, [PCB_REG + PCB_UFP + (0 * VIS_BLOCKSIZE)] %asi
579         stda    %f16, [PCB_REG + PCB_UFP + (1 * VIS_BLOCKSIZE)] %asi
580         stda    %f32, [PCB_REG + PCB_UFP + (2 * VIS_BLOCKSIZE)] %asi
581         stda    %f48, [PCB_REG + PCB_UFP + (3 * VIS_BLOCKSIZE)] %asi
582         membar  #Sync
583
584         andn    %o5, FPRS_FEF, %o5
585         stx     %o5, [%o4 + TF_FPRS]
586         ldx     [PCB_REG + PCB_FLAGS], %o4
587         or      %o4, PCB_FEF, %o4
588         stx     %o4, [PCB_REG + PCB_FLAGS]
589
590 1:      wrpr    %o3, 0, %pstate
591
592         ldda    [%o0] %asi, %f0
593         add     %o0, VIS_BLOCKSIZE, %o0
594         sub     %o2, VIS_BLOCKSIZE, %o2
595
596 2:      ldda    [%o0] %asi, %f16
597         fsrc1   %f0, %f32
598         fsrc1   %f2, %f34
599         fsrc1   %f4, %f36
600         fsrc1   %f6, %f38
601         fsrc1   %f8, %f40
602         fsrc1   %f10, %f42
603         fsrc1   %f12, %f44
604         fsrc1   %f14, %f46
605         stda    %f32, [%o1] %asi
606         add     %o0, VIS_BLOCKSIZE, %o0
607         subcc   %o2, VIS_BLOCKSIZE, %o2
608         bz,pn   %xcc, 3f
609          add    %o1, VIS_BLOCKSIZE, %o1
610         ldda    [%o0] %asi, %f0
611         fsrc1   %f16, %f32
612         fsrc1   %f18, %f34
613         fsrc1   %f20, %f36
614         fsrc1   %f22, %f38
615         fsrc1   %f24, %f40
616         fsrc1   %f26, %f42
617         fsrc1   %f28, %f44
618         fsrc1   %f30, %f46
619         stda    %f32, [%o1] %asi
620         add     %o0, VIS_BLOCKSIZE, %o0
621         sub     %o2, VIS_BLOCKSIZE, %o2
622         ba,pt   %xcc, 2b
623          add    %o1, VIS_BLOCKSIZE, %o1
624
625 3:      membar  #Sync
626
627         stda    %f16, [%o1] %asi
628         membar  #Sync
629
630         retl
631          wr     %g0, 0, %fprs
632 END(spitfire_block_copy)
633
634 /*
635  * void zeus_block_copy(void *src, void *dst, size_t len)
636  */
637 ENTRY(zeus_block_copy)
638         prefetch [%o0 + (0 * VIS_BLOCKSIZE)], 0
639
640         rdpr    %pstate, %o3
641         wrpr    %g0, PSTATE_NORMAL, %pstate
642
643         wr      %g0, ASI_BLK_S, %asi
644         wr      %g0, FPRS_FEF, %fprs
645
646         sub     PCB_REG, TF_SIZEOF, %o4
647         ldx     [%o4 + TF_FPRS], %o5
648         andcc   %o5, FPRS_FEF, %g0
649         bz,a,pt %xcc, 1f
650          nop
651         stda    %f0, [PCB_REG + PCB_UFP + (0 * VIS_BLOCKSIZE)] %asi
652         stda    %f16, [PCB_REG + PCB_UFP + (1 * VIS_BLOCKSIZE)] %asi
653         stda    %f32, [PCB_REG + PCB_UFP + (2 * VIS_BLOCKSIZE)] %asi
654         stda    %f48, [PCB_REG + PCB_UFP + (3 * VIS_BLOCKSIZE)] %asi
655         membar  #Sync
656
657         andn    %o5, FPRS_FEF, %o5
658         stx     %o5, [%o4 + TF_FPRS]
659         ldx     [PCB_REG + PCB_FLAGS], %o4
660         or      %o4, PCB_FEF, %o4
661         stx     %o4, [PCB_REG + PCB_FLAGS]
662
663 1:      wrpr    %o3, 0, %pstate
664
665         ldd     [%o0 + (0 * 8)], %f0
666         prefetch [%o0 + (1 * VIS_BLOCKSIZE)], 0
667         ldd     [%o0 + (1 * 8)], %f2
668         prefetch [%o0 + (2 * VIS_BLOCKSIZE)], 0
669         fmovd   %f0, %f32
670         ldd     [%o0 + (2 * 8)], %f4
671         prefetch [%o0 + (3 * VIS_BLOCKSIZE)], 0
672         fmovd   %f2, %f34
673         ldd     [%o0 + (3 * 8)], %f6
674         prefetch [%o0 + (4 * VIS_BLOCKSIZE)], 1
675         fmovd   %f4, %f36
676         ldd     [%o0 + (4 * 8)], %f8
677         prefetch [%o0 + (8 * VIS_BLOCKSIZE)], 1
678         fmovd   %f6, %f38
679         ldd     [%o0 + (5 * 8)], %f10
680         prefetch [%o0 + (12 * VIS_BLOCKSIZE)], 1
681         fmovd   %f8, %f40
682         ldd     [%o0 + (6 * 8)], %f12
683         prefetch [%o0 + (16 * VIS_BLOCKSIZE)], 1
684         fmovd   %f10, %f42
685         ldd     [%o0 + (7 * 8)], %f14
686         ldd     [%o0 + (8 * 8)], %f0
687         sub     %o2, VIS_BLOCKSIZE, %o2
688         add     %o0, VIS_BLOCKSIZE, %o0
689         prefetch [%o0 + (19 * VIS_BLOCKSIZE)], 1
690         ba,pt   %xcc, 2f
691          prefetch [%o0 + (23 * VIS_BLOCKSIZE)], 1
692         .align  32
693
694 2:      ldd     [%o0 + (1 * 8)], %f2
695         fmovd   %f12, %f44
696         ldd     [%o0 + (2 * 8)], %f4
697         fmovd   %f14, %f46
698         stda    %f32, [%o1] %asi
699         ldd     [%o0 + (3 * 8)], %f6
700         fmovd   %f0, %f32
701         ldd     [%o0 + (4 * 8)], %f8
702         fmovd   %f2, %f34
703         ldd     [%o0 + (5 * 8)], %f10
704         fmovd   %f4, %f36
705         ldd     [%o0 + (6 * 8)], %f12
706         fmovd   %f6, %f38
707         ldd     [%o0 + (7 * 8)], %f14
708         fmovd   %f8, %f40
709         ldd     [%o0 + (8 * 8)], %f0
710         fmovd   %f10, %f42
711         sub     %o2, VIS_BLOCKSIZE, %o2
712         prefetch [%o0 + (3 * VIS_BLOCKSIZE)], 0
713         add     %o1, VIS_BLOCKSIZE, %o1
714         prefetch [%o0 + (24 * VIS_BLOCKSIZE)], 1
715         add     %o0, VIS_BLOCKSIZE, %o0
716         cmp     %o2, VIS_BLOCKSIZE + 8
717         bgu,pt  %xcc, 2b
718          prefetch [%o0 + (12 * VIS_BLOCKSIZE)], 1
719         ldd     [%o0 + (1 * 8)], %f2
720         fsrc1   %f12, %f44
721         ldd     [%o0 + (2 * 8)], %f4
722         fsrc1   %f14, %f46
723         stda    %f32, [%o1] %asi
724         ldd     [%o0 + (3 * 8)], %f6
725         fsrc1   %f0, %f32
726         ldd     [%o0 + (4 * 8)], %f8
727         fsrc1   %f2, %f34
728         ldd     [%o0 + (5 * 8)], %f10
729         fsrc1   %f4, %f36
730         ldd     [%o0 + (6 * 8)], %f12
731         fsrc1   %f6, %f38
732         ldd     [%o0 + (7 * 8)], %f14
733         fsrc1   %f8, %f40
734         add     %o1, VIS_BLOCKSIZE, %o1
735         fsrc1   %f10, %f42
736         fsrc1   %f12, %f44
737         fsrc1   %f14, %f46
738         stda    %f32, [%o1] %asi
739         membar  #Sync
740
741         retl
742          wr     %g0, 0, %fprs
743 END(zeus_block_copy)
744
745 /*
746  * void spitfire_block_zero(void *dst, size_t len)
747  * void zeus_block_zero(void *dst, size_t len)
748  */
749 ALTENTRY(zeus_block_zero)
750 ENTRY(spitfire_block_zero)
751         rdpr    %pstate, %o3
752         wrpr    %g0, PSTATE_NORMAL, %pstate
753
754         wr      %g0, ASI_BLK_S, %asi
755         wr      %g0, FPRS_FEF, %fprs
756
757         sub     PCB_REG, TF_SIZEOF, %o4
758         ldx     [%o4 + TF_FPRS], %o5
759         andcc   %o5, FPRS_FEF, %g0
760         bz,a,pt %xcc, 1f
761          nop
762         stda    %f0, [PCB_REG + PCB_UFP + (0 * VIS_BLOCKSIZE)] %asi
763         stda    %f16, [PCB_REG + PCB_UFP + (1 * VIS_BLOCKSIZE)] %asi
764         stda    %f32, [PCB_REG + PCB_UFP + (2 * VIS_BLOCKSIZE)] %asi
765         stda    %f48, [PCB_REG + PCB_UFP + (3 * VIS_BLOCKSIZE)] %asi
766         membar  #Sync
767
768         andn    %o5, FPRS_FEF, %o5
769         stx     %o5, [%o4 + TF_FPRS]
770         ldx     [PCB_REG + PCB_FLAGS], %o4
771         or      %o4, PCB_FEF, %o4
772         stx     %o4, [PCB_REG + PCB_FLAGS]
773
774 1:      wrpr    %o3, 0, %pstate
775
776         fzero   %f0
777         fzero   %f2
778         fzero   %f4
779         fzero   %f6
780         fzero   %f8
781         fzero   %f10
782         fzero   %f12
783         fzero   %f14
784
785 1:      stda    %f0, [%o0 + (0 * VIS_BLOCKSIZE)] %asi
786         stda    %f0, [%o0 + (1 * VIS_BLOCKSIZE)] %asi
787         stda    %f0, [%o0 + (2 * VIS_BLOCKSIZE)] %asi
788         stda    %f0, [%o0 + (3 * VIS_BLOCKSIZE)] %asi
789         sub     %o1, (4 * VIS_BLOCKSIZE), %o1
790         brnz,pt %o1, 1b
791          add    %o0, (4 * VIS_BLOCKSIZE), %o0
792         membar  #Sync
793
794         retl
795          wr     %g0, 0, %fprs
796 END(spitfire_block_zero)
797
798         .globl  fpu_fault_end
799 fpu_fault_end:
800         nop
801
802         .globl  fpu_fault_size
803         .set    fpu_fault_size, fpu_fault_end - fpu_fault_begin
804
805 ENTRY(longjmp)
806         set     1, %g3
807         movrz   %o1, %o1, %g3
808         mov     %o0, %g1
809         ldx     [%g1 + _JB_FP], %g2
810 1:      cmp     %fp, %g2
811         bl,a,pt %xcc, 1b
812          restore
813         bne,pn  %xcc, 2f
814          ldx    [%g1 + _JB_SP], %o2
815         cmp     %o2, %sp
816         blt,pn  %xcc, 2f
817          movge  %xcc, %o2, %sp
818         ldx     [%g1 + _JB_PC], %o7
819         retl
820          mov    %g3, %o0
821 2:      PANIC("longjmp botch", %l1)
822 END(longjmp)
823
824 ENTRY(setjmp)
825         stx     %sp, [%o0 + _JB_SP]
826         stx     %o7, [%o0 + _JB_PC]
827         stx     %fp, [%o0 + _JB_FP]
828         retl
829          clr    %o0
830 END(setjmp)
831
832 /*
833  * void ofw_entry(cell_t args[])
834  */
835 ENTRY(ofw_entry)
836         save    %sp, -CCFSZ, %sp
837         SET(ofw_vec, %l7, %l6)
838         ldx     [%l6], %l6
839         rdpr    %pstate, %l7
840         andn    %l7, PSTATE_AM | PSTATE_IE, %l5
841         wrpr    %l5, 0, %pstate
842         SET(tba_taken_over, %l5, %l4)
843         brz,pn  %l4, 1f
844          rdpr   %wstate, %l5
845         andn    %l5, WSTATE_PROM_MASK, %l3
846         wrpr    %l3, WSTATE_PROM_KMIX, %wstate
847 1:      call    %l6
848          mov    %i0, %o0
849         brz,pn  %l4, 1f
850          nop
851         wrpr    %g0, %l5, %wstate
852 1:      wrpr    %l7, 0, %pstate
853         ret
854          restore %o0, %g0, %o0
855 END(ofw_entry)
856
857 /*
858  * void ofw_exit(cell_t args[])
859  */
860 ENTRY(ofw_exit)
861         save    %sp, -CCFSZ, %sp
862         flushw
863         SET(ofw_tba, %l7, %l5)
864         ldx     [%l5], %l5
865         rdpr    %pstate, %l7
866         andn    %l7, PSTATE_AM | PSTATE_IE, %l7
867         wrpr    %l7, 0, %pstate
868         rdpr    %wstate, %l7
869         andn    %l7, WSTATE_PROM_MASK, %l7
870         wrpr    %l7, WSTATE_PROM_KMIX, %wstate
871         wrpr    %l5, 0, %tba                    ! restore the OFW trap table
872         SET(ofw_vec, %l7, %l6)
873         ldx     [%l6], %l6
874         SET(kstack0 + KSTACK_PAGES * PAGE_SIZE - PCB_SIZEOF, %l7, %l0)
875         sub     %l0, SPOFF, %fp                 ! setup a stack in a locked page
876         sub     %l0, SPOFF + CCFSZ, %sp
877         mov     AA_DMMU_PCXR, %l3               ! force primary DMMU context 0
878         sethi   %hi(KERNBASE), %l5
879         stxa    %g0, [%l3] ASI_DMMU
880         flush   %l5
881         wrpr    %g0, 0, %tl                     ! force trap level 0
882         call    %l6
883          mov    %i0, %o0
884         ! never to return
885 END(ofw_exit)
886
887 #ifdef GPROF
888
889 ENTRY(user)
890         nop
891
892 ENTRY(btrap)
893         nop
894
895 ENTRY(etrap)
896         nop
897
898 ENTRY(bintr)
899         nop
900
901 ENTRY(eintr)
902         nop
903
904 /*
905  * XXX including sys/gmon.h in genassym.c is not possible due to uintfptr_t
906  * badness.
907  */
908 #define GM_STATE        0x0
909 #define GMON_PROF_OFF   3
910 #define GMON_PROF_HIRES 4
911
912         .globl  _mcount
913         .set    _mcount, __cyg_profile_func_enter
914
915 ENTRY(__cyg_profile_func_enter)
916         SET(_gmonparam, %o3, %o2)
917         lduw    [%o2 + GM_STATE], %o3
918         cmp     %o3, GMON_PROF_OFF
919         be,a,pn %icc, 1f
920          nop
921         SET(mcount, %o3, %o2)
922         jmpl    %o2, %g0
923          nop
924 1:      retl
925          nop
926 END(__cyg_profile_func_enter)
927
928 #ifdef GUPROF
929
930 ENTRY(__cyg_profile_func_exit)
931         SET(_gmonparam, %o3, %o2)
932         lduw    [%o2 + GM_STATE], %o3
933         cmp     %o3, GMON_PROF_HIRES
934         be,a,pn %icc, 1f
935          nop
936         SET(mexitcount, %o3, %o2)
937         jmpl    %o2, %g0
938          nop
939 1:      retl
940          nop
941 END(__cyg_profile_func_exit)
942
943 #endif /* GUPROF */
944
945 #endif /* GPROF */