C15 is a 100 MHz processor based on a fictional architecture brought to life thanks to an FPGA. The processor contains three registers, all 32 bits wide: register A, register B, and register R, used for arithmetic results. There are four flags: zero, greater than, less than, and out of time (indicating the exhaustion of the execution time).
Press "Run" to assemble/compile, upload, and execute the machine code. You can program the processor by either using C15 assembly or the programming language C.
To use the C compiler, create a new tab with the extension ".c".
The compiler has support for struct, integer, unsigned integer, and float types.
There is no support for recursion due to the limited stack space in the processor.
There are a few intrinsics provided:
Memory below all instructions is prefixed with the "a" character followed by the index. Numbers with the "0x" prefix are treated as hexadecimal, numbers ending with "f" are treated as single-precision floating point, and everything else is treated as decimal. Use the "#" symbol to begin a comment.
Listed below is a subset of the C15 instruction set:
Halts the execution of the processor.
Copies the value in register R to the given address.
Copies the value in register A to the given address.
Copies the value in register B to the given address.
Writes the value to the address.
Loads the value located at the given address into the register A.
Loads the value located at the given address into the register B.
Sums the values from register A and B and stores the result in register R. (A + B)
This will set the flag Z to 1 if the result is zero. (which may occur because of an arithmetic overflow)Subtracts the values from register A and B and stores the result in register R. (A - B)
This will set the flag Z to 1 if the result is zero. (which may occur because of an arithmetic underflow)Multiplies the values from register A and B and stores the result in register R. (A × B)
This will set the flag Z to 1 if the result is zero.Divides the values from register A and B and stores the quotient in register R. (A ÷ B)
This will set the flag Z to 1 if the result is zero.Divides the values from register A and B and stores the remainder in register R. (A % B)
Increments the value of register A and stores the result back into register A. (A++)
Decrements the value of register A and stores the result back into register A. (A--)
Generates a 32-bit random number and places the random number into register A.
Jumps to the given address (sets the program counter to the given address).
Jumps to the given address if the flag Z is set to 1.
This instruction combined with CMP is equivalent to A == B.Jumps to the given address if the flag Z is set to 0.
This instruction combined with CMP is equivalent to A != B.Jumps to the given address if the flag Less Than is set to 1.
This instruction combined with CMP is equivalent to A < B.Jumps to the given address if the flag Greater Than is set to 0.
This instruction combined with CMP is equivalent to A <= B.Jumps to the given address if the flag Greater Than is set to 1.
This instruction combined with CMP is equivalent to A > B.Jumps to the given address if the flag Less Than is set to 0.
This instruction combined with CMP is equivalent to A >= B.Compares the values in registers A and B and sets the flags accordingly:
Pushes the next address after the current address to the stack and jumps to the given address.
This acts like a JMP instruction but has the ability to return back to its previous address similar to how a subroutine works.Pops the address on top of the stack and jumps to it.
This operation will jump back to the address last called with the CALL instruction.Copies the value from the source address to the destination address.
Swaps the values of register A and B.
Performs single-precision floating-point addition between the values in registers A and B,
then places the result in register R.
A + B
Performs single-precision floating-point multiplication between the values in registers A and B,
then places the result in register R.
A * B
Performs single-precision floating-point division between the values in registers A and B,
then places the result in register R.
A / B
Converts a single-precision floating-point in register A to an integer and places the result in register R.
(int)A
Converts an integer in register A to a single-precision floating-point and places the result in register R.
(float)A
Places the number of clock cycles since execution began in register R.
Pushes the value at the given address to the stack. (maximum 32 elements)
Pushes the value at the top of the stack and places it at the given address.
Compares the values from register A and B and places a 1 if A < B, otherwise 0 in register R.
Compares the values from register A and B and places a 1 if A > B, otherwise 0 in register R.
Compares the values from register A and B and places a 1 if A <= B, otherwise 0 in register R.
Compares the values from register A and B and places a 1 if A >= B, otherwise 0 in register R.
Compares the values from register A and B and places a 1 if A == B, otherwise 0 in register R.
Compares the values from register A and B and places a 1 if A != B, otherwise 0 in register R.
Jumps to the given address if the value in register R is non-zero.
Jumps to the given address if the value in register R is zero.
Places a 1 in register R if the value in register A is zero.
Places a 0 in register R if the value in register A is non-zero.
This instruction is equivalent to !A.
Performs quick inline addition, compared to the ADD instruction, quick addition allows for single cycle addition
by placing the operands A and B into the 32-bit width of the instruction. The result after the operation is placed into register R.
The assembler will interpret addresses by value, that is, only the numeric value of the address will be placed into an operand not the contents at the given address.
Operands A and B are restricted to 12-bit values, specifically, only values ranging from 0 and up to and including 4095.