Skip to content

Instructions

Andreas Taylor edited this page Dec 7, 2025 · 9 revisions

Instructions

This is Version 2 of the CPU design.

Core Instructions

These instructions are implemented in the CPU hardware directly.

Four-character fixed-length mnemonics are used to simplify the assembler implementation.

The Flags column indicates how flags are affected by the operation:

-: Flag is not affected
0: Flag is cleared
1: Flag is set
S, Z, C, V: Flag value depends on result of operation

Mnemonic Description Mode SZCV (Flags) Notes
LDAL Immediate value into AA, lower nibble IMM ----
LDAH Immediate value into AA, upper nibble IMM ----
LDBL Immediate value into AB, lower nibble IMM ----
LDBH Immediate value into AB, upper nibble IMM ----
LJLL Immediate value into JL, lower nibble IMM ----
LJLH Immediate value into JL, upper nibble IMM ----
LJHL Immediate value into JH, lower nibble IMM ----
LJHH Immediate value into JH, upper nibble IMM ----
LOAD Memory into AA IND ----
STOR AA into memory IND ----
MOVE Move register to/from AA DIR ----
PUSH Push register onto the stack IMP ---- Supports registers AA and FL only
POPP Pop stack into register IMP ---- Supports registers AA and FL only
COMP AA ^ AB, discard result DIR 0Z00 Z flag set if AA and AB are the same
SUBB AA <- AA - AB DIR SZCV Z flag set if AA and AB are the same
ADDD AA <- AA + AB DIR SZCV
ANDD AA <- AA & AB DIR 0Z00
ORRR AA <- AA | AB DIR 0Z00
XORR AA <- AA ^ AB DIR 0Z00
NAND AA <- ~(AA & AB) DIR 0Z00
NORR AA <- ~(AA | AB) DIR 0Z00
NOTT AA <- ~(AA) DIR 0Z00 1's complement
NEGA AA <- 0 - AA DIR 0Z00 2's complement
XNOR AA <- ~(AA ^ AB) DIR 0Z00
SHRL Shift right logical on AA DIR 0ZC0 Bit 0 is shifted into C; bit 7 is set to 0
SHLL Shift left logical on AA DIR 0ZC0 Bit 7 is shifted into C; bit 0 is set to 0
SHRA Shift right arithmetic on AA DIR 0ZC0 Bit 7 is shifted into itself and bit 6; bit 0 is shifted into C
SRLC Shift AA right using Carry flag DIR 0ZC0 C is shifted into bit 7, bit 0 shifted into C
SLLC Shift AA left using Carry flag DIR 0ZC0 C is shifted into bit 0, bit 7 shifted into C
INCA AA <- AA + 1 DIR SZCV Implemented with ADDD and hardcoded 0x01 in ALU
DECA AA <- AA - 1 DIR SZCV Implemented with ADDD and hardcoded 0xFF in ALU
INCB AB <- AB + 1 DIR ---- Uses counter function in register
INCM MR <- MR + 1 DIR ----
INCC AC <- AC + 1 DIR 0Z00
BCFL Clear a bit in FL BIT S|Z|C|V Only 1 flag bit can be changed at a time
BSFL Set a bit in FL BIT S|Z|C|V Only 1 flag bit can be changed at a time
LDA0 Load AA with $00 DIR ---- Loads register with 8-bit value in single instruction
LDB0 Load AB with $00 DIR ---- Loads register with 8-bit value in single instruction
LDC0 Load AC with $00 DIR ---- Loads register with 8-bit value in single instruction
JPVC Jump if Overflow flag is clear IND ---- If true, jump to address in JR
JPVS Jump if Overflow flag is set IND ---- If true, jump to address in JR
JPCC Jump if Carry flag is clear IND ---- If true, jump to address in JR
JPCS Jump if Carry flag is set IND ---- If true, jump to address in JR
JPZC Jump if Zero flag is clear IND ---- If true, jump to address in JR
JPZS Jump if Zero flag is set IND ---- If true, jump to address in JR
JPSC Jump if Sign flag is clear IND ---- If true, jump to address in JR
JPSS Jump if Sign flag is set IND ---- If true, jump to address in JR
JUMP Unconditional jump IND ---- Jump to address in JR
NOOP No operation N/A ----
HALT Stop fetching new instructions N/A ----

Notes on Specific Instructions

LOAD and STOR

LOAD loads the contents of memory location pointed to by MR into AA. STOR stores the contents of register AA into the location pointed to by MR.

MOVE

MOVE moves values between AA and another register. For example, MOVE AA->BA or MOVE JL->AA. Register AA must be the source or destination of the MOVE instruction.

ADDD and SUBB

The Carry bit is included in the sum or difference. Be sure to clear the Carry flag (BCFL C) before executing ADDD or SUBB if you don't want it included in the calculation.

In other words, ADDD is implemented as AA = AA + AB + C, and SUBB is implemented as AA = AA - AB - C.

SRLC and SLLC

The "shift logical through carry" instructions are included in order to simplify multi-byte shift operations. For example, if you wanted to divide a signed 16-bit value by 2, you could use the following:

    LOAD (MR)   ; Start with MSB
    SHRA A      ; Previous bit 0 of MSB is now in Carry flag
    STOR (MR)   ; Save updated MSB
    INCM        ; Move pointer to next byte
    LOAD (MR)   ; Get LSB
    SRLC        ; Bit 0 from MSB is shifted into bit 7 of LSB through Carry flag
    STOR (MM)   ; Save updated LSB

BCFL and BSFL

The set and clear instructions for the flags (BCFL and BSFL) are included in the core CPU instructions because it is cumbersome to perform this operation without any other side effects.

HALT

TBD: Should the HALT instruction set an externally accessible hardware line to signal that the CPU is halted?

Instructions Implemented by the Assembler

In addition to core instructions listed above, several additional instructions will be supported by the assembler. These can be implemented by stringing together several core CPU instructions.

Mnemonic Description SZCV (Flags) Notes
BCAA Clear a bit in AA 0Z00 Load AB with bit mask, then ANDD
BSAA Set a bit in AA 0Z00 Load AB with bit mask, then ORRR
EXCH Exchange AA with AB ---- PUSH AA, AB->AA, AA->AC, POP AA, AA->AB, AC->AA
LDAA 8-bit immediate version of LDAx ---- LDAL, LDAH
LDAB 8-bit immediate version of LDBx ---- LDBL, LDBH
LDJR 16-bit immediate version of LJxx ---- LJLL, LJLH, LJHL, LJHH
AD16 Add two 16 bit values SZCV
SU16 Subtract two 16 bit values SZCV
CM16 2's complement 16 bit value SZ00
XNOR Bitwise XNOR on AA 0Z00 XORR, NOTT
LJMP Long jump ---- LJLL, LJLH, LJHL, LJHH, JUMP
CALL Call subroutine ---- Push PC to stack and jump to location in JR
RETU Return from subroutine ---- Pop JR from stack and jump to location in JR
CAZS Call subroutine if Zero flag set ----
CAZC Call subroutine if Zero flag clear ----
CACS Call subroutine if Carry flag set ----
CACC Call subroutine if Carry flag clear ----
CASS Call subroutine if Sign flag set ----
CASC Call subroutine if Sign flag clear ----
CAVS Call subroutine if Overflow flag set ----
CAVC Call subroutine if Overflow flag clear ----

CALL, CAxx, RETU

The CALL and CAxx instructions need to calculate the "future" PC value at the end of the call sequence, storing and pushing the value using JR. JR is not preserved by CALL and RETU. The calling routine needs to save/push whatever values it wants to preserve before calling the subroutine, and needs to restore/pop any previously saved values after returning. (Note that previously, I had CALL push all the registers to the stack and RETU to pop them back off. I realized that creates significant overhead for subroutine calls and created other design complications.)

The RETU instruction pops the return address to JH and JL and then use JUMP command to return to the instruction after the CALL.

Index Mode Instructions

Index mode instructions may be added later. They aren't strictly necessary, but make using arrays a lot easier.

History

Date Changes
14-Oct-2025 Created - Design Version 2
18-Oct-2025 Optimizing the instruction set
28-Oct-2025 Add EXCH instruction, clarify PUSH, POPP
06-Dec-2025 Instruction changes, see 06-Dec-2025 blog entry

Clone this wiki locally