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