In this blog I share my observations, thoughts and experience about computers, linguistics, philosophy and many other things that interest me.

Monday, January 19, 2026

Eight Days, Sixty Years: Building a System That Knows What It's For

Eight days ago, I asked Claude a question: "What's the most optimal organization for a microprogrammed CPU?"

Today, I have a computing system that displays its own name on a terminal.

GMS/359
GMS 2050 CPU
GateMate A1

This is the story of those eight days. But more importantly, it's a story about why the IBM System/360 — a machine designed in 1964 — still matters in 2026. And why I chose to build one on an FPGA.

The Machine Room

Look at this picture. It's from Jason, a beautiful S/360 emulator by Camiel Vanderhoeven (of "Operation Blinkenlights" fame). I first saw it about ten years ago. At the time, it was just a pretty picture of old computers.

Now, after eight days of building my own S/360, every element suddenly makes sense:

  • CPU — the central processing unit with its operator panel
  • DSP at 0C0 — the display console
  • CON at 01F — the operator console
  • PRT 1403 at 01E — the legendary line printer
  • RDR 2501 at 00C — the card reader
  • DASD at 350 — Direct Access Storage Device (disk)
  • TAPE at 280 — the magnetic tape drives

Those numbers — 0C0, 01F, 01E, 00C, 350, 280 — are device addresses. The same kind of addresses I now type into SIO instructions in my own code:

SIO   010h        ; Start I/O on video controller
SIO   011h        ; Start I/O on keyboard
SIO   012h        ; Start I/O on UART
SIO   02Bh        ; Start I/O on SYSINFO

There's no better way to understand something than to build it yourself.

What We Built in Eight Days

On January 10th, I had questions about CPU architecture. By January 18th, I had:

GMS 2050 CPU:

  • 16 general-purpose registers (32-bit)
  • 12 working instructions: LR, AR, LFI, LB, SB, ST, BC, SIO, TIO, LPSW, MVI, NOPR
  • 24-bit addressing (16 MB address space)
  • Base register addressing with NASM-style syntax
  • Condition code handling

GMS 2870 Multiplexor Channel:

  • Full Channel Command Word (CCW) execution
  • READ and WRITE operations
  • Command chaining
  • Channel Status Word (CSW) reporting

Peripheral Devices:

  • Video controller (0x10) — text output to VGA
  • PS/2 Keyboard (0x11) — with FIFO buffer
  • UART (0x12) — 115200 baud serial
  • SYSINFO (0x2B) — 256-byte system identification ROM
  • Console (0x2E) — debug output

Development Tools (asm359):

  • Assembler with NASM-style preprocessor
  • Linker for multi-section programs
  • IPL loader via UART

The keyboard works. I press 'A', I see 1C F0 1C on the UART — the PS/2 make and break codes, converted to hex by a lookup table that reminded me of ENIAC's glowing decimal displays from 1946. I press Pause, I see the legendary eight-byte monster: E1 14 77 E1 F0 14 F0 77.

The system can identify itself. Device 2Bh returns a 256-byte ROM containing the magic string "GMS/359", the CPU model, the FPGA type, feature flags, memory size, clock frequency. The machine knows what it is.

Why System/360?

Here's what I want to explain, and I hope I can do it justice.

When I first learned about the IBM System/360, it was through the history of UNIX — the porting efforts, the Interdata 7/32, and later the S/360 ports. Then I read Emerson Pugh's books on IBM history, and Fred Brooks' "The Mythical Man-Month." I fell in love with this machine.

Not because it's old. Not because it's "retro." Not because vacuum tubes and blinking lights are aesthetically pleasing (though they are).

I fell in love because the System/360 was designed, from its very first day, as a serious system.

Let me explain what I mean.

The Problem State

In S/360 architecture, the CPU has two modes: supervisor state and problem state. The operating system runs in supervisor state. User programs run in problem state.

Think about that name: problem state. Not "user mode." Not "application mode." Not "sandbox" or "container" or whatever the fashionable term is today.

Problem state. Because the machine exists to solve problems. Customer problems. Business problems. The problems that banks and insurance companies and airlines and governments need solved reliably, day after day, year after year, decade after decade.

The System/360 was not designed to make "Hello World" easy. When you first look at Channel I/O, you might think: "This is absurdly complicated! I need to set up a Channel Address Word, create a Channel Command Word chain, execute SIO, poll with TIO, check the Channel Status Word... just to print a string?"

Yes. Exactly.

Because the System/360 was never meant for printing one string. It was meant for printing millions of paychecks, processing billions of transactions, running the infrastructure of civilization. The "complexity" of Channel I/O is precisely what makes it powerful: DMA transfers, command chaining, device independence, error recovery, concurrent I/O across multiple channels. The architecture pays its complexity cost once, then amortizes it across fifty years of real work.

The Difference

Compare this to so many modern projects. You know the pattern:

"Here's our new CPU/board/platform! Look how easy it is to blink an LED! Look, Hello World in just three lines! Join our Discord! Buy our dev kit!"

And then... they disappear. The company pivots. The community fragments. The documentation rots. Your code stops working. You move on to the next shiny thing.

The System/360 architecture, announced in 1964, is still running bank transactions today. The same instruction set. The same Channel I/O concepts. The same principles. Sixty years and counting.

That's not an accident. That's what happens when you design a system for real work instead of easy demos.

IBM didn't optimize for the first five minutes of the user experience. They optimized for the next fifty years of the customer's business.

Why I'm Building This

The GMS/359 is not going to replace modern mainframes. It's not going to run z/OS. It's a hobby project on a small FPGA, built for the joy of understanding.

But I'm building it because I believe in the philosophy behind it.

When I design the Channel I/O system, I'm not thinking "how can I make Hello World easier?" I'm thinking "how can I make this architecture correct?" How can I build something that could, in principle, scale? Something where the complexity exists for good reasons, not just accumulated cruft?

When I added the SYSINFO device (0x2B), it wasn't because I needed it for a demo. It's because a real system should be able to identify itself. A real system should have feature flags that software can query. A real system should know its own version number.

The System/360 taught me this: design for the real work, not the demo.

The Next Fifty Years (Or At Least the Next Few Months)

Version 0.1.0 is tagged and pushed. The repository is now public at gitlab.com/gatemate/s359.

What's next:

  • More instructions (SR, logical operations, shifts)
  • Selector Channel for block devices, PSRAM as "RAM-disk"
  • Interrupt handling
  • IPL loads the "nucleus" and the "RAM-disk" image (created as a "DASD", perhaps), and the nucleus starts

But more importantly: continuing to learn from an architecture that got so many things right, six decades ago.

No comments: