- 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
00is A-instruction01is M-instruction10is J-Instruction11is 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:
000for addition001for substraction010for division011for multiplication100for bitwise xor101for bit shift110for bitwise and111for bitwise orImmediate 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. High indicates if
0xFFFF should be added to memory address specified by operand in order to access
addresses above 0xFFFF. Word 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 Condition may be one of
00for greater than zero01for less than zero10for equal to zeroIindicates 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 |