Overview
Memory Map
Register Set
Instruction Encoding
Assembler Syntax
IO Devices
VRAM Layout
Syscall Mechanism
Instruction Set
Development Notes
License
Contributions
Neptune is a custom-built 32-bit CPU emulator with an integrated assembler and assembly language. It is designed for educational purposes, experimentation, and as a foundation for building simple operating systems or games. The emulator simulates RAM, ROM (used for syscalls), VRAM for graphical output, a stack, a heap, and memory-mapped IO devices. It uses little-endian word addressing and has fixed-size instructions (single or double word).
Region
Address Range
Size
Description
ROM
0x00000000 - 0x00001FFF
8 KB
Boot ROM (syscalls, bootloader)
- Boot Code
0x00000000 - 0x0000000F
16 B
Bootloader code
- Syscall Table
0x00000010 - 0x0000010F
256 B
Maps syscall numbers to handler addresses
- Syscall Code
0x00000110 - 0x0000090F
2 KB
Syscall handler implementations
- ROM Free
0x00000910 - 0x00001FFF
5.7 KB
Available ROM space for extensions
RAM
0x00002000 - 0x00101FFF
1 MB
Main system RAM
- Program Area
0x00002000 - 0x00081FFF
512 KB
User program space
- Heap
0x00082000 - 0x00101FFC
512 KB
Dynamic memory (grows upwards)
- Stack
0x00101FFD - 0x00101FFF
3 B
Call stack (grows down from top of RAM)
VRAM
0x00102000 - 0x00111FFF
64 KB
Video RAM (128x128 RGBA32 framebuffer)
IO
0x00112000 - 0x00112FFF
4 KB
Memory-mapped input/output devices
Memory is byte-addressable but operates on 32-bit words
All addresses are 32-bit
Stack collisions with heap result in runtime errors
Words are 32-bit (4 bytes) and affect instruction encoding
Neptune has 32 general-purpose registers (configurable in constructor) plus special registers:
General-Purpose Registers
Register
Description
r0 - r31
General-purpose registers (32 total, default)
Register
Description
PC
Program Counter, tracks next instruction
SP
Stack Pointer, grows downward
HP
Heap Pointer, grows upward
FLAGS
Contains four boolean flags
The FLAGS register contains four boolean flags:
Z (Zero): Set if result is zero
N (Negative): Set if result is negative (signed)
C (Carry): Set if unsigned carry occurs
V (Overflow): Set if signed overflow occurs
Single Word Instructions (Register-Register)
| 31-24: rDest | 23-16: rSrc | 15-8: Reserved | 7-0: Opcode |
Example: ADD r1, r2 → r1 = r1 + r2 (r1 is both source and destination)
Double Word Instructions (Immediate)
Word 1: | 31-24: rDest | 23-16: 0 | 15-8: Reserved | 7-0: Opcode |
Word 2: Immediate value (32-bit literal/address)
Example: MOVI r1, 42 → r1 = 42
Jump/Call Instructions (Double Word)
Use the same immediate encoding format, where Word 2 is the absolute 32-bit address
Labels: label: (used for jumps and calls)
Comments: ; starts a comment line
Instructions: Case-insensitive (recommended uppercase)
Immediate literals:
Decimal: 42
Hexadecimal: 0x2A
No directives like .org or .word are currently supported
Offset
Name
Type
Description
+0x00
FIRST_CHAR
RO
ASCII code of the oldest char in buffer
+0x04
BUFFER_READY
RO
1 if buffer has >=2 chars, else 0
+0x08
CURRENT_CHAR
RO
Most recent char pressed
+0x0C
CONTROL
WO
1=consume oldest, 2=clear buffer, 3=reset
Write ASCII values to the output register at offset +0x00
CPU sends bytes to display as console output
Provides tick counts or can be expanded for interrupts
Resolution: 128x128 pixels
Format: RGBA32 (4 bytes per pixel)
Total Size: 64 KB
Address formula:
address = VRAM_BASE + (y * 128 + x) * 4
Pixel layout: Row-major order (left-to-right, top-to-bottom)
Each pixel is stored as 4 consecutive bytes:
| +0: Alpha | +1: Blue | +2: Green | +3: Red |
Write to VRAM to update the framebuffer
Invoke syscalls using the SYSCALL instruction
Syscall number is placed in register r0
The syscall handler address is looked up in ROM's syscall table (64 possible syscalls)
The CPU pushes PC onto the stack and jumps to the syscall handler
Use RET at the end of the syscall handler to return
Instruction
Description
ADD rDest, rSrc
Add rSrc to rDest, store in rDest, update flags
ADDI rDest, imm
Add immediate to rDest, store in rDest, update flags
SUB rDest, rSrc
Subtract rSrc from rDest, store in rDest, update flags
SUBI rDest, imm
Subtract immediate from rDest, store in rDest, update flags
MUL rDest, rSrc
Multiply rDest by rSrc, store in rDest, update flags
MULI rDest, imm
Multiply rDest by immediate, store in rDest, update flags
DIV rDest, rSrc
Divide rDest by rSrc, store in rDest, update flags (throws if divide by zero)
DIVI rDest, imm
Divide rDest by immediate, store in rDest, update flags (throws if divide by zero)
MOD rDest, rSrc
Modulo rDest by rSrc, store in rDest, update flags (throws if modulo by zero)
MODI rDest, imm
Modulo rDest by immediate, store in rDest, update flags (throws if modulo by zero)
INC rDest
Increment rDest by 1, update flags
DEC rDest
Decrement rDest by 1, update flags
NEG rDest
Negate rDest, update flags
Instruction
Description
AND rDest, rSrc
Bitwise AND rDest with rSrc, store in rDest, update flags
ANDI rDest, imm
Bitwise AND rDest with immediate, store in rDest, update flags
OR rDest, rSrc
Bitwise OR rDest with rSrc, store in rDest, update flags
ORI rDest, imm
Bitwise OR rDest with immediate, store in rDest, update flags
XOR rDest, rSrc
Bitwise XOR rDest with rSrc, store in rDest, update flags
XORI rDest, imm
Bitwise XOR rDest with immediate, store in rDest, update flags
NOT rDest
Bitwise NOT of rDest, store in rDest, update flags
Instruction
Description
SHL rDest, shift
Shift rDest left by shift bits, store in rDest, update flags
SHR rDest, shift
Logical shift rDest right by shift bits, store in rDest, update flags
Instruction
Description
LOAD rDest, rAddr
Load word from memory at rAddr into rDest, update flags
STORE rSrc, rAddr
Store word from rSrc into memory at rAddr
LOADI rDest, immAddr
Load word from memory at immediate address into rDest, update flags
STORI rSrc, immAddr
Store word into memory at immediate address
MSET rAddr, rValue
Set r1 words starting at rAddr to rValue
MCPY rDest, rSrc
Copy r1 words from rSrc to rDest
Control Flow Instructions
Instruction
Description
JMP address
Jump unconditionally
CALL address
Push PC to stack, jump to address (2-word instruction)
RET
Pop PC from stack and jump back
Conditional Jumps (Equality/Zero)
Instruction
Description
JZ address
Jump if zero flag is set (==)
JE address
Jump if zero flag is set (==)
JNZ address
Jump if zero flag is not set (!=)
Conditional Jumps (Signed Comparison)
Instruction
Description
JN address
Jump if negative flag is set (signed < 0)
JP address
Jump if negative flag is not set (signed >= 0)
JG address
Jump if greater (signed >) - zero flag not set AND negative flag not set
JGE address
Jump if greater or equal (>=) - negative flag not set
JL address
Jump if less (signed <) - negative flag set
JLE address
Jump if less or equal (<=) - negative flag set OR zero flag set
Conditional Jumps (Unsigned Comparison)
Instruction
Description
JC address
Jump if carry flag is set (unsigned <)
JNC address
Jump if carry flag is not set (unsigned >=)
JA address
Jump if above (unsigned >) - carry flag not set AND zero flag not set
JAE address
Jump if above or equal (>=) - carry flag not set
JB address
Jump if below (unsigned <) - carry flag set
JBE address
Jump if below or equal (<=) - carry flag set OR zero flag set
Instruction
Description
PUSH rSrc
Push register rSrc onto stack
POP rDest
Pop from stack into rDest, update flags
Data Movement Instructions
Instruction
Description
MOV rDest, rSrc
Copy value from rSrc into rDest, update flags
MOVI rDest, imm
Load immediate into rDest, update flags (2-word instruction)
CLR rDest
Clear rDest (set to 0), update flags
Instruction
Description
CMP rA, rB
Compare rA with rB (rA - rB), update flags (no register change)
CMPI rA, imm
Compare rA with immediate, update flags (no register change)
TEST rA, rB
Bitwise AND of rA and rB, update flags (no register change)
TESTI rA, imm
Bitwise AND of rA and immediate, update flags (no register change)
Instruction
Description
SYSCALL
Execute system call specified by r0
NOP
No operation
HLT
Halt the CPU
Instruction Category
Z
N
C
V
Arithmetic
✔
✔
✔
✔
Logic
✔
✔
✖
✖
CMP/TEST
✔
✔
✖
✖
MOV/MOVI
✔
✔
✖
✖
PC starts at main: label
ROM is reserved for syscall handlers and the syscall table
Heap grows upward from HEAP_START (0x00004000)
Stack grows downward from STACK_START (0x00021FFC)
Heap-stack collision triggers a runtime panic
VRAM is read-write memory for external graphics engines
Register count is configurable in constructor (default: r0-r31)
Words are 32-bit (4 bytes)
Directives in assembler (.data, .org, etc.)
Interrupt support
Floating-point instructions
More IO devices (audio, mouse, network)
MIT License.
Contributions are welcome. Submit pull requests to add IO devices, instructions, syscall implementations, or assembler features.