---
created_at: '2014-05-07T11:13:09.000Z'
title: Unix on the Game Boy Advance (2004)
url: http://www.kernelthread.com/publications/gbaunix/
author: omnibrain
points: 67
story_text: ''
comment_text: 
num_comments: 10
story_id: 
story_title: 
story_url: 
parent_id: 
created_at_i: 1399461189
_tags:
- story
- author_omnibrain
- story_7709539
objectID: '7709539'

---
[Source](http://www.kernelthread.com/publications/gbaunix/ "Permalink to UNIX&reg; on the Game Boy Advance")

# UNIX&reg; on the Game Boy Advance

# [kernelthread.com][1]

#### contents

[Mac OS X Internals][2] **|** [Projects][3] **|** [Publications][4] **|** [Résumé][5] **|**

#### meta

[Contact][6] **|** [Legalese][7] **|** [Slashdotted][8] **|**

## UNIX® on the Game Boy Advance

© Amit Singh. All Rights Reserved. Written in August 2004  
UNIX® is a registered trademark of The Open Group.    
  

### Introduction

In this document, I discuss "gbaunix", a rather contrived experiment in which I run an ancient version of the UNIX operating system on a popular hand-held video game system using a simulator. I can imagine this to be loosely of interest to a few types of people: 

* Game Boy hobbyist programmers
* Students of operating systems, emulators, and compilers
* UNIX aficionados

Specifically, I run 5th edition UNIX on the Nintendo Game Boy Advance. I briefly cover the following topics in this discussion: 

* [Game Boy Advance: Overview and Specifications][9]
* [High-level Architecture of gbaunix][10]
* [A Subset of a Brief History of UNIX][11]
* [An Annotated Demonstration of gbaunix][12]
* [Optimizing gbaunix][13]
* [Ideas and Suggestions][14]
* [Download][15]
* [References][16]

### Game Boy Advance: Overview and Specifications

![][17]

Nintendo has been in the gaming business since _1889_ (yes, 1**8**89; please stop sending me corrections). Their Game Boy line of hand-held video game systems is the most successful in the world, not that Nintendo has had much competition in this domain. Since the Game Boy's introduction in 1989, about 175 million units (counting all versions) have been sold. While the focus of this discussion is the Game Boy Advance (AGB, or GBA, as it is often called), the discussion also applies to the "SP" incarnation, which is similar to the GBA architecturally. Important GBA hardware features include: 

* 32-bit 16.78 MHz ARM (RISC) processor
* 8-bit Z80 (CISC) processor that runs at 4.2 MHz or 8.4 MHz (this provides compatibility with older Game Boys: the Game Boy Color, or CGB, and the monochrome Game Boy, or DMG)
* Four 16-bit timers
* Four DMA channels
* 240x160 TFT color LCD
* Stereo sound (through stereo headphones)
* Ten keypad inputs
* Serial port
* Game cartridge (GamePak) interface

The GBA includes several memories for different purposes: 

* 16 KB BIOS ROM
* 256 KB external (to the ARM processor) work RAM (EWRAM)
* 32 KB internal (to the ARM processor, that is, on the same chip as the ARM core) work RAM (IWRAM)
* 1 KB Background and Sprite Palette RAM
* 96 KB Video RAM
* 1 KB Object Attribute RAM
* Up to 32 MB of GamePak ROM
* Up to 64 KB of GamePak SRAM (optional)

Note that a GamePak ROM has two mirrors (in addition to the "original") in the GBA's memory map. A game cartridge may have multiple ROM banks with different access characteristics (such as wait-states). 

The GBA can be booted from a game cartridge or a compatible flash-memory cartridge that you can load your programs on. Alternatively, a GBA (slave) can download bootable code from another GBA (master), or even from a computer. This functionality, known as "multibooting", is present in the GBA's BIOS. 

The GBA's hardware is primarily accessible to a programmer through a well-defined memory map. Various I/O registers are mapped to specific memory addresses. Note that memory and ports are accessible through a common address mapping. Moreover, the BIOS contains a variety of functions accessible via software interrupts. 

##### ARM

Just as Nintendo is a mighty contender in the video game market, ARM is a leader in the RISC market. Unless you do not use any electronics, chances are that your life has been touched by an ARM (pun belabored). While Intel is the world's largest semiconductor vendor, its dominance in the PC microprocessor market is often misconstrued as _overall_ dominance in microprocessor technology. The PC market is only a small percentage of the overall microprocessor market, with embedded processors being the majority. This is hardly surprising, since electronics devices far outnumber personal computers. Consider: 782 million ARM-based devices were shipped in 2003 (source: Standard & Poor's). Some other numbers place ARM's RISC market-share to be almost 75%. 

Keywords often associated with ARM include "embedded", "high-performance", "low-cost", "power-efficient", and "RISC". ARM designs and licenses RISC-based microprocessor solutions to a maddening array of companies, including conventionally major players (such as Intel). 

The first ARM processor was developed at Acorn Computers Limited (Cambridge, U. K.) in the mid 1980s. At that time, ARM stood for "Acorn RISC Machine". The first version of the ARM architecture, or ARMv1, had 26-bit addressing, with no multiplier or coprocessor. The first ARMv1 processor, ARM1, saw limited use as a low-cost secondary component in the BBC microcomputer, and in prototypes of the Archimedes workstation. Nevertheless, this was one of the very first commercial RISC implementations. It is noteworthy that ARM eschewed some key features of the then prevailing Berkeley RISC architecture, such as: delayed branching, register windows, and requiring all instructions to execute in a single cycle each. 

On a related note, Apple was attempting to push RISC in the early 90s. (See Section 1.5.2 in in "[A Technical History Of Apple's Operating Systems][18].) Apple teamed with Acorn to fund a new company called Advanced RISC Machines, Limited, which became the _new_ ARM. VLSI Technology was a technology partner in this endeavor. ARM Limited's first processor was the ARM6, based on Version 3 of the ARM architecture (ARMv3). It had full 32-bit code and data addressing. An ARM6 processor, a 20 MHz 610, was used in Apple's MessagePad hand-held (Newton). 

The GBA's 32-bit processor is an ARM7TDMI, an implementation of Version 4T of the ARM architecture. We look at some of its details in the next section. 

##### The GBA's ARM

The GBA uses an ARM7TDMI processor, with certain ARM features missing. The ARM7TDMI is the most widely-used 32-bit embedded RISC microprocessor. Its architecture (ARMv4T) is almost a decade old (as of 2004). The ARM7TDMI has neither a memory management unit nor a cache. Its nomenclature may be understood as follows: 

* It is an **ARM7** processor
* It includes the **T**humb 16-bit compressed instruction set
* It has on-chip **D**ebug support
* It has an enhanced 32-bit x 8 **M**ultiplier, with 64-bit result
* It has Embedded**I**CE hardware that supports on-chip breakpoints and watchpoints

The ARM7TDMI core has a single 32-bit data bus carrying both instructions and data. Data can be 8, 16, or 32 bits, and only load, store, and swap instructions can access data from memory. There are 31 general-purpose 32-bit registers, 6 status registers, a barrel-shifter, an Arithmetic Logic Unit (ALU), and an enhanced multiplier. All registers are not accessible at the same time. For example, in ARM state, 16 general registers and one or two status registers are accessible at any one time. The processor can operate in seven _modes_: a user mode that is used for executing most programs, and six privileged modes (Fast Interrupt, Interrupt, Supervisor, Abort, Undefined, and System). The processor has two _states_: ARM and Thumb (see below). 

The GBA has DMA hardware (with 4 channels) external to the processor. While ARM supports two types of interrupt requests: normal (IRQ) and "fast" (FIQ), the GBA only makes use of the normal IRQ. 

The ARM7 has a simple three-stage pipeline with the following stages: 

* **Fetch**: An instruction is fetched (from memory), and put into the instruction pipeline.
* **Decode**: An instruction is decoded (for example, the registers used in the instruction are decoded).
* **Execute**: One or more registers are read from the register bank, shift and ALU operations occur, and results are written to one or more registers.

At any point during normal operation, while one instruction executes, the next instruction is decoded and a third instruction is fetched. 

##### Thumb

A traditional drawback of RISCs is their relatively poor code density (as compared to CISCs), due to their fixed-length instruction sets. This increases the size of a program's working-set, and leads to poorer cache utilization, more memory traffic, and higher power consumption. Such problems become particularly important in embedded applications. While an efficient solution to the power consumption problem would be multi-pronged (efficient use of parallelism, innovative electronics, etc.), ARM incorporated the "Thumb" architecture into certain processors to improve code density. 

Thumb is a 16-bit _compressed_ version of the normal 32-bit ARM instruction set. It includes a subset of the most commonly used 32-bit ARM instructions. While Thumb instructions have 16-bit wide opcodes, they operate on the same 32-bit register set as ARM code, and have most other benefits of the 32-bit core (32-bit address space, 32-bit barrel shifter, 32-bit ALU, etc.) Thumb-enabled processors (such as the GBA's ARM7TDMI) have decompression hardware in the instruction pipeline. The decompressor _translates_ Thumb instructions into equivalent ARM instructions. Thumb code density approaches, and even exceeds, that of many CISC processors. It is much better than ARM in certain contexts, for example (the numbers are approximate): 

* Thumb code takes 35% lesser space than ARM code
* Thumb code uses 40% more instructions than ARM code
* Thumb code is 40% slower than ARM code, if using 32-bit memory
* Thumb code is up to 60% faster than ARM code, if using 16-bit memory
* Thumb code results in 30% less external memory power consumption than ARM code

Typical applications, including those on the GBA (and our experimental code), use a mixture of ARM and Thumb. The ARM7TDMI interprets an instruction stream as ARM or Thumb based on a bit (the "T" bit) in the Current Program Status Register (CPSR). The GBA has a small amount of fast 32-bit memory (the 32 KB IWRAM). Typically, some amount of speed-critical code can be ARM code executing from this memory. The majority of an application's code might not be speed-critical, however, and thus may be Thumb executing from slower memory (such as an GBA GamePak). Nevertheless, as we saw, Thumb code can be faster than ARM code under certain circumstances, so it is not always a straightforward comparison. 

### High-level Architecture of gbaunix

gbaunix is a 5th edition UNIX system running on the GBA. To achieve this, gbaunix uses [SIMH][19], a highly portable PDP-11 simulator written in C. SIMH also implements simulators for numerous other systems, but I only use the PDP-11 portion. While the GBA has a C runtime via freely available toolchains, the port of SIMH to the GBA requires several additions and a few modifications. The high-level architecture of gbaunix is shown below: 

![][20]

The gbaunix "game cartridge" (or ROM) is the concatenation of a simulator runtime and a UNIX disk image. The latter could be taken as is, or may have additional programs loaded onto it. 

The simulator contains SIMH at its core. I have attempted to make minimal modifications to SIMH itself, abstracting GBA specific functionality into a logically separate layer that SIMH talks to. This layer could be thought of as having the following components: 

* **TTY Output**: gbaunix provides an illusion of a text terminal to SIMH. All TTY output is re-routed to GBA routines that format it, and send it to the GBA's framebuffer. Text-scrolling is done, if necessary. `printf()` is implicitly converted to a two step operation: `sprintf()` into a formatting buffer, followed by displaying the buffer on the screen.
* **TTY Input**: gbaunix does not have an input mechanism currently. You can only execute a canned sequence of UNIX shell commands. The sequence must be specified at compile-time as an array of strings in `gba/gba_kbd.h` in the source. While UNIX is running, pressing the START button feeds the next command line into the TTY's input buffer. gbaunix can either simply poll for keypresses, or can use the GBA's keypad interrupt. The latter ensures that no keypresses are missed. An example sequence is shown below:

` /* gba/gba_kbd.h */ const char *gba_kbdinput[] = { **"unixr"**, **"rootr"**, **"chdir /workr"**, **"ls -lr"**, **"./fact 100r"**, **"cat hanoi.cr"**, **"./hanoir"**, **"./hanoi 3r"**, **"chdir /tmpr"**, **"echo 'main() { printf("Hello, World! "); }' > hello.cr"**, **"cc hello.cr"**, **"./a.outr"**, ... /* more commands */ **NULL**, }; `
* **File System**: Due to the size of the UNIX disk image (2.5 MB), the only area of GBA memory that it would fit in is the ROM. Even though I cannot write to the ROM, I must accommodate writes to this "disk". A simple-minded solution is to allocate a "shadow" buffer in RAM every time a _new_ write happens. All reads and writes look up the shadow buffer chain to see if the source or target (respectively) regions of the disk already exist. Note that a subsequent operation may span multiple shadow buffers, partially or fully. Thus, we may need to coalesce buffers occasionally. Furthermore, a fake `stdio` layer is exported to SIMH.
* **Memory**: The simulated PDP-11 is given 128 KB of memory from the GBA's 256 KB EWRAM. Simulator memory operations (such as copying or moving) are implicitly converted to equivalent GBA operations (with optimizations, such as the use of DMA, if applicable).
* **Miscellaneous**: This category includes code to initialize the runtime: for setting up the TTY, setting up any interrupt handlers, calling file system initialization hooks, etc.

### A Subset of a Brief History of UNIX

You can try gbaunix either using a Game Boy Advance emulator, or on a real Game Boy Advance. For the latter, you would need, say, a flash-based cartridge and a flash programmer. 

##### Development

![][21] It is more convenient to run gbaunix on a GBA emulator, especially if you want to experiment with it by modifying its source. gbaunix is not greatly optimized yet, and for various reasons, most telling of which is that I am simulating the PDP-11 _in software at the instruction level_, gbaunix is _extremely_ slow on a real GBA. For example, it takes 2 minutes to go from the boot prompt to the login prompt on real hardware! Many emulators allow you to run them "as fast as possible", resulting in a more pleasant development experience. 

My build environment is hosted on Mac OS X. I used the "Boycott Advance" emulator, and the "devkitARM" toolchain, compiled from source on Mac OS X. I tested on real hardware courtesy of a flash cartridge. 

As we look at screenshots of gbaunix, we shall discuss a very small subset of the history of UNIX. 

##### Time-Sharing

Project MAC (Multiple Access Computer, Machine-Aided Cognition, Man and Computer) was a research project founded at the Massachusetts Institute of Technology (MIT) in 1963. It would evolve into the Laboratory for Computer Science (LCS), and is today the Computer Science and Artificial Intelligence Laboratory. 

The early 60s saw a surge in popular interest in time-sharing. John McCarthy wrote a memo titled "A Time Sharing Operator Program for Our Projected IBM 709" in 1959. Corbató, Merwin-Daggett, and Daley wrote in a 1962 paper that: _"... we are in the midst of a third major modification to computer usage: the improvement of man-machine interaction by a process called time-sharing."_ While they informally defined time-sharing to be something that _"increases the efficiency of persons trying to use a computer"_, they also pointed out a related connotation: _multiprogramming_, or several people making use of a computer at the same time, is also a consideration. Dennis Ritchie said of UNIX later that _"... the cycle of edit-translate-execute-debug is limited by thinking time, not compute time."_

Project MAC made seminal contributions to time-sharing systems, including development of the Compatible Time-Sharing System (CTSS, which was first demonstrated even before Project MAC was formed). There were various other time-sharing systems in the mid to late 60s (BBN, DTSS, JOSS, SDC, ...), but a comprehensive history of time-sharing is not within the scope of this discussion. However, one system is of particular interest: Multiplexed Information and Computing Service (MULTICS, or Multics). 

##### Multics

Multics was a joint research project between MIT, Bell Telephone Laboratories (BTL), and General Electric (GE) to create a time-sharing operating system for the GE-645 computer. 

At that time, "use" (of a computer) primarily meant programming, and thus, "efficiency" meant being able to program more efficiently and imaginatively: for example, being able to edit, compile, and debug interactively, without unnecessary delays. 

Multics was intended to be a utility-like system that could support a large number (about a thousand) of simultaneous users. It had several key design objectives (as discussed in _Introduction and Overview of the Multics System_, Corbató and Vyssotsky, 1965): 

* Run continuously and reliably 24x7, similar to telephone or power systems.
* Have a general framework, capable of evolving with time as changes in technology and user needs occur.
* Support multiple programming languages and user interfaces (Multics itself was mostly implemented in a high-level language: PL/I).

For an example of a PL/I program, see [_The Towers of Hanoi in PL/I][22]_. 

* Support a wide range of applications.
* Have flexible and convenient remote access, with acceptable response time.
* Have a hierarchical information structure (allowing for hierarchical control, and decentralization, of resource allocations and accounting authorizations).
* Have a reliable internal file system.
* Have selective information sharing (for example, a user may selectively allow others to access his files).
* Have on-line system documentation.

BTL withdrew from the Multics project in early 1969. 

Multics continued as a commercial product after Honeywell acquired GE's computer assets, and after Bull acquired the Honeywell properties. The system eventually met many of its design objectives. The last Multics site was shut down in 2000. In any case, Multics' design would influence several systems to come. 

##### UNIX

After BTL's withdrawal, there were a few at BTL who had been working on Multics and were restless (Ken Thompson, Dennis Ritchie, Stu Feldman, Doug McIlroy, Bob Morris, and Joe Ossanna). Thompson was working on a "game", Space Travel, on the GE-635. Space Travel had first been written for Multics, and had a FORTRAN port for the General Electric Comprehensive Operating System (GECOS) running on the 635. The game simulated the motion of certain celestial bodies in the Solars System. The player's goal was to land a space ship on a planet or a moon. The GE computer's hardware and software were both ill-equipped to run the game, and playing was expensive in terms of CPU time (although the "money" so spent was only theoretical). Thompson proactively looked for an alternative. He decided to take over a "little-used" DEC PDP-7. This particular unit had 8K 18-bit words of memory and a capable vector display processor. Thompson, with help from Ritchie, rewrote Space Travel in PDP-7 assembly language from scratch (including a floating-point simulator). It ran standalone on the PDP-7. 

##### 0th Edition (late 1969)

Thompson and Ritchie did not use any native software on the PDP-7 to write Space Travel, but used a cross-assembler on the GE machine, and used paper tapes to run the program on the PDP. Unhappy with this setup, Thompson began writing an operating system for the PDP-7, starting with a file system. The "cross-assembly on GECOS followed by paper tape" arrangement continued until Thompson had a system capable of hosting development. At this point (late 1969), the system had a kernel, an editor, an assembler, a simple command shell, and some file utilities (`cat`, `cp`, `rm`, etc.) This was UNICS: a pun on Multics whether you think of it as "Uniplexed ULTICS" or a castrated Multics. Later, UNICS became UNIX. This first incarnation of UNIX may be regarded as the 0th edition. 

The ancient `cp` command operated on multiple file name arguments by taking them in pairs. Thus: 

# **cp file11 file12 file21 file22 ...**

The `dsw` command (contraction for "delete using switches") was used for deleting files interactively. 

Multics (and the earlier CTSS) influenced many aspects of UNIX, such as: 

* The shell (the command interpreter was even called "shell" on Multics). UNIX ``shell command`` is analogous to Multics' [`shell command]`.
* Utilities such as `ls`, `pwd`, `chdir` (`cwd` on Multics), `mail`, `man` (`help` on Multics).
* "rc" files (CTSS had a program called `RUNCOM`).
* `roff`, the command for rendering text (the CTSS `RUNOFF` command was used for Multics documentation).
* A file as a stream of bytes with no underlying structure
* A text file as a stream of characters with newlines
* File system with a tree structure
* Structure of the underlying disk hidden from applications performing file I/O
* The arguments (file handle, buffer, count) used in file I/O calls
* I/O redirection

Ritchie said in _The Unix Time-sharing System — A Retrospective_ that _"In most ways UNIX is a very conservative system. Only a handful of its ideas are genuinely new. In fact, a good case can be made that it is in essence a modern implementation of MIT's CTSS system. The claim is intended as a compliment to both UNIX and CTSS."_

PDP-7 UNIX had a file system with i-nodes, although an i-node contained very basic information: the list of physical blocks, and minimal metadata (size, protection mode, and type). While special files and directories were supported, there were no pathnames. There was even buffering in the file system. Some stark limitations included: 

* You could only create directories and special files at file system creation time.
* The system had only one disk, and you could not mount any more disks.
* The system was not multiprogrammed. Thus, only one program could exist in memory at a time.
* Disk I/O completely blocked the CPU.
* There were no `fork`, `exec`, or `wait`. The shell executed commands using a tedious mechanism, which terminated the shell upon every command. After command completion, `exit` ran a brand new copy of the shell.

The PDP-7 UNIX system also caused the inception of a high-level language, B, which was was influenced by the BCPL programming language. Dennis Ritchie called B _"... C without types ... BCPL squeezed into 8k bytes of memory and filtered through Thompson's brain ..."_ B would eventually lead to C. PDP-7 UNIX, as well as its utility programs, were all written in assembly language. 

For an example of a BCPL program, see [_The Towers of Hanoi in BCPL][23]_. 

Note that UNIX also ran on the PDP-9. 

1969 was also the year that the first ARPANET node became operational, and the first Internet RFC was published. 

The UNIX "group" then made efforts to convince BTL to acquire a better machine, the PDP-11. They promised to deliver a document editing and formatting system (meant to run standalone, without UNIX), and were supposed to use UNIX only as a development platform. The first PDP-11 they received was an 11/20, with 24 KB of memory. UNIX ran on the PDP-11 in early 1971. Of its memory, 12 KB was used by the kernel, some by user programs, and rest as a ram disk. 

##### 1st Edition (November, 1971)

The 1st edition ran on the PDP-11/20, which had no MMU, nor any hardware protection features. Therefore, it was trivial to crash the operating system. There was no multiprogramming. Pathnames were present. The only (documented) system calls were: `break`, `cemt`, `chdir`, `chmod`, `chown`, `close`, `creat`, `exec`, `exit`, `fork`, `fstat`, `getuid`, `gtty`, `ilgins`, `intr`, `link`, `mkdir`, `mount`, `open`, `quit`, `read`, `rele`, `seek`, `setuid`, `smdate`, `stat`, `stime`, `stty`, `tell`, `time`, `umount`, `unlink`, `wait`, and `write`. 

A few programming languages were supported: Assembly, B, BASIC, and FORTRAN (but no C). 

The B (and Assembly) compilation environment consisted of the following: 

| ----- |
| Component | Description |  
| `/bin/as` | assembler (the output of the assembler went to a file called `a.out` by default) |  
| `/bin/ld` | the link editor (note that only one person could use `ld` at a time in a given directory due to its use of temporary files) |  
| `/bin/nm` | program for printing the symbol table from the output file of an assembler or loader run |  
| `/bin/strip` | program for removing symbols and relocation bits |  
| `/bin/un` |  program for printing a list of undefined symbols in an appropriate file |  
| `/etc/as2` | second pass of the PDP-11 assembler |  
| `/etc/ba` | B assembler (`prog.i` —> `prog.s`) |  
| `/etc/bc` | B compiler (`prog.b` —> `prog.i`) |  
| `/etc/bilib` | B interpreter library |  
| `/etc/brt1` | B runtime routines |  
| `/etc/brt2` | B runtime routines |  
| `/etc/liba.a` | assembly language subroutines |  
| `/etc/libb.a` | general utility routines for B programs |  
| `/usr/b/rc` | a shell script that compiled, by invoking other programs, a B source file (`program.b`) into executable (`a.out`). The compilation sequence was `program.b —> program.i —> program.s —> a.out` | 

It is noteworthy that the 1st edition did not carry any copyright notice. 

The system had impressive documentation. The [first edition manual][24] was divided into seven sections: 

1. Commands (programs intended to be invoked directly by the user)
2. System calls (entries into the UNIX supervisor, accessed via the trap instruction)
3. Subroutines (intended to be called by user programs)
4. Special files (files referring to I/O devices)
5. File formats
6. User maintained programs
7. Miscellaneous

Subsequent editions had an eighth section titled System Maintenance. 

Each logical page of the manual, a "man page", contained subsections: name, synopsis, description, files, see also, diagnostics, bugs, and owner. The manual was prepared using the UNIX text editor `ed`, and the `roff` text formatter. 

The first man page was for the `cat` command. 

##### 2nd Edition (June, 1972)

The 2nd edition contained `cc`, the C compiler, but it was not yet implemented in C. A few new commands, system calls, and subroutines were introduced, such as: `:(1)`, `cc`, `echo(1)`, `exit(1)`, `goto(1)`, `if(1)`, `login(1)`, `m6(1)`, `man(1)`, `mt(1)`, `opr(1)`, `stty(1)`, `tmg(1)`, `tss(1)`, `kill(2)`, `sleep(2)`, `sync(2)`, `atan(3)`, `hypot(3)`, `nlist(3)`, `qsort(3)`, `salloc(3)`, and `sqrt(3)`. 

| ----- |
| Component | Description |  
| `**:(1)**` | A command that did nothing (its function was to place a label for the `goto` command: thus, the shell didn't have to be fixed to ignore lines with `:`'s. |  
| `**cc(1)**` | The C compiler. |  
| `**m6(1)**` | A general purpose macro processor. |  
| `**opr(1)**` | submit a job for off line printing. |  
| `**tmg(1)**` | A compiler compiler (TMG was a compiler-writing language). |  
| `**tss(1)**` | Interface to the Honeywell TSS. |  
| `**salloc(3)**` | A set of routines for dealing with (almost) arbitrary length strings of words and bytes. | 

2nd edition UNIX was still unprotected, with no multiprogramming. It did carry a copyright. 

##### 3rd Edition (February, 1973)

The 3rd edition was the first UNIX to run on the PDP-11/45, which had hardware segmentation and support for more core memory (256 KB). 

3rd edition UNIX had some noteworthy features, such as pipes and multiprogramming. Some other interesting additions included: 

| ----- |
| Component | Description |  
| **`cdb(1)`** | The C debugger |  
| **`crypt(3)`** | The password encoding routine |  
| **`proof(1)`** | A program for comparing two text files (latter day `diff`) |  
| **`ps(8)`** |  |  
| **`sno(1)`** | A SNOBOL III compiler and interpreter |  
| **`speak(1)`** | A word to voice translator that turned a stream of ASCII words into utterances, and output them to a voice synthesizer. |  
| **`typo(1)`** | Quoted verbatim from the man page: _"... hunts through a document for unusual words, typographic errors, and hapax legomena and prints them on the standard output."_) |  
| **`yacc(6)`** | A compiler compiler | 

##### 4th Edition (November, 1973)

The 4th edition was essentially the 3rd edition written in C. It also supported newer PDP-11 systems (such as the /60 and /70). Implementation in a high-level language resulted in a system about a third bigger than the previous. 

A few commands were added, while the B programming language was not included. 

### An Annotated Demonstration of gbaunix

##### 5th Edition (June, 1974)

I use the 5th edition for gbaunix. It is the oldest UNIX for which a machine readable bootable file system image exists. There also exists the source for the kernel (in fact, we shall later see an example of recompiling the UNIX kernel). 

![][25] Upon power-on, gbaunix displays some information about the "PDP-11"'s hardware, followed by the `@` boot prompt. When you press the START button, the hard-coded keyboard feeder would type `unix`, the name of the kernel to boot. The boot process will take an extremely long time (about 2 minutes) on real hardware, after which you will get a login prompt. 

The semi-colon in the login prompt ([;login][26] is also the magazine of the [USENIX][27] Association) has to do with a popular terminal (Teletype model 37) in the early 1970s. The ';' escape sequence put that terminal in full-duplex mode. Hence, the UNIX greeting message contained this sequence. A terminal that does not understand this sequence, such as our GBA TTY, would print the semi-colon. 

![][28] We noted that even the first UNIX had special files: I/O devices represented as files. When such a file was read from or written to, the underlying device was activated. In the accompanying screenshot, `/dev/rk0` and `/dev/rrk0` are the block and character devices, respectively, corresponding to first moving-head "RK" disk drive. `/dev/mem` mapped the core memory of the computer into a file. It was possible to patch the running system using a debugger on this device. 

![][29] `glob`, contraction for "global", was an external (to the shell) program use by the shell to expand special characters ('*' and '?') in the argument list. `glob` would expand any metacharacters and invoke the command itself. Upon failing to generate any matches, `glob` would print the classic UNIX error message: "No match". 

Note that certain commands, such as `mkfs`, were kept in `/etc` to lessen the probability of them being invoked accidentally, or out of curiosity! 

The `dc` command, an arbitrary precision reverse Polish calculator, made its appearance very early in UNIX. In fact, it was the first program to be tested on the PDP-11, even before UNIX ran on it. 

![][30] A typical 5th edition kernel was less than 26 KB. Note also the sizes of the shell (5738 bytes) and `init` (1972 bytes). The system shown here has a minimal `rc`. `/etc/update` periodically updated the super block every 30 seconds, so as to ensure that the file system was fairly up to date in case of a crash. 

The long format output of `ls` listed the mode, number of links, owner, size in bytes, time of last modification, and name. 

![][31] By the time the 5th edition was released, UNIX had a rich programming environment with support for numerous programming languages, such as Algol-68, APL, Assembly, BASIC, C, FORTRAN, M6, PASCAL, Snobol, and TMG. In fact, using gbaunix you can even program _on_ the GBA itself in several languages (_in theory, might be painful in real-life_). Compilers/interpreters are included on the 5th edition disk image for C, PDP-11 assembly, BASIC, Shell (scripting), and FORTRAN. I have tried Algol-68 too, although you may have to load it onto the disk image. 

Following are some more examples of programming in the gbaunix environment (including the obligatory "Towers of Hanoi"): 

| ----- |
| ![][32] | ![][33] |  
| ![][34] | ![][35] | 

Some more screenshots, including those of the output of miscellaneous commands, can be seen on the [screenshot-overflow][36] page. 

##### Subsequent Editions

The 6th edition (May, 1975) was important in that BSD and XENIX were derived from it. John Lions wrote his famous Commentary based on the 6th edition (_A Commentary on the Sixth Edition UNIX Operating System_, 1977). Moreover, 6th edition is the earliest UNIX system that is available in machine readable form in its entirety. 

The on-line documentation for 5th edition is missing. Only bits and pieces are available of the 4th edition and earlier systems. 

Beginning with the 6th edition, the UNIX system proliferated rather rapidly. 

Further editions in the BTL lineage were: 

* 7th edition (January, 1979)
* 8th edition (February, 1985)
* 9th edition (September, 1986)
* 10th edition (October, 1989)

##### BSD

It is also possible to run some other systems on the GBA that normally run under SIMH. However, doing so is increasingly harder (and after a point, impossible) as system requirements increase (more memory required, say). 

Following are some screenshots depicting BSD 2.9 running on the GBA: 

| ----- |
| ![][37] | ![][38] |  
| ![][39] | ![][40] | 

### Optimizing gbaunix

gbaunix has provisions for experimenting with a few potentially performance-affecting aspects. Note that you would need to recompile gbaunix to experiment with these. 

##### Performance-critical code in IWRAM

gbaunix includes an example of compiling certain code as ARM and keeping it in IWRAM. Note that the code that is most likely to benefit from this optimization, if at all, is the CPU simulation code. 

##### DMA

The GBA provides a few methods of performing memory operations, with different performance characteristics and restrictions (alignment, size, overlap, etc.) Those relevant to gbaunix include using DMA channel 3 (general-purpose DMA) for `memcpy()` and `memset()`. Moreover, the GBA BIOS contains functions for copying and setting memory via software interrupts. gbaunix includes support for experimenting with these methods. 

##### Caching

As we saw earlier, gbaunix emulates `stdio`, and in turn, a simulated disk, by making a section of the GBA GamePak ROM appear as a UNIX file. Since we cannot write to the ROM (on real hardware, at least), gbaunix shadows the writes into buffers in RAM, and all subsequent reads and writes first consult the shadow buffers. gbaunix allows you to _pre-load_ the shadow buffers with "hot" areas of the UNIX disk that are written to initially (from power-on until a user logs in, say). 

##### Recompiling the UNIX kernel

While recompiling the UNIX kernel would not have any perceptible performance benefits for gbaunix, doing so is interesting nonetheless, if only to contrast it with today's kernel compilations. We could limit the number of devices the kernel supports, and thus not link in some code, thereby reducing the kernel's footprint somewhat. 

Consider the source size of the 5th edition kernel: 

* Headers: 418 lines in 13 files
* C files: 7222 lines in 43 files (including available source for all peripheral device drivers)
* Assembly files: 1080 lines in 2 files

I have not even attempted to compile the kernel _on_ the GBA itself: it would take an inordinately long time, and we would certainly run out of shadow-write memory with the current scheme, if not the current GBA specifications. 

The following sequence of commands assumes that you have 5th edition UNIX running (on real or simulated hardware), and the UNIX kernel source is in its default location (`/usr/sys`). 

Remove libraries that possibly exist due to a previous compilation: 

` # **chdir /usr/sys** # **rm -f lib1** # **rm -f lib2** `

Before you begin compilation, you could study and modify tunable parameters in `/usr/sys/param.h`. 

If you get a compiler error (I did with the source tree I have) about an undefined `KISA0`, define `KISA0` (the first kernel i-space address register) in `/usr/sys/seg.h`. 

` # **echo '#define KISA 0172340' >> /usr/sys/seg.h** `

Compile the "main" kernel: 

` # **chdir ken** # **cc -c -O *.c** ... # **ar vr ../lib1 main.o alloc.o iget.o prf.o rdwri.o slp.o subr.o text.o trap.o sig.o sysent.o clock.o fio.o malloc.o nami.o pipe.o sys1.o sys2.o sys3.o sys4.o** ... `

Compile device drivers, etc. Note that you could choose not to compile some of the files in this directory if you are not including support for the corresponding devices: 

` # **chdir ../dmr** # **cc -c -O *.c** ... # **ar vr ../lib2 *.o** `

Generate system configuration, and link everything to yield the kernel binary: 

` # **chdir ../conf** # **cc mkconf.c** # **mv a.out mkconf** # **echo rk | ./mkconf** # **cc -c c.c** # **as l.s** # **mv a.out l.o** # **as mch.s** # **mv a.out mch.o** # **ld -x l.o mch.o c.o ../lib1 ../lib2** # **mv a.out rkunix** `

`rkunix` is the newly compiled UNIX kernel. Place it as `/rkunix`, and type `rkunix` instead of `unix` at the boot prompt to test it. 

### Ideas and Suggestions

Following are some ideas for further work (with mostly academic relevance): 

##### Native port of UNIX to the GBA

It would be a good exercise for operating systems students to attempt a _native_ port of, say, 6th edition UNIX to the GBA. I expect a substantial improvement in performance (as compared to gbaunix) if this were done. Ancient UNIX is a system small enough to be easily understood by one person. The 6th edition kernel source consists of 44 files (The Lions Commentary): 

* 14 C headers
* 28 C source files
* 2 assembly files

The entire source is less than 9,000 lines if a subset of peripheral device drivers is included. Of this, assembly constitutes about 10%. 

While I think it is very feasible to do a native port, it is less trivial than it appears ("only 2 assembly files!"), particularly if you port the C compiler as well. 

##### gbaunix performance improvements

Even though I have included some preliminary hooks for optimization (use of DMA, tweakable caching, placement of certain code in the processor's internal memory, etc.), it is an open problem to come up with an optimization scheme that takes all constraints into account and results in a perceptible performance improvement. You could start by focusing on the code that simulates PDP-11 instructions (`pdp11_cpu.c`) — that's where the simulator spends most of its time. 

##### An input mechanism for gbaunix

Currently, gbaunix is always in "demo mode", wherein it iterates through a hardcoded (at compile time) sequence of UNIX commands. For more realistic and interactive user experience, an input mechanism could be created (or an existing one incorporated). For example, you could have a modal mechanism in which you _compose_ a command line by choosing characters (via the keypad) displayed on the screen: once done, a button press returns you to UNIX, with your composed command in the TTY's input buffer. 

##### Emulating the original Macintosh on the GBA

The first Macintosh had the following key specifications: 8 MHz 16-bit processor, 128 KB RAM, 64 KB ROM, no cache or interrupts, 400 KB floppy, and monochrome 512x342 display. To recapitulate, the GBA has the following relevant specifications: 16.78 MHz 32-bit processor, 288 KB (32 KB internal + 256 KB external) RAM, 32 MB ROM, and 240x160 display. It should be possible to port a lightweight Macintosh emulator (or perhaps even create one) to the GBA. You might do offscreen scrolling to accommodate the higher resolution, emulate a writable floppy drive via shadow writes, etc. 

Other possibilities include porting an 8088 emulator to run some ancient version of DOS. 

### Download

[gbaunix-0.0.tar.bz2][41]

Note that in order to run 5th edition UNIX with gbaunix, you must have an RK05 disk image of 5th edition UNIX, which is _not_ included in the gbaunix distribution. SCO owns the copyright for the 5th edition (and several others). You can download a disk image, after reading and understanding the license and ensuring that you are eligible, from the Unix Archive at the PDP-11 Unix Preservation Society: 

<http://minnie.tuhs.org/PUPS/>

##### Usage

If you only want to run gbaunix, without recompiling it, you can simply concatenate the pre-compiled executable (`unixv5.tmp`) in the distribution with the RK05 disk image: 

` % **cat unixv5.tmp disks/unixv5.dsk > unixv5.gba** `

`unixv5.gba` is the ready-to-run "game cartridge", which can be used with a Game Boy Advance emulator, or on real hardware. 

If you want to compile gbaunix (highly recommended, and the only realistic way to experiment with it), you would need a cross-compilation environment: an ARM toolchain for your platform. You may need to edit the Makefile to set the path to your ARM compiler. The RK05 image must be present as `disks/unixv5.dsk` in the source tree. Thereafter, simply run `make`. 

### References

* Ancient UNIX sources, binaries, and documentation.
* Dennis Ritchie's writings.
* SIMH documentation.

All contents of this site, unless otherwise noted, are ©1994-2009 **Amit Singh**. All Rights Reserved. [Terms of Use][42]

[1]: http://www.kernelthread.com
[2]: http://osxbook.com "Mac OS X Internals: The Book"
[3]: http://www.kernelthread.com/projects/ "Projects"
[4]: http://www.kernelthread.com/publications/ "Publications"
[5]: http://www.kernelthread.com/resume/
[6]: http://www.kernelthread.com/contact/ "Contact Amit Singh"
[7]: http://www.kernelthread.com/legalese/ "Legalese"
[8]: http://www.kernelthread.com/slashdotted/ "Slashdotted"
[9]: http://www.kernelthread.com#GBA
[10]: http://www.kernelthread.com#GBAUNIX
[11]: http://www.kernelthread.com#HISTORY
[12]: http://www.kernelthread.com#WALKTHROUGH
[13]: http://www.kernelthread.com#OPTIMIZING
[14]: http://www.kernelthread.com#IDEAS
[15]: http://www.kernelthread.com#DOWNLOAD
[16]: http://www.kernelthread.com#REFERENCES
[17]: http://www.kernelthread.com/images/gbaunix.gif
[18]: http://osxbook.com/book/bonus/chapter1/ "A Technical History Of Apple's Operating Systems"
[19]: http://simh.trailing-edge.com/ "The Computer History Simulation Project"
[20]: http://www.kernelthread.com/images/gbaunix_arch.gif
[21]: http://www.kernelthread.com/images/devel.gif
[22]: http://www.kernelthread.com/projects/hanoi/html/pli.html "Hanoi: PL/I"
[23]: http://www.kernelthread.com/projects/hanoi/html/bpl.html "Hanoi: BCPL"
[24]: http://cm.bell-labs.com/cm/cs/who/dmr/1stEdman.html "Unix Manual, first edition"
[25]: http://www.kernelthread.com/images/u5_login.gif
[26]: http://www.usenix.org/publications/login/ "USENIX - ;login: online"
[27]: http://www.usenix.org/ "USENIX"
[28]: http://www.kernelthread.com/images/u5_devices.gif
[29]: http://www.kernelthread.com/images/u5_dc.gif
[30]: http://www.kernelthread.com/images/u5_catmisc.gif
[31]: http://www.kernelthread.com/images/u5_helloworld.gif
[32]: http://www.kernelthread.com/images/u5_lswork.gif
[33]: http://www.kernelthread.com/images/u5_fact100.gif
[34]: http://www.kernelthread.com/images/u5_hanoi_cat.gif
[35]: http://www.kernelthread.com/images/u5_hanoi.gif
[36]: http://www.kernelthread.com/so.html "UNIX® on the Game Boy Advance: Screenshots"
[37]: http://www.kernelthread.com/images/bsd29_boot.gif
[38]: http://www.kernelthread.com/images/bsd29_prompt.gif
[39]: http://www.kernelthread.com/images/bsd29_ls.gif
[40]: http://www.kernelthread.com/images/bsd29_vi.gif
[41]: http://www.kernelthread.com/gbaunix-0.0.tar.bz2 "gbaunix-0.0.tar.bz2"
[42]: http://www.kernelthread.com/legalese/

