My CPU - the C16

Feed

date: 2026-01-15 21:00:11

categories: hardware

firstPublishDate: 2025-12-26 18:30:44

The C16 CPU has 32 general purpose registers each 16bit, 32bit or 64bit wide.

Related:

System with the c16 CPU and Gpu1

Gpu1

Verilog tools

I don't use the version with 16bit wide registers because the address space is too small and it needed banking RAM to address more than 64KB.

The ISAs for the 32bit and 64bit version are identical, a 64bit program can run on the 32bit CPU with small changes, mainly changing the addresses to 32bit.

This CPU is called C16 because all the opcodes are 16bit words, it makes the instruction decoder simple and C16 could read 128 bytes per clock cycles and decode 64 instructions.

The goal of the ISA is to have as many bits as possible for the jump (`jmp`) instruction and have as many as possible instructions with 2 register operands.

There are 2 stacks one for data and one for return addresses of functions. It is not possible to change the return address of a function when accessing the data on the data stack since the return address is not stored in the data stack.

The `loadi` instruction load 8bits to register r0, it is the only instruction for loading immediate data to registers.

The conditional jump instructions have 10bit immediate values and can jump +- 512 instructions.

Some instructions can be fused and executed as if it was one instruction. Loading the value 0xff000000 to r0 and r1 can be executed as:

The ISA is able to be extended to support many features:

The performance will be poor if all these features are implemented, because opcodes will reused for integers, floats and vectors and the execution needs to be in-order when switching mode. If the execution is out-of-order and the program changes from integer to float, the CPU might execute instructions in the wrong mode. For these features, the opcodes need to be longer than 16bit or variable length.

The ISA specification is parsed to generate the assembler, the decoder for the virtual CPU and for the hardware CPU.

In current implementation, the instructions execute in between 2 to 5 clock cycle, the design is not pipelined and it run at 50mhz or 100mhz.

This page is about the 32bit c16 ISA.

Registers

r0 to r31 are the general purpose registers. flags, pc (program counter), rsp (return address stack pointer), dsp (data stack pointer), itb (interrupt table address), clkcnt (clock counter) and icnt (instruction counter) are address mapped, it saves bits in the opcode space.

Address map for the 32bit c16:

Flags register

The meaning of the bits in the flags register is:

State flags:

There are conditional jump instructions to check the carry, zero, overflow and sign flags.

ja (jump if above), jae (jump if above or equal, same instruction as jnc), jb (jump if below, same instruction as jc), jbe (jump if below or equal) are for unsigned integer comparisons.

jg (jump if greater), jge (jump if greater or equal), jl (jump if less), jle (jump if less or equal) are for signed integer comparisons.

Instructions

Some instructions have fix registers:

Instructions decription

Interrupts

The interrupt table stores the address of the interrupt handlers, it has 32 entries and is located at address itb. Inerrupt 8 is the hardware interrupt and interrupts from 16 to 31 are free to use by software. Interrupt 0 to 15 are usable but it is not future proof to use them as they will be used in the future versions of the CPU (syscall, divide error, exeptions, timer, ...).

Assembler

The assembler is called `casm` and takes one argument which is the file to compile.

The code is saved in `c16.out` (the emulator executes `c16.out`).

`casm` is a 2 pass assembler, in the first pass it places the code, data and labels and in the second pass it writes code and the address of data and labels.

Example source code:

This is how to compare a register to zero:

It doesn't support declaring variables, just choose addresses in RAM and write comments in the code.

It would be great to have a C compiler for this ISA.

Feed

Guestbook