# How the AGC INTERPRETER System Performs Calculations: Apollo-11 Virtual Machine Architecture

> Discover how the AGC INTERPRETER system performs calculations. Learn about its fetch-dispatch loop, addressing modes, and arithmetic sub-routines within the Apollo-11 VM.

- Repository: [Chris Garry/Apollo-11](https://github.com/chrislgarry/Apollo-11)
- Tags: internals
- Published: 2026-03-04

---

**The AGC INTERPRETER system executes interpretive programs stored in erasable memory by decoding opcode pairs in a fetch-dispatch loop, resolving three addressing modes (direct, indexed, and push-down), and delegating arithmetic operations to specialized sub-routines.**

The Apollo Guidance Computer (AGC) utilized a sophisticated **INTERPRETER system** to perform complex mathematical calculations without the memory overhead of native machine code. As implemented in the `chrislgarry/Apollo-11` repository, this virtual machine—located in `Luminary099/INTERPRETER.agc`—reads compact opcode sequences from erasable memory and dispatches operations to dedicated arithmetic handlers, enabling compact representation of flight software algorithms.

## Architecture and Entry Point of the INTERPRETER System

The interpreter acts as a virtual machine layer between native AGC assembly and high-level mathematical algorithms. It resides in **`Luminary099/INTERPRETER.agc`**, included by `MAIN.agc` at line 55 via the assembly directive `$INTERPRETER.agc`.

### Initializing Interpretive Mode with `INTPRET`

The public entry point **`INTPRET`** (lines 34-55) initializes the interpreter state when the main dispatcher (`DANZIG`) invokes interpretive execution. According to the file comments on lines 34-38, this routine performs four critical setup actions:

- **Set the location counter**: `EXTEND` / `QXCH LOC` loads the starting address of the interpretive program into `LOC` (lines 34-45)
- **Configure bank addressing**: `CA BBANK` / `TS BANKSET` loads the interpretive program's bank into `BANKSET`, enabling addressability without super-bank switching (lines 46-48)
- **Record bank flags**: `MASK BIT15` / `TS INTBIT15` captures the bit-15 flag of `FBANK` to handle high-bank versus low-bank addressing rules (lines 49-50)
- **Prepare first opcode**: `TS EDOP` clears any leftover instruction residue before `TCF NEWOPS` fetches the initial opcode pair (lines 52-55)

## The Opcode Dispatch Loop

Once initialized, the interpreter enters **`NEWOPS`**, the core fetch-decode-execute cycle that processes interpretive programs stored in erasable memory until encountering an exit code.

### Fetching Opcode Pairs with `NEWOPS`

The **`NEWOPS`** routine implements the main loop that drives the virtual machine:

```asm
NEWOPS  INDEX LOC                # Advance location counter and load next word

        CA  0                    # Load opcode pair into accumulator

        CCS A                    # Sign test → absolute value

        TCF DOSTORE              # Branch to store-code handler if applicable

```

This sequence uses `INDEX LOC` to advance the program counter, loads the 15-bit opcode pair into the accumulator, and applies `CCS A` to obtain the absolute value. If the high-order bits indicate a store operation, control transfers to `DOSTORE`; otherwise, execution falls through to the next instruction handler. The dispatcher (`DANZIG`) calls back to `INTPRET` whenever a new interpretive job must start after interrupts or mode changes.

## Address Handling in the INTERPRETER System

The AGC INTERPRETER supports three distinct addressing modes to access operands in erasable memory, managed by the **`ADDRESS`** routine (lines 1005-1008).

### Direct and Indexed Addressing

The interpreter determines the addressing mode by testing the low-order bit of the address word:

```asm
ADDRESS MASK  BIT1               # Test indexing flag (BIT1)

        CCS  A
        TCF  INDEX               # If set, resolve via INDEX routine

```

When **`BIT1`** is set, the interpreter jumps to the **`INDEX`** routine (lines 1006-1010), which resolves the index register and constructs the full 12-bit address in `ADDRWD`. Direct addressing places the sub-address directly into `ADDRWD` without indexing.

### Push-Down List Operations

If no address word follows a store code, the interpreter implicitly uses the **push-down list** (a hardware stack). The **`PUSHUP`** routine (lines 1230-1240) manages this stack, allowing arithmetic operations to consume operands from or push results to the top of stack without explicit memory addressing.

## Store Codes and Arithmetic Dispatch

The INTERPRETER system does not implement arithmetic logic directly; instead, it dispatches to specialized sub-routines based on decoded opcodes.

### Processing Store Codes via `DOSTORE`

Store codes (such as `STADR`, `STCALL`, and `STODL`) are handled by **`DOSTORE`** (lines 1004-1013):

```asm
DOSTORE TS  ADDRWD
        MASK  LOW11
        XCH  ADDRWD
        MASK  B12T14
        EXTEND
        MP  BIT5                # Prepare for vector operand fetch

        INDEX  A
        TCF  STORJUMP           # Jump to store-specific handler

```

The sub-address in `ADDRWD` selects the specific store routine from the **`STORJUMP`** table. After the store operation completes, control returns to the dispatcher (`DANZIG`), which fetches the next opcode pair.

### Arithmetic Sub-Routine Delegation

Mathematical operations dispatch via the **`INDJUMP`** (lines 1028-1035) and **`UNAJUMP`** tables defined in `ASSEMBLY_AND_OPERATION_INFORMATION.agc`. For example, the **square-root** operation (`SQRT`) is invoked through the `UNAJUMP` table (lines 1062-1065), executing the iterative algorithm located in `SINGLE_PRECISION_SUBROUTINES.agc`. Similarly, **triple-precision add** (`TAD`) and **vector add** (`VAD`) dispatch through `INDJUMP` to routines in `VECTOR_SUBROUTINES.agc`.

## Exiting the INTERPRETER System

When the decoder encounters an opcode pair of `0`, the **`EXIT`** routine (lines 1051-1057) terminates interpretive execution:

```asm
EXIT    CA  BANKSET
        TS  BBANK               # Restore original bank set

        INDEX  LOC
        TC  1                   # Return to native dispatcher (DANZIG)

```

This sequence restores the user's bank settings (`BBANK`) and returns control to the native AGC instruction stream via the dispatcher.

## Practical Implementation Example

The following assembly demonstrates calculating a vector magnitude using the interpreter to execute `DOT` followed by `SQRT`, leveraging the push-down list for operand passing:

```asm
; Interpretive program stored at address 3000 in erasable memory
3000:  0025          ; DOT opcode (vector dot product) - INDJUMP entry 27
3001:  0010          ; SQRT opcode - UNAJUMP entry
3002:  0000          ; EXIT opcode or dummy word

; Native AGC setup code
        CAF   XCOMP
        PDDL                 ; Push X component onto stack
        CAF   YCOMP
        PDDL                 ; Push Y component
        CAF   ZCOMP  
        PDDL                 ; Push Z component
        CAF   3000           ; Load interpretive program address
        TC    INTPRET        ; Enter interpreter
        ; Vector magnitude now resides in MPAC registers

```

The interpreter fetches the `DOT` opcode, computes the vector dot product of the three pushed components, then processes the `SQRT` opcode to produce the magnitude, leaving the final result in the **MPAC** (Multi-Purpose Accumulator) registers before executing `EXIT`.

## Summary

- The **AGC INTERPRETER system** in `Luminary099/INTERPRETER.agc` provides a virtual machine that executes compact interpretive programs stored in erasable memory, distinct from native AGC instructions.
- Entry via **`INTPRET`** initializes the location counter `LOC`, bank set `BANKSET`, and bit-15 flags before entering the **`NEWOPS`** fetch-decode loop.
- The system supports **three addressing modes**: direct (12-bit `ADDRWD`), indexed (via `INDEX` routine when `BIT1` is set), and push-down list (stack-based via `PUSHUP`).
- **Store codes** dispatch through `DOSTORE` and `STORJUMP`, while arithmetic operations delegate to specialized sub-routines via `INDJUMP` and `UNAJUMP` tables in external files.
- Execution terminates through the **`EXIT`** opcode (lines 1051-1057), which restores native bank settings and returns control to the `DANZIG` dispatcher.

## Frequently Asked Questions

### What is the primary function of the INTERPRETER system in the AGC?

The INTERPRETER system serves as a virtual machine that executes mathematical algorithms stored as compact opcode sequences in erasable memory. It enables the Apollo Guidance Computer to perform complex calculations—such as vector arithmetic, trigonometric functions, and coordinate transformations—without requiring every operation to be coded in native AGC assembly, significantly reducing memory usage while maintaining computational flexibility.

### How does the AGC INTERPRETER handle arithmetic operations?

The interpreter does not implement arithmetic logic directly within `INTERPRETER.agc`. Instead, it uses jump tables (`INDJUMP` for binary operations like `TAD` and `VAD`, `UNAJUMP` for unary operations like `SQRT`) to dispatch to dedicated sub-routines located in files such as `SINGLE_PRECISION_SUBROUTINES.agc` and `VECTOR_SUBROUTINES.agc`. When the decoder identifies an arithmetic opcode, it transfers control to the appropriate routine, which executes the calculation and returns to the dispatch loop.

### What addressing modes does the AGC INTERPRETER support?

The system supports three distinct operand addressing modes: **direct addressing** (placing a 12-bit sub-address directly in `ADDRWD`), **indexed addressing** (setting `BIT1` to trigger the `INDEX` routine for register-relative addressing), and **push-down list** (using the hardware stack managed by `PUSHUP` when no explicit address follows a store code). The `ADDRESS` routine (lines 1005-1008) tests the low-order bit to determine whether indexing applies.

### Where is the INTERPRETER system code located in the Apollo-11 repository?

The core virtual machine implementation resides in **`Luminary099/INTERPRETER.agc`** (pages 1002-1094), which `MAIN.agc` includes at assembly time. Supporting arithmetic routines live in `SINGLE_PRECISION_SUBROUTINES.agc` and `VECTOR_SUBROUTINES.agc`, while constant tables and opcode documentation appear in `ASSEMBLY_AND_OPERATION_INFORMATION.agc` and `INTERPRETIVE_CONSTANT.agc`.