Introduction to GNU Toolchain for Series 32000

Author: Alexander Voropai alec@sensi.org
May 2017
This page was created as a “companion” for this amazing site: http://www.cpu-ns32k.net

Overview

The GNU Toolchain is a collection of opensource software used for developing other software and OS-es. GNU Toolchain “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 Toolchain 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 environment like Cygwin or MSYS2 for Windows. 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 (50+). 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 (upto binutils-2.27 was tested) but latest GCC supporting ns32k was a GCC 3.4.x (gcc-3.4.6), GCC 4.0.x (gcc-4.0.4) and was removed starting from the GCC 4.1 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 “build.sh” script. Unfortunately, at the same time NetBSD 1.6 dropped support for ns32k.

Binary format support

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

NetBSD 1.5.3 used good old a.out format.

NOTE! There are many flavors of the a.out formats for ns32k. For example, early GENIX (extracted from the 4.1BSD) had a different a.out format than NetBSD.

National Semiconductor's GENIX 2 was a System V Release 2 (SYSVR2) and Release 3 (SYSVR3) ports and used COFF ns32k executables. GNX 4 cross tools also uses enhanced COFF format (with debug info, modules support e.t.c.). GNX4 cross-tools has a SYS5_2 and SYS5_3 targets. “GNX Language tools 4” book has “COFF Programmers Guide” chapter.

ELF was introduced in the System V Release 4 (SVR4) about 1990. There is no known any ns32k UNIX systems ported from the System V Release 4 codebase with ELF support (correct me).

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

NameValueMeaning
EM_NS32K97National Semiconductor 32000 series

http://www.sco.com/developers/gabi/latest/ch4.eheader.html

System V Release 3 introduced an early static shared libraries implementation with mkshlib and COFF files. SYSVR4 replaced it with more advanced shared oblect concept that required compiler and linker support (ld.so module, GOT (Global Ofset Table), PLT, PIC (Position Independent Code) e.t.c. available with ELF only).

Sidenote: An earlier GCC had support for many another ns32k targets: i.e. GCC 1.42 had a ns32k-ns-genix target (with output compatible with native GENIX as syntax, see GENIX ). Unfortunately ns32k-ns-genix was buggy in the GCC 2.0 and GCC 2.1 and was removed in the GCC 2.2 .

Early Mach-O object file format also had a definition for NS32000 architecture.

Further reading:
- FreeBSD 9 Handbook: Binary Formats
- ELF Tutorial
- Linux ELF HOWTO
- shared.txt Solaris shared library FAQ
- dso.txt DSO explanation from SGI IRIX
- “Linkers and Loaders” by John R. Levine
- System V ABI
mipsabi32.pdf MIPS ABI

Building binutils

As noted above, the latest binutils still support 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.

Binutils 2.27 source download link: http://ftp.gnu.org/gnu/binutils/binutils-2.27.tar.gz

If you need to build early binutils-2.13, you have to use GCC 3, but this version deprecated and disappeared from the most of 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).

I've made a test build for various platforms: toolchain-build (not complete).

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 zxf binutils-2.27.tar.gz
cd binutils-2.27
./configure --prefix=/opt/cross --target=ns32k-pc532-netbsd --disable-nls
make
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 so-called TDS (Tiny Development System) assembler and GENIX assembler. Be careful when porting your ns32k assembler files to 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-relative use movd var(pc),r0 istruction template. Many assembler directives are different too. Consult a documentation :

https://sourceware.org/binutils/docs/as/index.html

On the other hand, GNU as is just a “backend” for the GCC compiler and rarely used standalone. An examples of the GNU as usage may be found in the NetBSD ns32k for the pc532 port: in the bootloader, kernel ans some libraries call optimized for speed.

GCC compiler has an interesting option -S to produce an assembly .s file from the .c. Resulting files are fully compatible with gas. 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.

Download NetBSD 1.5.3 includes and libraries:
https://archive.netbsd.org/pub/NetBSD-archive/NetBSD-1.5.3/pc532/binary/sets/base.tgz
https://archive.netbsd.org/pub/NetBSD-archive/NetBSD-1.5.3/pc532/binary/sets/comp.tgz

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

Download: http://ftp.gnu.org/gnu/gcc/gcc-3.4.6/gcc-3.4.6.tar.gz

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
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: https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/index.html

Further reading: http://wiki.osdev.org/GCC_Cross-Compiler

Precompiled binaries: http://wiki.sensi.org/download/ns32k/ns32k-netbsd-cross-i686-linux.tgz
Includes binutils-2.27, gcc-3.4.6, NetBSD-1.5.3 headers. Prefix: /opt/cross
Binaris are compiled with GCC-3 for the i686 arhitecture and tested on the modern 64-bit Centos 7 (RHEL 7)
Since these are 32-bit -i686 binaries, install a glibc.i686 package
Just copy this TAR file to the root / and extract it with tar zxf
Add an export PATH=/opt/cross/bin:$PATH

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;
   a=0x1234567;
   b=10;
   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”.

Compile:

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.

NOTE! GCC sometimes emits “built-in” functions like __udivdi3 and requres “compiler runtime” library libgcc for target processor. Just smplify your arithmetic expressions to avoid this.

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
emutest.o
architecture: ns32k:32532, flags 0x0000003e:
EXEC_P, HAS_LINENO, HAS_DEBUG, HAS_SYMS, HAS_LOCALS
start address 0x00000000

Sections:
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
                  ALLOC
SYMBOL TABLE:
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 emutest.map  -o emutest.bin emutest.o

GNU ld documentation .

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 and binary file:

 ./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 .

GDB

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

…Work in progress

Sources: ftp://sourceware.org/pub/gdb/old-releases/

GDB 2.5.1: no ns32k support. parsing ns32k COFF coffread.c
GDB 2.8.1: initial ns32k support: m-merlin.h m-umax.h m-npl.h ns32k-opcode.h ns32k-pinsn.c coffread.c
GDB 3.1: ns32k support: m-merlin.h m-umax.h m-npl.h ns32k-opcode.h ns32k-pinsn.c coffread.c
GDB 3.3: the same, more instructions, bugs correction e.t.c.

GDB 4.0.1: uses BFD

NetBSD 1.5.3 uses GDB 4.17

GDB 5.1: Most ns32k hosts and targets have been marked as obsolete: ns32k-*-mach3* ns32k-umax-* ns32k-utek-sysv* ns32k-utek-*
GDB 6.4 dropped support for ns32k-*-*

Non-GNU Toolchains

Moved to new page: ns32ksoft

Navigation