There are many ARM cores as described at Wikipedia. The processors get more complex as they evolve and occasionally new instructions are introduced. One instance is the rev instruction which will reverse the bytes in a word e.g. for converting big-endian numbers to little-endian and vice versa.
In my Sheeva Plug there is a version 5TE processor (which does not support this instruction); my Raspberry Pi has a version 6 processor (which does).
I would like to keep my code in one source file, and dynamically assemble the optimum code for the processor upon which it was built.
We can use the macro assembler of the GNU assembler to achieve this.
.if ARCH >= 6 rev r0, r0 .else and r2, r0, #0xff000000 @ load the top 2 bytes to r2 and r3, r0, #0x00ff0000 @ load the next 2 bytes to r3 and r4, r0, #0x0000ff00 @ load the next 2 bytes to r4 and r5, r0, #0x000000ff @ load the bottom 2 bytes to r5 mov r0, r2, lsr #24 @ shift r2 bytes to bottom and store to r0 orr r0, r3, lsr #8 @ or the remaining shifted data orr r0, r4, lsl #8 orr r0, r5, lsl #24 .endif
We can interrogate the machine at build time by looking inside /proc/cpuinfo via
cat /proc/cpuinfo | grep ^Processor which gives :
- On A SheevaPlug : Processor : Feroceon 88FR131 rev 1 (v5l)
- On A Raspberry Pi : Processor : ARMv6-compatible processor rev 7 (v6l)
And then we pull the appropriate number within the Makefile and then we can build via make endian using the following Makefile
AS := /usr/bin/as LD := /usr/bin/ld ASOPTS := -gstabs ARCH = $(shell sed -ne 's/^Processor\s*:.*(v\([0-9]\)l)/\1/p' /proc/cpuinfo) endian: endian.s echo ARCH is $(ARCH) $(AS) $(ASOPTS) --defsym ARCH=$(ARCH) -march=armv$(ARCH) -o $@.o $^ $(LD) -o $@ $@.o