Go to file
n loewen af52d4f373 (notes) - 2023-08-23 - Add a caveat about the current plan for the new ISA (requires 8-bit addressing) 2023-08-23 14:47:38 +01:00
notes (notes) - 2023-08-23 - Add a caveat about the current plan for the new ISA (requires 8-bit addressing) 2023-08-23 14:47:38 +01:00
sketches Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
test-programs assembler - WIP - Start adding a 'set the initial IP to assembler to' feature + Start adding a 'return debug data as well as machine code' feature 2023-08-21 16:08:58 +01:00
assembler.js assembler - Finish WIP - Refactor extensively / Add a 'set the initial address to assemble at' feature / Add a feature that collects debug info that could be passed as output when running in debug mode 2023-08-22 13:03:52 +01:00
cpu.js Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
display.js Merge branch '5x5-display' 2023-08-21 14:38:02 +01:00
jsconfig.json Turn on Jsdoc-based type checking 2023-08-03 16:24:51 +01:00
logging.js Feature: WIP: Replace CHP and CFC instructions with FHP and FTG (carry flag is implemented, other flags are not) 2023-08-15 12:04:48 +01:00
machine.config.js Feature: Keypad simulation! 2023-08-16 16:23:59 +01:00
package-lock.json Feature (CPU): Implement a simple single-stepping mode 2023-08-16 13:56:23 +01:00
package.json Feature (CPU): Implement a simple single-stepping mode 2023-08-16 13:56:23 +01:00
readme.md readme - WIP - Change "Instruction Set" section to describe a new, revised architecture 2023-08-23 14:45:14 +01:00
run-assembler.js assembler - Finish WIP - Refactor extensively / Add a 'set the initial address to assemble at' feature / Add a feature that collects debug info that could be passed as output when running in debug mode 2023-08-22 13:03:52 +01:00
run-cpu.js Docs: Update todos re: invoking the cpu/assembler; move notes on this from `run-cpu.js` to `todo.md` 2023-08-16 16:36:01 +01:00
scratch.js assembler - WIP - Start adding a 'set the initial IP to assembler to' feature + Start adding a 'return debug data as well as machine code' feature 2023-08-21 16:08:58 +01:00

readme.md

Cardiograph Mark I — simulator for a paper computer

Dependencies

  • Node.js
    • readline-sync

Run

Assemble

Hex output:
./run-assembler run source_code.asm

Binary output:
./run-assembler runbin source_code.asm

Verbose debugging output (hex):
./run-assembler debug source_code.asm

Assemble and run

With animated display of screen memory:
./run-cpu run source_code.asm

With verbose debugging output:
./run-cpu debug source_code.asm

With single stepping + pretty-printed display:
./run-cpu step source_code.asm

With single stepping + verbose debugging output:
./run-cpu stepdebug source_code.asm

Registers and Flags

  • A - accumulator
  • IP - instruction pointer (aka program counter)
  • FLAGS - flags: Negative, Zero, Overflow, Carry
    • in machine language, each flag is given a number:
      • N = 3
        Z = 2
        O = 1
        C = 0
    • (bitwise, 0000 = NZOC)

Instruction set

Operations

Hex  Mnem.  Name         Operand type  Effect
---------------------------------------------

00   END    End          (ignored)     Halt CPU
01   NOP    No op        (ignored)     None

50   STO    Store        literal #     mem[lit#] = A
51   LDA    Load         literal #     A = lit#
52   ADD    Add          literal #     A = A + lit#
53   SUB    Sub          literal #     A = A - lit#
54   HOP    Hop          literal #     If A == lit#, skip next op (IP += 4)
55   JMP    Jump         literal #     IP = lit#
56   FTG    Flag toggle  literal #     Toggle flag, where flag number == lit#
57   FHP    Flag hop     literal #     Skip next op if flag is set, where flag number == lit#

60   STO    Store        address       mem[mem[addr]] = A
61   LDA    Load         address       A = addr
62   ADD    Add          address       A = A + mem[addr]
63   SUB    Sub          address       A = A - mem[addr]
64   HOP    Hop          address       If A == mem[addr], skip next instruction (IP += 4)
65   JMP    Jump         address       IP = mem[addr]

Map + effects on flags, registers

hex   bin          group  mode      op   mem  flags  IP
-------------------------------------------------------
00    0000 0000    0      --        END              +2
01    0000 0001    0      --        NOP              +2

50    0101 0000    1      direct    STO  w           +2
51    0101 0001    1      direct    LDA  r    NZ     +2
52    0101 0010    1      direct    ADD       NZOC   +2
53    0101 0011    1      direct    SUB       NZOC   +2
54    0101 0100    1      direct    HOP              +2/+4
55    0101 0101    1      direct    JMP              arg
56    0101 0110    1      direct    FTG       NZOC   +2
57    0101 0111    1      direct    FHP       NZOC   +2/+4

60    0110 0000    1      indirect  STO  r,w         +2
61    0110 0001    1      indirect  LDA  r,r  NZ     +2
62    0110 0010    1      indirect  ADD  r    NZOC   +2
63    0110 0011    1      indirect  SUB  r    NZOC   +2
64    0110 0100    1      indirect  HOP  r           +2/+4
65    0110 0101    1      indirect  JMP  r           arg
66    0110 0110    1      indirect  FTG  r    NZOC   +2
67    0110 0111    1      indirect  FHP  r    NZOC   +2/+4

CPU start-up

When starting up, the CPU executes a JMP $FF.

Put differently: it starts executing instructions at the address contained in $FF.

Cardiograph memory map

  • 00-19 - display (5x5)
  • 1A - pointer to display memory
  • 1B - keypad: value of latest key pressed
  • 1C - reserved for future use (bank switching flag)
  • 1D-FF - free

Peripherals

Keypad

The value of the latest keypress on a hex keypad is stored at $1B.

The keypad uses the same layout as the COSMAC VIP (and CHIP-8). The CPU simulator maps those keys onto a Qwerty set.

1 2 3 C    1 2 3 4
4 5 6 D    Q W E R
7 8 9 E    A S D F
A 0 B F    Z X C V

  VIP     simulator

Assembly language

ADD $01         ; comments follow a `;`

ADD $FF         ; this is direct addressing
ADD ($CC)       ; this is indirect addressing

END             ; END and NOP don't require operands
                ; (the assembler will fill in a default value of 0)

@subroutine     ; create a label
    ADD $01     ; (it must be on the line before the code it names)
    ADD $02

JMP @subroutine ; use a label as operand
                ; the label will be replaced with
                ; the address of the label

#foo $FF        ; define a constant
                ; (must be defined before it is referenced)

ADD #foo        ; use a constant as an operand

LDA *           ; `*` is a special label referencing the memory address
                ; where the current line will be stored after assembly
  • Hexadecimal numbers are preceded by a $
  • Whitespace is ignored