BMOW title
Floppy Emu banner

Tiny CPU Instruction Set

After four months of inactivity, here’s some documentation for the Tiny CPU instruction set.
 

opcode

x0

x1

x2

x3

x4

x5

x6

x7

x8

x9

xA

xB

xC

xD

xE

xF

0x

SUB abs SUB imm SUB abs,X ADD abs ADD imm ADD abs,X CMP abs CMP imm CMP abs,X NOR abs NOR imm NOR abs,X

1x

LDA abs LDA imm LDA abs,X STA abs STA imm STA abs,X LDX abs LDX imm CPX abs CPX imm STX abs

2x

BNE
abs
BEQ abs BCC abs BCS abs

3x

PLA PLX RETURN PHA PHX JMP abs CALL abs INX DEX

Addressing Modes

imm immediate LDA #$1F operand is literal byte $1F
abs absolute LDA $1FF operand is contents of address $1FF
abs,X absolute, X-indexed LDA $1FF,X operand is contents of address formed by adding $1FF to the value in the X register
impl implied INX operand is implied by the instruction

Encoding

The instruction’s opcode is packed into the most significant six bits of a program byte. Instructions with no operands (implied addressing) require only a single program byte. Address operands are 10 bits, formed from the least significant two bits of the first program byte, and all eight bits of the second program byte. Immediate operands are 8 bits, taken from the second program byte.

Programmer-Visible Registers

PC program counter (10 bit)
SP stack pointer (6 bit)
A accumulator (8 bit)
X index register (8 bit)
SR status register [carry, zero] (2 bit)

Processor Stack

LIFO, top down, 64 entry, $3C0 – $3FF

Instructions

ADD — add to accumulator with carry-out
A, C <- A + OPERAND
status flags affected: C, Z
 
BCC — branch if carry flag is clear
PC <- OPERAND if C = 0
status flags affected: none
 
BCS — branch if carry flag is set
PC <- OPERAND if C = 1
status flags affected: none
 
BEQ — branch is zero flag is set
PC <- OPERAND if Z = 1
status flags affected: none
 
BNE — branch is zero flag is clear
PC <- OPERAND if Z = 0
status flags affected: none
 
CALL — push return address onto stack, and branch to new location
(SP) <- PC
PC <- OPERAND
status flags affected: none
 
CMP — compare with accumulator
A – OPERAND
status flags affected: C, Z
 
CPX — compare with X register
X – OPERAND
status flags affected: C, Z
 
DEX — decrement X register
X <- X – 1
status flags affected: Z
 
INX — increment X register
X <- X + 1
status flags affected: Z
 
JMP — branch to new location
PC <- OPERAND
status flags affected: none
 
LDA — load accumulator
A <- OPERAND
status flags affected: Z
 
LDX — load X register
X <- OPERAND
status flags affected: Z
 
NOR — bitwise nor with accumulator
A <- A NOR OPERAND
status flags affected: Z
 
PHA — push accumulator onto stack
(SP) <- A
status flags affected: none
 
PHX — push X register onto stack
(SP) <- X
status flags affected: none
 
PLA — pull stack value into accumulator
A <- (SP)
status flags affected: none
 
PLX — pull stack value into X register
X <- (SP)
status flags affected: none
 
RETURN — pull stack value into program counter, and branch to new location
PC <- (SP)
status flags affected: none
 
STA — store accumulator
OPERAND <- A
status flags affected: none
 
STX — store X register
OPERAND <- X
status flags affected: none
 
SUB — subtract from accumulator with carry-out
A, C <- A – OPERAND
status flags affected: C,Z
Read 8 comments and join the conversation 

8 Comments so far

  1. Jeff Hopkins November 8th, 2010 3:37 pm

    Good work! Keep it coming

  2. zerx November 11th, 2010 2:47 am

    thanks very much.I’m always waiting for this..

  3. Erik Petrich November 19th, 2010 3:36 pm

    Finally, a processor that supports STA imm. I suppose the logical outcome of this instruction would be that the second byte of this instruction is changed to reflect the current contents of the A register.

    (It’s probably just an oversight in the table, but it amuses me nonetheless)

  4. Steve November 19th, 2010 9:15 pm

    Ha, good catch. It also supports some other dubious instructions, like STX abs,X.

  5. David February 22nd, 2011 10:28 am

    Hey Steve, what’s up? Is this project dead?

  6. Steve February 22nd, 2011 3:04 pm

    Nope, it’s not dead, but it’s on the back burner due to work commitments. I definitely hope to return to it soon.

    Personal note: I joined an MMO game startup in 2006, and started development on the game that became RIFT. Since then it’s absorbed increasing amounts of my time. Now after a four and a half year odyssey, RIFT is finally launching! Servers open for business on Thursday February 24. http://www.riftgame.com

  7. A February 10th, 2012 1:32 am

    Lol, wasting time with video games instead of computer architecture? What a waste. Wasteful.

  8. Mr. Wilson September 20th, 2020 9:19 am

    22 instructions is good, but if you can get it down to 16, you’ll have a 4-bit opcode. You don’t need a CMP because that’s just a SUBtract without keeping the result. ALSO, if you can load in and invert the flags, you won’t need the “NOT” versions of the conditional jumps. Just load the flags and either AND to select the desired flag or just invert the whole flags register to make a BEQ a BNQ, for example. If you write an assembler, it can do that stuff for you so all your “Not” jumps are pseudo-commands.

    All good wishes.

Leave a reply. For customer support issues, use the Contact page instead of comments.