linux-mips
[Top] [All Lists]

Byte swapping versions of insl & outsl

To: Linux SGI <linux@cthulhu.engr.sgi.com>
Subject: Byte swapping versions of insl & outsl
From: "Andrew R. Baker" <andrewb@uab.edu>
Date: Thu, 21 Oct 1999 18:14:15 -0500 (CDT)
Cc: linux-mips@fnet.fr, linux-mips@vger.rutgers.edu
Sender: owner-linuxmips@oss.sgi.com
I needed these to get a 3COM Etherlink III working in the Indigo2.  I
don't know if anyone else could use them, but here they are.  I might be
able to come up with an algorithm that uses one or two fewer instructions.
The can probably be optimised to only use 3 registers instead of 4.  But 
thay are still a lot better than four consecutive insb/outsb.  If other
people are planning on using these I'll do it sooner rather than later.  
I'll try and sneak them into the CVS archive sometime soon ;)


/* 
 * Byte swapping versions of insl and outsl.  I needed these to get the
 * Etherlink III working efficiently on the Indigo2.  They might be useful
 * in porting other ISA drivers to big-endian architectures
 *
 * -Andrew
 */


extern inline void insl_sw(unsigned int port, void * addr, unsigned long count)
{
        if (count) __asm__ __volatile__ (
                ".set\tnoreorder\n\t"
                ".set\tnoat\n"
                "1:\tlw\t$1,%4(%5)\n\t"
                "subu\t%1,1\n\t"
                "sll\t$2,$1,24\n\t"
                "srl\t$3,$1,24\n\t"
                "or\t$4,$2,$3\n\t"
                "sll\t$2,$1,8\n\t"
                "srl\t$1,$2,16\n\t"
                "andi\t$2,$1,65280\n\t"
                "andi\t$3,$1,255\n\t"
                "sll\t$1,$3,16\n\t"
                "or\t$3,$2,$1\n\t"
                "or\t$1,$4,$3\n\t"
                "sw\t$1,(%0)\n\t"
                "bne\t$0,%1,1b\n\t"
                "addiu\t%0,%6\n\t"
                ".set\tat\n\t"
                ".set\treorder"
                : "=r" (addr), "=r" (count)
                : "0" (addr), "1" (count), "i" (0), "r" 
(mips_io_port_base+port), "I" ( 4 )
                : "$1", "$2", "$3", "$4" );
}

extern inline void outsl_sw(unsigned int port, void * addr, unsigned long count)
{
        if (count) __asm__ __volatile__ (
                ".set\tnoreorder\n\t"
                ".set\tnoat\n"
                "1:\tlw\t$1,(%0)\n\t"
                "subu\t%1,1\n\t"
                "sll\t$2,$1,24\n\t"
                "srl\t$3,$1,24\n\t"
                "or\t$4,$2,$3\n\t"
                "sll\t$2,$1,8\n\t"
                "srl\t$1,$2,16\n\t"
                "andi\t$2,$1,65280\n\t"
                "andi\t$3,$1,255\n\t"
                "sll\t$1,$3,16\n\t"
                "or\t$3,$2,$1\n\t"
                "or\t$1,$4,$3\n\t"
                "sw\t$1,%4(%5)\n\t"
                "bne\t$0,%1,1b\n\t"
                "addiu\t%0,%6\n\t"
                ".set\tat\n\t"
                ".set\treorder"
                : "=r" (addr), "=r" (count)
                : "0" (addr), "1" (count), "i" (0), "r" 
(mips_io_port_base+port), "I" ( 4 )
                : "$1", "$2", "$3", "$4" );
}





<Prev in Thread] Current Thread [Next in Thread>
  • Byte swapping versions of insl & outsl, Andrew R. Baker <=