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|How to reduce libc size]]. See [Wikipedia](http://en.wikipedia.org/wiki/ARM_architecture#Thumb) 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 [2](http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=39668)[3](http://mail-index.netbsd.org/tech-toolchain/2008/10/01/msg000437.html). 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: * binutils upgrade and tuning for NetBSD in [4](http://koowaldah.org/people/ash/netbsd/thumb_to_current_01/0001-Upgrade-to-binutils-2.18.50.patch) and [5](http://koowaldah.org/people/ash/netbsd/thumb_to_current_01/0002-binutils-don-t-rebuild-bfd.info.patch) * thumb build script [6](http://koowaldah.org/people/ash/netbsd/thumb_to_current_01/0003-A-build-script-for-thumb-userspace.patch) After the patches have been applied on top of **current**, the build process continues like this: * build tools ./build.sh -U -O obj -m evbarm -j 3 tools * build userspace to thumb, note that the script expects to find tools directory under obj ./thumb.sh * build a normal ARM mode kernel, where CONFIG is the configuration file name like TISDP2420 ./build.sh -U -O obj -m evbarm -j 3 kernel=CONFIG 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: * thumb mode gcc segfaults on target

    # 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.
* thumb mode gdb segfaults on target

    # 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](http://sourceware.org/ml/binutils/2008-10/msg00140.html). 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](http://mail-index.netbsd.org/tech-toolchain/2008/10/17/msg000454.html) libraries are not stripped.