1/*        $NetBSD: byte_swap_8.S,v 1.2 2009/12/14 00:39:00 matt Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 *        The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <mips/asm.h>
36
37#if defined(LIBC_SCCS) && !defined(lint)
38          RCSID("$NetBSD: byte_swap_8.S,v 1.2 2009/12/14 00:39:00 matt Exp $")
39#endif /* LIBC_SCCS and not lint */
40
41#undef _LOCORE
42#define _LOCORE               /* XXX not really, just assembly-code source */
43#include <machine/endian.h>
44
45NLEAF(bswap64)      # a0 = 0xffeeddccbbaa9988 return 0x8899aabbccddeeff
46#if (__mips == 32 || __mips == 64) && __mips_isa_rev == 2
47#if !defined(__mips_o32)
48          /*
49           * If we are on MIPS32r2 or MIPS64r2 use the new instructions.
50           */
51          dsbh      v0, a0                        # dwords swap bytes within halfwords
52          dshd      v0, v0                        # dwords swap halwords within dwords
53          j         ra
54#else /* defined(__mips_o32) */
55          /*
56           * If we are on MIPS32r2 or MIPS64r2 use the new instructions.
57           * (except we must use the 32bit versions)
58           */
59          wsbh      v1, a0                        # word swap bytes within halfwords
60          wsbh      v0, a1                        # word swap bytes within halfwords
61          rotr      v1, v1, 16                    # rotate word 16bits and swap word
62          rotr      v0, v0, 16                    # rotate word 16bits and swap word
63          j         ra
64#endif /* defined(__mips_o32) */
65#elif !defined(__mips_o32)
66                                                  # a0  = 0xffeeddccbbaa9988
67          li        t0, 0xffff                    # t0  = 0x000000000000ffff
68          dsll      t1, t0, 32                    # t1  = 0x0000ffff00000000
69          or        t0, t1                        # t0  = 0x0000ffff0000ffff
70          dsll      t2, t0, 8           # t2  = 0x00ffff0000ffff00
71          xor       t2, t0                        # t2  = 0x00ff00ff00ff00ff
72          /*
73           * We could swap by halfword, but that would be one instruction longer.
74           */
75          dsrl      ta0, a0, 32                   # ta0 = 0x00000000ffeeddcc
76          dsll      ta1, a0, 32                   # ta1 = 0xbbaa998800000000
77          or        a1, ta0, ta1                  # a1  = 0xbbaa9988ffeeddcc
78                                                  # words swapped
79          and       ta0, a1, t0                   # ta0 = 0x000099880000ddcc
80          dsrl      ta1, a1, 16                   # ta1 = 0x0000bbaa9988ffee
81          and       ta1, t0                       # ta1 = 0x0000bbaa0000ffee
82          dsll      a2, ta0, 16                   # a2  = 0x99880000ddcc0000
83          or        a2, ta1                       # a2  = 0x9988bbaaddccffee
84                                                  # halfwords swapped
85          and       ta0, a2, t2                   # ta0 = 0x008800aa00cc00ee
86          dsrl      ta1, a2, 8                    # ta1 = 0x009988bbaaddccff
87          and       ta1, t2                       # ta1 = 0x009900bb00dd00ff
88          dsll      v0, ta0, 8                    # v0  = 0x8800aa00cc00ee00
89          or        v0, ta1                       # v0  = 0x8899aabbccddeeff
90                                                  # bytes swapped
91          j         ra
92#else /* defined(__mips_o32) */
93          /*
94           * 32bit ABI.
95           */
96                                                  # a0  = 0xccddeeff
97                                                  # a1  = 0x8899aabb
98          srl       t0, a0, 24                    # t0  = 0x000000cc
99          srl       t1, a1, 24                    # t1  = 0x00000088
100          sll       ta0, a0, 24                   # ta0 = 0xff000000
101          sll       ta1, a1, 24                   # ta1 = 0xbb000000
102          or        ta0, ta0, t0                  # ta0 = 0xff0000cc
103          or        ta1, ta1, t1                  # ta1 = 0xbb000088
104          and       t0, a0, 0xff00                # t0  = 0x0000ee00
105          and       t1, a1, 0xff00                # t1  = 0x0000aa00
106          sll       t0, t0, 8           # t0  = 0x00ee0000
107          sll       t1, t1, 8           # t1  = 0x00aa0000
108          or        ta0, ta0, t0                  # ta0 = 0xffee00cc
109          or        ta1, ta1, t1                  # ta1 = 0xbbaa0088
110          srl       t0, a0, 8           # t0  = 0x00ccddee
111          srl       t1, a1, 8           # t1  = 0x008899aa
112          and       t0, t0, 0xff00                # t0  = 0x0000dd00
113          and       t1, t1, 0xff00                # t1  = 0x00009900
114          or        v1, ta0, t0                   # v1  = 0xffeeddcc
115          or        v0, ta1, t1                   # v0  = 0xbbaa9988
116          j         ra
117#endif /* defined(__mips_o32) */
118END(bswap64)
119