- 16 bits wide
- R0 always reads 0, no effect on write
- R1..R15 - general purpose, RW
- PC - program counter, RO
Each instruction consists of 1 up to 5 bytes.
First byte is instruction description byte, rest is instruction operands
Description byte format is TT?????
where TT
is instruction type and rest of
bits are type-specific.
Instruction type may be of 11
, 01
, 10
and 00
where
00
is A-instruction01
is M-instruction10
is J-Instruction11
is S-instruction
A-instruction uses three operands: A, B and C.
Value of register A is combined with B using operation specified by F and then
stored to register specified by C. A-instruction-specific bit format is as follows:
FFFxxI
, where F
specifies operation:
000
for addition001
for substraction010
for division011
for multiplication100
for bitwise xor101
for bit shift110
for bitwise and111
for bitwise orI
mmediate indicates if B is an immediate value
M-instructions are using two operands and have this specific bit pattern:
FHWxAB
. F
is operation - 1
for store and 0
for load. H
igh indicates if
0xFFFF should be added to memory address specified by operand in order to access
addresses above 0xFFFF. W
ord indicates if stored\loaded value is word or a
byte. First operand specifies memory address and second operand is either a
value to write in case of store or a destination register for load. AB
bits
are set accordingly. Load can only have register as destination, so A
is
unused if F
is 0
.
J-instruction are using two operands. First operand is a register to check for
condition and second operand is immediate or register containing address for a
jump. Specific bits: CCxxxI
, where C
ondition may be one of
00
for greater than zero01
for less than zero10
for equal to zeroI
indicates that second operand is immediate.
S-instruction don't have operands. Only first bit is significant, indicating if
it's int
for 1
or brk
if it's 0
.
Addr range | Size | Device |
---|---|---|
00000-00006 | 6 | Interrupt controller |
00006-00007 | 1 | Input controller |
00007-00014 | 7 | Cartridge controller |
00014-16456 | 16441 | GPU |
16456-16968 | 512 | ROM |
16968-17406 | 438 | Reserved |
17406-18430 | 1024 | Battery-backed |
18430-65535 | 47105 | RAM |
Offset | Mode | Description |
---|---|---|
00000 | RO | Return address |
00002 | RW | Interrupt mask |
00003 | RW | Interrupt state |
00004 | RW | Interrupt handler addr |
Return address word:
- Stores PC when interrupt happened before jumping to handler
Interrupt mask byte:
- When bit is 1 - interrupt is masked
- When interrupt masked handler won't be invoked when interrupt raised
- All interrupts are masked before interrupt handler is invoked
- 0 bit: Data transfer finished
- 1 bit: Cart presence changed
- 2 bit: GPU command finish
- 3 bit: GPU invalid command
- 4 bit: Input state change
- 5 bit: Clock
- 6 bit: Reserved
- 7 bit: Reserved
Interrupt flags byte:
- Indexes are same as in mask byte
- Bit set to 1 when interrupt is active
- Set corresponding bit to 0 to mark interrupt as handled
Interrupt handler address word
- Stores address to jmp to when interrupt is raised
Offset | Mode | Description |
---|---|---|
00000 | RO | State bit |
00001 | RW | SRC word |
00003 | RW | DST word |
00005 | RW | LEN word |
Present byte:
- 1 when cartridge present
- 0 otherwise
SRC word:
- Starting address in cartridge mem to read from during data transfer
DST word:
- Starting address in main memory to write to during data transfer
LEN word:
- Length of buffer to transfer
- Non-zero when data transfer in progress
- Write non-zero value to start data transfer
- Resets to 0 when data transfer completed
Offset | Mode | Description |
---|---|---|
00000 | RW | Command argument register 1 |
00002 | RW | Command argument register 2 |
00004 | RW | Command argument register 3 |
00006 | RW | Command argument register 4 |
00008 | RW | Control |
00009 | RW | Transparency mask |
00010 | RW | Palette |
00058 | RW | Sprite map |
Palette 48 bytes:
- Array of 16 colors
- Each color is 3 RGB bytes
Sprites 16384 bytes:
- Array of 512 sprites
- Sprite is 8x8 pixel grid
- Pixel is 4 bit index to pallete
Control byte:
(IIII CCCC)
(C)
Command 4 bit index- Index of GPU command to execute
- 0x0: blit
- 0x1: line
- 0x2: fill
- 0x3: scroll
- 0x4: pixel
- Write command index to start executing command
- Resets to 0 when command execution finished
(I)
Color 4 bits:- Index of color from palette to use when drawing
Argument | Valid values |
---|---|
SprIx | 0..511 |
X | 0..319 |
Y | 0..239 |
N, M | 0..65535 |
Color | 0..15 |
Mnemonic | Index | Arguments | Description |
---|---|---|---|
Blit | 0 | SprIx, X, Y | Blit sprite with SprIx to X,Y position, where X,Y is top-left corner |
Line | 1 | X1, Y1, X2, Y2 | Draw a line from X1,Y1 to X2,Y2 using current color |
Fill | 2 | X1, Y1, X2, Y2 | Draw filled rectangle with current color with top level corner X1,Y1 and right bottom corner at X2,Y2 |
Scroll | 3 | N, M | Scroll screen to horizontally by N and vertically by M pixels, filling new space with current color |
Pixel | 4 | X, Y | Draw a pixel at X,Y using current color |
Offset | Mode | Description |
---|---|---|
00000 | RO | Input state |
Input state byte:
(PCCCCCCC)
(P)
- button pressed state(C)
- character of pressed button
Battery-backed: persists its contents without power RAM: conventional RAM, 16bits width, byte-addressable
<instruction>
.<command>
Commands:
- label - mark next instruction address as
- export - make available to use in another files
- import - use address from another file
- const - define constant value of named
- - ignore everything until eol, used as comment
Mnemonic | A | B | C | Note |
---|---|---|---|---|
add | r | r/i | r | |
sub | r | r/i | r | |
div | r | r/i | r | |
mul | r | r/i | r | |
xor | r | r/i | r | |
shf | r | r/i | r | |
and | r | r/i | r | |
or | r | r/i | r | |
save | r/i | r/i | Write lower byte of A to mem[B] | |
savew | r/i | r/i | Write A to mem[B] | |
saveh | r/i | r/i | Write lower byte of A to mem[0xFFFF + B] | |
savehw | r/i | r/i | Write A to mem[0xFFFF + B] | |
load | r/i | r | Write mem[A] to lower byte of register B | |
loadw | r/i | r | Write word at mem[A] to register B | |
loadh | r/i | r | Write mem[0xFFFF + A] to lower byte of to register B | |
loadhw | r/i | r | Write word at mem[0xFFFF + A] to register B | |
jgz | r | r/i | Jump to mem[B] if A is >0 | |
jlt | r | r/i | Jump to mem[B] if A is <0 | |
jez | r | r/i | Jump to mem[B] if A is 0 | |
int | Interrupt | |||
hlt | Halt CPU until next interrupt |
Instructions not implemented but can be improvised from existings ones:
Mnemonic | A | B | C | Instead use |
---|---|---|---|---|
set | r/i | r | add r0 A B | |
nop | add r0 r0 r0 (or any other arith or logic instruction) | |||
cmp | r/i | r/i | r | sub A B C |
inc | r | add A 1 A | ||
dec | r | sub A 1 A | ||
jmp | r/i | jez r0 A |