[uClinux-dev] $linux/arch/armnommu/lib/bitops.S (endian) ??

From: Kwanghoon Choi (khchoi@ruby.kaist.ac.kr)
Date: Thu Apr 19 2001 - 09:45:45 EDT


Dear Sir,

I am trying to port uClinux on our ARM-based embedded system. Our
system uses the ARM processor in BIG-ENDIAN MODE. In uClinux-2.0.x, 
we suspect that some routines are developed solely for little-endian mode. 
In $LINUX/arch/armnommu/lib/bitops.S,
(http://cvs.uclinux.org/cgi-bin/cvsweb/uClinux-2.0.x/arch/armnommu/lib/bitops.S)
there are five functions written in ARM assembly language: set_bit(), 
clear_bit(), change_bit(), find_zero_bit(), find_next_zero_bit().   
The code for set_bit() function is as follows.

=============================================================================
set_bit:  int set_bit(int bit, int *addr)
-----------------------------------------------------------------------------
input : r0 -> bit, r1 -> addr
        0<= r0 < 32(=2^5)
=============================================================================
add r1, r1, r0, lsr #3  // r0, lsr #3 => (0 <= r0 < 32)/ 8(=2^3)
                        //            => (0 <= r0' < 4) (quotient)
                        // add r1, r1, r0' => r1 <- r1 + (0 <= r0' < 4)
and r3, r0, #7          // r3 <- r0 & 0x111, i.e. r0 - (r0/8) * 8
(remainder)
mov r0, #1              // r0 <- 0x1
SAVEIRQS(ip)
DISABLEIRQS(ip)
ldrb r2, [r1]           // r2 <- mem[r1]
                        // r1            => byte-indexing
tst r2, r0, lsl r3      // r0, lsl r3    => bit-indexing
                        //               => set Z flag (checked by <cond> `eq')
orr r2, r2, r0, lsl r3  // r0, lsl r3    => bit-indexing
moveq r0, #0            // r0 <- 0 if Z flag =1  => set return-value
                        //       1 otherwise
strb r2, [r1]           // mem[r1] <- r2
RESTOREIRQS(ip)
RETINSTR(mov,pc,lr)
=============================================================================

According to the above code, this C code

                int v = 0x00000000;    // 32bit

                setbit(8, &v);         // set 8th bit of 0th~31st bits
                printf("%08x", v);     // print `v'

prints 0 x 00 01 00 00, though I expect that the C code 
prints 0 x 00 00 01 00. From this result, we suspect the above 
instructions are developed for little-endian mode. For big-endian mode, 
I think that the first instruction `add r1, r1, r0, lsr #3' must be 
revised as this:

mov r2, r0, lsr #3
eor r2, r2, #3
add r1, r1, r2

// add r1, r1, r0, lsr #3  // r0, lsr #3 => (0 <= r0 < 32)/8  (=2^3)
//                         //            => (0 <= r0' < 4) (quotient)
//                         // add r1, r1, r0' => r1 <- r1 + (0 <= r0' < 4)

My questions:

 * Was this source program  developed solely for little-endian mode? 
 * Or, did authors intentionally treat data in little-endian mode uniformly, 
   no matter what their ARM processors are either in little-endian mode or 
   in big-endian mode?

Please, let me know what goes on. I will also please if one leads
me to any documentation/experience about porting uClinux on BIG-ENDIAN ARM
processors.

Thanks in advance.

Kwanghoon Choi

P.S. You can see our own revision of `bitops.S' for big-endian mode.
     I enclose the source program in this mail.




This message resent by the uclinux-dev@uclinux.org list server http://www.uClinux.org/

This archive was generated by hypermail 2.1.4 : Thu Sep 19 2002 - 13:19:40 EDT