Recently I have taken up an interest in learning "bare-metal" development for ARM processors using native assembly. I bought a Raspberry Pi Zero which features an ARM11 processor, and am currently looking for a toolchain to assemble and link my code. It says on this page that only the A, R and M profiles are supported by the GNU Toolchain for Arm Processors, but I have come across this source which indicates that GCC is capable of compiling code for Arm architectures all the way back to ARMv4, and indeed supports the processor that I want to compile for (ARM1176JZF-S). Is there something I'm missing here? These are conflicting sources, are they not? And if the GNU Toolchain does not in fact support the ARM11 processor, what other options do I have?
Just try it
.cpu arm7tdmi
.globl _start
_start:
bl main
b .
.globl bounce
bounce:
bx lr
int bounce ( int x );
int main ( void )
{
return(bounce(3));
}
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
arm-none-eabi-as --version
GNU assembler (GNU Binutils) 2.34
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -march=armv4t so.c -o so.o
arm-none-eabi-ld -Ttext=0x1000 start.o so.o -o so.elf
arm-none-eabi-objdump -d so.elf
Disassembly of section .text:
00001000 <main>:
1000: e92d4010 push {r4, lr}
1004: e3a00003 mov r0, #3
1008: eb000003 bl 101c <bounce>
100c: e8bd4010 pop {r4, lr}
1010: e12fff1e bx lr
00001014 <_start>:
1014: ebfffff9 bl 1000 <main>
1018: eafffffe b 1018 <_start+0x4>
0000101c <bounce>:
101c: e12fff1e bx lr
(no this is not a complete functional program, just a tools demonstration)
Remember that gnu binutils (assembler, linker and other binary utilities) and gnu gcc (c compiler) are two separate projects so there is the expectation that they are not perfectly in sync one may support things the other doesn't.
I think they dropped support for the armv2/3 which is the acorn, actual chip stuff in recent tools perhaps gcc.
arm-none-eabi-gcc -O2 -c -mcpu=arm2 so.c -o so.o
arm-none-eabi-gcc: error: unrecognized -mcpu target: arm2
arm-none-eabi-gcc: note: valid arguments are: arm8 arm810 strongarm
strongarm110 fa526 fa626 arm7tdmi arm7tdmi-s arm710t arm720t arm740t arm9 arm9tdmi arm920t arm920 arm922t arm940t ep9312 arm10tdmi arm1020t arm9e arm946e-s arm966e-s arm968e-s arm10e arm1020e arm1022e xscale iwmmxt iwmmxt2 fa606te fa626te fmp626 fa726te arm926ej-s arm1026ej-s arm1136j-s arm1136jf-s arm1176jz-s arm1176jzf-s mpcorenovfp mpcore arm1156t2-s arm1156t2f-s cortex-m1 cortex-m0 cortex-m0plus cortex-m1.small-multiply cortex-m0.small-multiply cortex-m0plus.small-multiply generic-armv7-a cortex-a5 cortex-a7 cortex-a8 cortex-a9 cortex-a12 cortex-a15 cortex-a17 cortex-r4 cortex-r4f cortex-r5 cortex-r7 cortex-r8 cortex-m7 cortex-m4 cortex-m3 marvell-pj4 cortex-a15.cortex-a7 cortex-a17.cortex-a7 cortex-a32 cortex-a35 cortex-a53 cortex-a57 cortex-a72 cortex-a73 exynos-m1 xgene1 cortex-a57.cortex-a53 cortex-a72.cortex-a53 cortex-a73.cortex-a35 cortex-a73.cortex-a53 cortex-a55 cortex-a75 cortex-a76 neoverse-n1 cortex-a75.cortex-a55 cortex-a76.cortex-a55 cortex-m23 cortex-m33 cortex-r52; did you mean ‘arm8’?
arm-none-eabi-gcc -O2 -c -march=armv2a so.c -o so.o
arm-none-eabi-gcc: error: unrecognized -march target: armv2a
arm-none-eabi-gcc: note: valid arguments are: armv4 armv4t armv5t armv5te armv5tej armv6 armv6j armv6k armv6z armv6kz armv6zk armv6t2 armv6-m armv6s-m armv7 armv7-a armv7ve armv7-r armv7-m armv7e-m armv8-a armv8.1-a armv8.2-a armv8.3-a armv8.4-a armv8.5-a armv8-m.base armv8-m.main armv8-r iwmmxt iwmmxt2; did you mean ‘armv4’?
Where older versions of gcc were fine with it.
.cpu arm2
.globl _start
_start:
bl main
b .
No warnings/errors
100c: e8bd4010 pop {r4, lr}
1010: e12fff1e bx lr
that means armv4t vs:
arm-none-eabi-gcc -O2 -c -march=armv5t so.c -o so.o
arm-none-eabi-objdump -D so.o
so.o: file format elf32-littlearm
Disassembly of section .text.startup:
00000000 <main>:
0: e3a00003 mov r0, #3
4: eafffffe b 0 <bounce>
hmm they went so far as to make it a tail optimization, okay.
int bounce ( int x );
int main ( void )
{
return(bounce(3)+2);
}
00000000 <main>:
0: e92d4010 push {r4, lr}
4: e3a00003 mov r0, #3
8: ebfffffe bl 0 <bounce>
c: e2800002 add r0, r0, #2
10: e8bd8010 pop {r4, pc}
A difference between armv4t and armv5t is you can pop pc but you cant use it for arm/thumb interwork so the compiler unless possibly told, will generate interwork compatible code.
So yes even with gcc 9.3.0 it is supported. I used the wrong computer, I thought I had the latest on this one, will edit the answer with 10.2.0
Yes, I should just rewrite this, maybe I will...
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
arm-none-eabi-as --version
GNU assembler (GNU Binutils) 2.35
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.
.cpu arm2
.globl _start
_start:
bl main
b .
.globl bounce
bounce:
@ bx lr
mov pc,lr
arm-none-eabi-as start.s -o start.o
arm-none-eabi-objdump -d start.o
start.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: ebfffffe bl 0 <main>
4: eafffffe b 4 <_start+0x4>
00000008 <bounce>:
8: e1a0f00e mov pc, lr
Or try the original program
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -march=armv4t so.c -o so.o
arm-none-eabi-ld -Ttext=0x1000 start.o so.o -o so.elf
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <main>:
1000: e92d4010 push {r4, lr}
1004: e3a00003 mov r0, #3
1008: eb000003 bl 101c <bounce>
100c: e8bd4010 pop {r4, lr}
1010: e12fff1e bx lr
00001014 <_start>:
1014: ebfffff9 bl 1000 <main>
1018: eafffffe b 1018 <_start+0x4>
0000101c <bounce>:
101c: e12fff1e bx lr
so 10.2.0 and 2.35 both support this core/cpu.
arm-none-eabi-gcc -O2 -c -march=arm2a so.c -o so.o
arm-none-eabi-gcc: error: unrecognized -march target: arm2a
arm-none-eabi-gcc: note: valid arguments are: armv4 armv4t armv5t armv5te armv5tej armv6 armv6j armv6k armv6z armv6kz armv6zk armv6t2 armv6-m armv6s-m armv7 armv7-a armv7ve armv7-r armv7-m armv7e-m armv8-a armv8.1-a armv8.2-a armv8.3-a armv8.4-a armv8.5-a armv8.6-a armv8-m.base armv8-m.main armv8-r armv8.1-m.main iwmmxt iwmmxt2
arm-none-eabi-gcc: error: missing argument to ‘-march=’
arm-none-eabi-gcc -O2 -c -mcpu=arm2 so.c -o so.o
arm-none-eabi-gcc: error: unrecognized -mcpu target: arm2
arm-none-eabi-gcc: note: valid arguments are: arm8 arm810 strongarm strongarm110 fa526 fa626 arm7tdmi arm7tdmi-s arm710t arm720t arm740t arm9 arm9tdmi arm920t arm920 arm922t arm940t ep9312 arm10tdmi arm1020t arm9e arm946e-s arm966e-s arm968e-s arm10e arm1020e arm1022e xscale iwmmxt iwmmxt2 fa606te fa626te fmp626 fa726te arm926ej-s arm1026ej-s arm1136j-s arm1136jf-s arm1176jz-s arm1176jzf-s mpcorenovfp mpcore arm1156t2-s arm1156t2f-s cortex-m1 cortex-m0 cortex-m0plus cortex-m1.small-multiply cortex-m0.small-multiply cortex-m0plus.small-multiply generic-armv7-a cortex-a5 cortex-a7 cortex-a8 cortex-a9 cortex-a12 cortex-a15 cortex-a17 cortex-r4 cortex-r4f cortex-r5 cortex-r7 cortex-r8 cortex-m7 cortex-m4 cortex-m3 marvell-pj4 cortex-a15.cortex-a7 cortex-a17.cortex-a7 cortex-a32 cortex-a35 cortex-a53 cortex-a57 cortex-a72 cortex-a73 exynos-m1 xgene1 cortex-a57.cortex-a53 cortex-a72.cortex-a53 cortex-a73.cortex-a35 cortex-a73.cortex-a53 cortex-a55 cortex-a75 cortex-a76 cortex-a76ae cortex-a77 neoverse-n1 cortex-a75.cortex-a55 cortex-a76.cortex-a55 cortex-m23 cortex-m33 cortex-m35p cortex-m55 cortex-r52; did you mean ‘arm8’?
arm-none-eabi-gcc: error: missing argument to ‘-march=’
You can see the arm1176jzf-s versions in there of which one is in the raspberry pi zero.
arm-none-eabi- vs arm-linux-gnueabi-, arm-whatever-whatever unless possibly configured in the build of the tool, will all support the same targets for the same version of gcc (or binutils).
EDIT NOTE
arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
arm-linux-gcc -mno-thumb-interwork -O2 -c -mcpu=arm2 -march=armv2a so.c -o so.o
So this is along the lines of does gcc support armxyz. The arm2/3 was dropped recently but older versions do/did support it (there is at least one open core armv2/3 out there that is I guess license free so if you want to use it you will want some tools).
But from the above demonstration with the current tools as of this writing (10.2.0 and 2.35) the armv4/4t up to the present (armv7-a/r/m) appear supported by gcc and binutils.
So since they did purge the arm2/3 at one point which probably wasn't too hard, there is an overlap between the arm2/3 and the present armv4 to armv7 as far as the machine code goes, there are some instructions in arm2/3 that didn't make it across the acorn/advanced transition (chips to cores, different companies) some/many overlap. As with the overlap from armv4 to armv7. So technically they may wish for example to remove armv4 support at some point as it has some things as shown above that are special cased. But if you bother to dig into the sources, you will find they appear to be held together with duct tape and bailing wire, so I cant imagine there would be a strong desire to go in and rip stuff out, even if you simply searched for armv4 or armv5 or armv6 or whatever the variable name for the flag is that indicates these.
They have done it before and they might again, so be prepared, test each build of the tools when you switch to it or better yet be explicit in your build so that if/when the tool drops support it will fail to build.
What you do in that case is you use an older one. On Debian/Ubuntu/Mint, etc
sudo apt-get -y install gcc-arm-linux-gnueabi binutils-arm-linux-gnueabi
sudo apt-get -y install gcc-5-arm-linux-gnueabi
Which won't be cutting edge they will be a few major revs back. But there was a distinct change after gcc 5.x.x that makes it highly desirable to keep a hold of, gcc's optimization went downhill, binaries are larger, etc. Newer versions of Ubuntu, etc may not have the gcc-5 so you can try gcc-7 instead, you lose the gcc 5.x.x unless you can build it yourself, which eventually will become obsolete, the gnu folks don't tend to write clean C code that is meant to be compiled for many many years to come so their own tools won't build their own tools after some period of time. So if you get that deep in the hole then you run an older Linux on a virtual machine and in that Linux you grab or build the older toolchain (or windows or whatever).
While the Raspberry Pi Zero still exists I can't see armv6 support going away any time soon. It really has to do with maintainers and perhaps these conferences they have. pdp-11 support was ADDED not too many years ago and is still maintained (pdp-11s are still in use today, although with the hit to the airline industry from the virus, will see, maybe there is an opportunity to upgrade there). (pdp-11, a good first processor for learning assembly language, good simulators out there and easy to write your own).
Is the ARM11 (in the Pi Zero) still supported? Yes gcc and binutils still support it.
What do I do if/when they don't? Use an older toolchain, or worse case, run an older operating system that supports building/running the older toolchain.