The DynamicSystems™ CoolCPU is the future of computing.

Advanced features like "addition" and "number comparisons" make anything else seem...uncool.

Try it now

Description

The CoolCPU is a brand new CPU architecture, inspired by processors like the Zilog Z80 and the MOS Technology 6502.

The CoolCPU can access up to 256 bytes of external memory. The first 128 bytes (0x00 to 0x7F) are read-only memory, or ROM, and it's what you set in the "Try it now" box above. Then, the memory from 0x80 to 0xF0 is random-access memory, or RAM. Your code can store and load values from RAM however it wants.

Finally, 0xF1 is the output register. Anything you write to the output register will be printed to the screen.

Registers

The CoolCPU has four main registers. The first is the Program Counter, or PC, which keeps track of the next instruction to run. The PC always starts at 0, and the CPU keeps track of it for you.

The remaining three are registers A, B, and C, which are general-purpose 8-bit registers. You can use them any way you want; however, note that some instructions only work on register A.

Instruction set

Name Hexadecimal Description
NOP 00
No Operation
Does nothing.
LDA nn 01 nn
Load Register A
Reads the data at address nn and stores it in register A.
LDB nn 02 nn
Load Register B
Reads the data at address nn and stores it in register B.
LDC nn 03 nn
Load Register C
Reads the data at address nn and stores it in register C.
LDA [A] 04
Load Register A
Reads the data located at the address in register A and stores it in register A.
LDB [A] 05
Load Register B
Reads the data located at the address in register A and stores it in register B.
LDC [A] 06
Load Register C
Reads the data located at the address in register A and stores it in register C.
STA nn 11 nn
Store Register A
Stores the value of register A into address nn.
STB nn 12 nn
Store Register B
Stores the value of register B into address nn.
STC nn 13 nn
Store Register C
Stores the value of register C into address nn.
STA [A] 14
Store Register A
Stores the value of register A into the memory address in register A.
STB [A] 15
Store Register B
Stores the value of register B into the memory address in register A.
STC [A] 16
Store Register C
Stores the value of register C into the memory address in register A.
INC 20
Increment
Add 1 to register A.
DEC 21
Decrement
Subtract 1 from register A.
CON nn 22 nn
Constant
Sets register A to the literal value nn.
JP nn 30 nn
Jump
Moves the Program Counter to address nn.
JZ nn 31 nn
Jump If Zero
If register A is 0, moves the Program Counter to address nn. Otherwise does nothing.
JNZ nn 32 nn
Jump If Not Zero
If register A is not 0, moves the Program Counter to address nn. Otherwise does nothing.
SWB 40
Swap Register B
Swaps the contents of registers A and B.
SWC 41
Swap Register C
Swaps the contents of registers A and C.
HCF FF
Halt And Catch Fire
Lights the CPU on fire, which terminates your program. Due to technological restrictions, the CoolCPU simulator cannot accurately simulate this instruction, and will only halt the CPU.

Sample program 1

Let's say you want to print out "cool!". This means you'd have to write each character in that string to the output register, which we know from the "Description" section above is 0xF1.

By looking up the characters in an ASCII table, you can figure out what values to write. The instructions to do this might look something like:

; print out c
CON 0x63
STA 0xF1

; print out o
CON 0x6F
STA 0xF1

; print out o
CON 0x6F
STA 0xF1

; print out l
CON 0x6C
STA 0xF1

; print out !
CON 0x21
STA 0xF1

; stop CPU
HCF

We use the CON instruction to load a value into register A, and then use the STA instruction to store that value into the output register. Finally, we use HCF to set the CPU on fire, which ends the program.

Now, using the table above, we can determine the hexadecimal values that correspond to these instructions:

22 63
11 F1
22 6F
11 F1
22 6F
11 F1
22 6C
11 F1
22 21
11 F1
FF

(they're spaced out on multiple lines for clarity—the spacing has no effect on their location)

And that's our program! You can try it in the simulator above.

Sample program 2

Let's say you now want to repeat the earlier code five times. You could just write the whole thing out over and over; however, it's better to do this in a loop. That might look something like this:

	CON 5
loop:
	SWB

	; print out c
	CON 0x63
	STA 0xF1

	; print out o
	CON 0x6F
	STA 0xF1

	; print out o
	CON 0x6F
	STA 0xF1

	; print out l
	CON 0x6C
	STA 0xF1

	; print out !
	CON 0x21
	STA 0xF1

	SWB

	DEC
	JNZ loop

	; stop CPU
	HCF

The main thing to notice here is that we're using the A register to track how many iterations are left in the loop. At the beginning of the program, the CON 5 sets it to 5. Then, at the end of each loop iteration, the DEC instruction subtracts 1, and the JNZ continues the loop—unless A is 0, in which case HCF is run.

However, you might have noticed an issue with this: we're using the A register for both the loop count and the character values! That's what the SWB instruction is for: it swaps registers A and B. We swap at the start of the loop to save the loop count, and then do a swap at the end to restore the count so that we can check it. Since most operations occur on register A, you'll find the swap instructions to be very helpful.

Like before, we can use the instruction table to find the hexadecimal representation of these instructions:

22 05
40
22 63
11 F1
22 6F
11 F1
22 6F
11 F1
22 6C
11 F1
22 21
11 F1
40
21
32 02
FF

Notice how we had to calculate where the loop label is in the code. Based on the size of the instruction before it, and knowing that the first byte is address 0x0, we can determine that loop is 0x02. So, JNZ loop becomes JNZ 0x02, which becomes 32 02.