This howto explains how NetBSD current can use thumb mode on ARM architecture (evbarm).

Introduction

While normal ARM instructions are 32 bits wide, thumb provides a subset of ARM instructions in 16 bits, and thus reduces executable sizes both in memory and on filesystem 1. See Wikipedia for more details.

On large codebases like NetBSD, ARM and thumb mode code can, and must, co-exists. This is because some parts of ARM specific code can not be programmed with the 16 bit thumb instructions. Luckily GCC makes this relatively easy with the thumb-interwork option.

As an overview, most machine independent (MI) C code can be compiled to thumb mode and most machine dependent (MD) C and assembly code can only be compiled to ARM mode. Some parts of the ARM port specific code in NetBSD have support for thumb mode, but most of them do not.

NetBSD's CPUFLAGS build variable is used tell the compiler, when an object file is compiled to thumb mode and when thumb interworking needs to enabled. The GCC options are -mthumb and -mthumb-interwork. By default ARM target binaries are of course compiled to ARM mode.

In a large codebase like NetBSD it becomes difficult to manually check if any one object file can be compiled to thumb mode. Luckily brute force works with the help of make option -k, as in keep going even one object file does not compile. By compiling whole tree with CPUFLAGS=-mthumb and MAKEFLAGS=-k, all of the build time failing machine dependent object files can be found, and marked with the help of Per file build options override to be compiled to ARM mode with thumb interworking.

Build time failures are of course not the only things can go wrong with thumb support. At run time, some parts of the kernel or userspace are expected to be in ARM mode. In userspace, for example, this means that the dynamic linker (ld.elf_so), userspace locking and C runtime initialization (CSU) parts need to be in ARM mode.

Userspace

Userspace in current compiles to userspace, but doesn't work due to a linker bug 23.

If the binutils package is upgraded to 2.18.50 from 2.16.1, then thumb mode works for userspace. After this, only a build script marking the ARM and thumb mode files is needed.

Following patches do it all for current snapshot from Oct 22nd 2008:

After the patches have been applied on top of current, the build process continues like this:

The next step is to verify that the thumb mode userspace works by booting into it. On OMAP 2420 development board this requires setting up a TFTP server for the kernel executable netbsd.bin and then setting up the root filesystem over NFS (and configuring the kernel accordingly).

Known problems

While the thumb mode userspace boots and most programs and the shell work, some programs may have issues. Known regressions at this time are:


    # cat > test.c << EOF
    > int main(void){
    > return 0;
    > }
    > EOF
    # gcc --verbose -Wall test.c
    Using built-in specs.
    Target: arm--netbsdelf
    Configured with: /usr/src/tools/gcc/../../gnu/dist/gcc4/configure --enable-longtThread model: posix
    gcc version 4.1.3 20080704 prerelease (NetBSD nb1 20080202)
     /usr/libexec/cc1 -quiet -v test.c -quiet -dumpbase test.c -auxbase test -Wall s#include "..." search starts here:
    #include <...> search starts here:
     /usr/include
    End of search list.
    GNU C version 4.1.3 20080704 prerelease (NetBSD nb1 20080202) (arm--netbsdelf)
            compiled by GNU C version 4.1.3 20080704 (prerelease) (NetBSD nb1 20080.GGC heuristics: --param
            ggc-min-expand=34 --param ggc-min-heapsize=7808
    Compiler executable checksum: c67c46e1fc2de869e7015b2c172bd073
    test.c: In function 'main':
    test.c:3: internal compiler error: Segmentation fault
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See  for instructions.

    # gdb --verbose /bin/cat
    [1]   Segmentation fault (core dumped) gdb --verbose /bin/cat

These issues may be solved by upgrading to newer versions of GCC compiler and gdb debugger.

Another problem is that newer binutils adds more symbols in thumb mode than older binutils, which makes thumb mode binaries file size larger than the with old binutils and larger than ARM mode binaries 7. These extra symbols only affect the file size and sections loaded to memory are smaller in thumb mode than in ARM mode. Also, all of these extra sections and symbols can be easily stripped by providing NetBSD build tools with a STRIPFLAG=-s build variable, though without this patch libraries are not stripped.