Introduction to GNU Toolchain for Series 32000

Author: Alexander Voropai
May 2017


The GNU Toolchain is a collection of opensource software used for developing other software and OS-es. GNU Toolchains “by design” supports high portability and cross-compilation. It includes (among other tools) the GNU Binutils (assembler, linker e.t.c) and GCC (GNU Compiler Collection: c, c++, fortran, ada e.t.c.).

To run GNU Toolchains you have to use Unix-like environment on real *NIX (Free/Net/Open-BSD Linux e.t.c.) with GNU tools pre-installed or UNIX-like tools like Cygwin or MinGW+MSYS for Windows. (An old working version of GCC 3 may required, see notes below). Virtual machine to run *NIX would be good too.

To support cross-compilation there are three system names that the building scripts knows about: the machine you are building on (BUILD), the machine that you are building for (HOST), and the machine that toolchain will produce code for (TARGET). When you configure toolchains, you specify these with –build=, –host=, and –target=.

ns32k architecture support

GNU Toolchain supports a lot of TARGET architectures (100+). The ns32k architecture support was actively developed around 1990-2000 due to PC532 platform popularity but faded-out now. GNU binutils still supports ns32k architecture (binutils-2.24 was tested) and latest GCC supporting ns32k is GCC 3.x (gcc-3.4.6 now) and was removed from the GCC 4.0 and above. However it's still possible to build and use previous versions.

The latest “large” OS which supported ns32k was NetBSD 1.5.3 on the PC532 platform (FAQ). It used GNU Toolchain (slightly patched) to build itself (surprise?), binutils-2.9.1 and egcs-1.1.2 (also known as GCC 2.91, see a Wikipedia for details about GCC history)

NetBSD's ns32k TARGET for PC532 is ns32k-pc532-netbsd.
( BUILD and HOST variables are determined automatically during build process)

Despite NetBSD itself is highly portable, it was not well-suited for cross-compilation before NetBSD 1.6. Starting from NetBSD 1.6 a common infrastructure for cross-compilation was established with universal “” script. Unfortunately, NetBSD 1.6 dropped support for ns32k.

ELF support

Another problem is a binaries format and ABI supported. There was no COFF nor ELF support introduced for ns32k in the GNU Toolchain.

ELF was introduced in the System V Release 4 (SVR4) about 1990. It is not known any ns32k UNIX systems ported from the System V Release 4 codebase.

National Semiconductor GENIX 32 was a System V Release 2 and Release 3 ports and supported COFF. NetBSD 1.5.3 used good old a.out format.

UNIX System V ELF specifications defines an “e_machine” idntifier for ns32k:

EM_NS32K97National Semiconductor 32000 series

Building binutils

As it was noted above, the latest binutils still supports ns32k target. Early binutils versions (i.e. < binutils-2.13 required for NetBSD compatibility) considered as “mature” and requires GCC 3 to build. Something is broken in the ns32k binutils sources and it can't be built with GCC 4 and above.

Not-so-old (i.e. > binutils-2.20 (correct me)) may be successfully compiled under GCC 4.

Source download:

If you need to build early binutils-2.13, you have to use GCC 3, but this version disappeared from the many modern systems. You have to find or build a local GCC 3 for your system (not covered by this document) or use a “compatibility” compiler pre-built for some systems. As an example, Redhat RHEL 5 and CENTOS 5 provide a “compat-gcc-34” package, MinGW provides “mingw32-gcc-v3-core” (correct me). FreeBSD 6 uses GCC 3 as system compiler and FreeBSD 7 provides gcc-3.4 (lang/gcc34) in the port collection. The latest Cygwin with system GCC 3 compiler was a Gygwin-1.5.25 and it may be obtained from the Cygwin Time Machine (see a cygwin-legacy).

Build results for various platforms: toolchin-build

Like many other GNU software GNU Toolchain uses GNU Autotools scripts (./configure) to produce a correct Makefile for user's platform.

If you use a “compat” GCC, re-define a local CC= BEFORE running ./configure script!

(Example for Cygwin-1.5.25 with full build tools installed, running under Windows XP inside the VirtualBox)

tar jxf binutils-2.24.tar.bz2
cd binutils-2.24
./configure --prefix=/opt/cross --target=ns32k-pc532-netbsd --disable-nls
make install

This will install a new shining ns32k-pc532-netbsd-as, ns32k-pc532-netbsd-ld e.t.c. into /opt/cross/ .

Add this directory to the PATH (it's mandatory for GCC build):

export PATH=$PATH:/opt/cross/bin

GNU as

GNU as (gas) has a slightly different syntax than the so-called TDS (Tiny Development System) and DYNIX assemblers. Be careful porting your ns32k assembler files to the gas. As an example, all hex constants should be written as 0x123456 not x'123456. Immediate values should not be prepended with $. To access a variable as PC-related use movd var(pc),r0 istruction. Many assembler directives are different too. Consult a documentation :

On the other hand, GNU as is just a “backend” for the GCC compiler and rarely used standalone.

GCC compiler has an interesting option -S to produce an assembly .s file from the .c. Resulting files are fully compatible with as. Also GCC may pass an options to as with -Wa option. To produce an assembler listing with source code lines:

ns32k-pc532-netbsd-gcc -o test.o -Wa,-adhln=test.lst -g -fverbose-asm test.c

objdump also has a -d option (disassemble). It produces slightly odd-looking ns32k code that may not be directly used for assembly.

Building GCC

You have to extract NetBSD “include” directory before GCC building.


mkdir /tmp/NetBSD-1.5.3
tar zxf base.tgz -C /tmp/NetBSD-1.5.3
tar zxf comp.tgz -C /tmp/NetBSD-1.5.3


tar jxf gcc-3.4.6.tar.bz2
cd gcc-3.4.6
./configure --prefix=/opt/cross --target=ns32k-pc532-netbsd -enable-languages=c,f77 --disable-nls \
 --with-headers=/tmp/NetBSD-1.5.3/usr/include/ --with-gnu-ld --with-gnu-as --disable-shared \
 --disable-threads --disable-libmudflap --disable-libgomp --disable-libssp --disable-libquadmath \
 --disable-libatomic --disable-libjava --without-multilib
make install

Now your /opt/cross/bin also contains “ns32k-pc532-netbsd-gcc” and “ns32k-pc532-netbsd-g77”. Install script also copies all of *.h files from the NetBSD into /opt/cross/ns32k-pc532-netbsd/sys-include/. You could also copy all NetBSD development libraries from the /tmp/NetBSD-1.5.3/usr/lib into /opt/cross/ns32k-pc532-netbsd/lib/.

Full documentation:

Standalone binaries

As it is known, C compiler and linker adds a CRT0 library to the C program to make a “standard system environment”.

It is possible also to create a “standalone” static binary w/o CRT0 to run in ROM or emul32k Emulator.

Example test :

int function ();
start () {
   /* Make stack at top of memory: 265K */
   asm ("lprd sp,0x3fffc" : : );
   /* Do main job */
   function ();
   /* Exit from emulator */
   asm ("bpt" : : );
int function () {
   int a,b;
   return a+b;

“start” function is located at address 0 and emulator executes it first. It uses “asm” GCC instructions to setup a stack at top of memory (-4) and issue a “bpt” instruction to exit from emulator. A “function“ just adds two integers and returns a result in “r0”.


ns32k-pc532-netbsd-gcc -c -ffreestanding -o emutest.o emutest.c

The option -ffreestanding disables “hosted” environment where main() is the first “user” function in the programm called by crt0.o.

Another useful GCC option is -fomit-frame-pointer - it disables usage of the fp register (frame pointer) and use sp-related (stack pointer) addressing for local variables like “old” compilers. GCC also supports -fpic option to compile PIC (Position-Independent Code) with sb-related addressing 0(_glblvar(sb)).

Test object file with disassembler:

ns32k-pc532-netbsd-objdump -D -x  emutest.o
emutest.o:     file format a.out-ns32k-netbsd
architecture: ns32k:32532, flags 0x0000003e:
start address 0x00000000

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000030  00000000  00000000  00000020  2**3
                  CONTENTS, ALLOC, LOAD, CODE
  1 .data         00000000  00000030  00000030  00000050  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000030  00000030  00000000  2**3
00000000 g       .text 0000 02 05 _start
00000010 g       .text 0000 02 05 _function

Disassembly of section .text:

00000000 <_start>:
   0:   82 00 00        enter   [], 0
   3:   ef a4 00 03     lprd    sp, $262140
   7:   ff fc
   9:   02 07           bsr     10 <_function>
   b:   f2              bpt
   c:   92 00           exit    []
   e:   12 00           ret     0

00000010 <_function>:
  10:   82 00 08        enter   [], 8
  13:   17 a6 01 23     movd    $19088743, -4(fp)
  17:   45 67 7c
  1a:   ce 18 a6 0a     movzbd  $10, -8(fp)
  1e:   78
  1f:   17 c0 7c        movd    -4(fp), r0
  22:   03 c0 78        addd    -8(fp), r0
  25:   92 00           exit    []
  27:   12 00           ret     0
  29:   00 00           addb    r0, r0
  2b:   00 00           addb    r0, r0
  2d:   00 00           addb    r0, r0
Disassembly of section .data:

To make a binary image run ld with –oformat=binary and custom ldscript:

ns32k-pc532-netbsd-ld -nostdlib --strip-all --oformat=binary --script=stand.ldscript \
 -Ttext 0x0 -M -Map  -o emutest.bin emutest.o

To check binary file:

od -t x1 emutest.bin
ns32k-pc532-netbsd-objdump.exe -D -x --target=binary -m ns32k emutest.bin

Run emul32k emulator:

 ./emul32k emutest.bin
Series 32000 Emulator Version 1.0 of 5 May 2016
11 instructions executed.
R0=01234571 R1=00000000 R2=00000000 R3=00000000
R4=00000000 R5=00000000 R6=00000000 R7=00000000
PC=0000000C SB=00000000 SP=0003FFFC FP=FFFFFFFC
Traps=00000000 INTBASE=00000000 PSR=0000 MOD=0000

“r0” contains 0x1234567+10 .


GNU Debugger provides an infrastructure for remote CPU debugging with various hardware probes and CPU testers.

GDB 6.4 dropped support for ns32k-*-*

…To be done