Hi,actually i need to run big endian code but i don't know how to set endian option in cp15 registers could any suggest me how to set EE bit set
no.actually only data access can be made as big endian remaining almost same for bigendian
If you use --bigend for building it will build the library in big endian format for RVDS, but i need to know which command i need to give in linux to build the code to big endian.
In linux how can i give the endian option acutally -mbig-endian is not supporting,so please tell the correct option in linux
I believe that big-endian support is an optional compile time build option for the GCC compiler itself, and not many pre-built versions for ARM support it as it is so rarely used, so you may need to re-build your own compiler with big-endian support.
Hello ranjithkumards,
do you ask how to set EE bit of SCTLR?
If SCTLR.EE=1, the data access is performed by big-endian although instruction access is little-endian..
MRC p15, 0, r0, c1, c0, 0 @ Read SCTLR into R0 ORR r0, r0, (1<<25) @ Set EE bit position MCR p15, 0, r0, c1, c0, 0 @ Write R0 to SCTLR
The sequence will set EE bit.
Is this your answer?
Best regards,
Yasuhiko Koumoto.
hi what is the meaning of "you may need to re-build your own compiler with big-endian support"?.
You will have to build a custom build of GCC, configured to include big-endian support.
This generally doesn't work unless you write the whole code sequence with "other endianness" in assembler. The compiler will make implicit memory accesses (such as stacking, and literal pool access) and therefore needs to have visibility / control of what the current endianness is; i.e. overriding directly via assembler is only going to work if you change back to "compiler endianness" before returning to C code.
Oh, thanks Harris
Hello Peter,
your comment is true. But I think we can dynamically access the data area by making special functions as following (for example).
Of course, these functions should be executed in the privileged mode.
How do you think about the idea?
/* short GetHalf(long *addr) */ GetHalf: PUSH {r10} MRC p15, 0, r10, c1, c0, 0 ORR r10, r10, (1<<25) MCR p15, 0, r10, c1, c0, 0 LDRH r0, [r0] MRC p15, 0, r10, c1, c0, 0 ORR r10, r10, (1<<25) EOR r10, r10, (1<<25) MCR p15, 0, r10, c1, c0, 0 POP {r10} BX lr /* void PutHalf(long *addr, long data) */ PutHalf: PUSH {r10} MRC p15, 0, r10, c1, c0, 0 ORR r10, r10, (1<<25) MCR p15, 0, r10, c1, c0, 0 STRH r1, [r0] MRC p15, 0, r10, c1, c0, 0 ORR r10, r10, (1<<25) EOR r10, r10, (1<<25) MCR p15, 0, r10, c1, c0, 0 POP {r10} BX lr
It's a very expensive way of doing it. If you are going to do functions to load single fields from memory then just use little-endian loads and use the "rev" instruction to reverse the result - it's only one additional instruction and much faster (and small enough to be inlined so you avoid the function overhead too).
It's only worth switching the whole processor data endianness if you are going to load a large block of data, and want to avoid executing hundreds of instructions to reverse the data.
Pete