CPUSim64 Instruction Set

The CPUSim64 instruction set has 32 instructions that operate on the 29 general purpose integer registers, 32 floating point registers, stack frame pointer, stack pointer, program counter and status register. Each instruction can have multiple numbers and types of operands as described in this document.

In the Operation columns below the description of the operation will use the operands in the same order that they appear in the Operands column. The <- or -> symbols show the direction of data movement. For all but the STORE instructions the direction is into the first argument. If a register is listed such as A it means that the value in the register is used. If a register is listed in square brackets such as [A] it means that the value of A is taken as an address and the contents in that address are used. This is known as a memory reference. You will only see this in the Register Load/Store Instructions.

Because some instructions operate on integer registers or floating point registers and because some instructions support integer literals of differing sizes, the following table lists the symbols used in the Operands and Operation columns

Register Reference Symbols
SymbolDescription
RInteger in r0-r28
AAddress in r0-r28, SF, SP or PC
FFloat in f0-f31
XR or F
YA or F
OR or C
QA, F or C
SFStack Frame
SPStack Pointer
PCProgram Counter
SRStatus Register (PZSO)
Integer Literal Symbols
SymbolDescription
Z4-bit condition code used for JUMP
or CALL or port number 0-255 for IN and OUT
B8-bit signed integer
C012-bit signed integer
C156-bit signed integer
C242-bit signed integer
C328-bit signed integer
K64-bit signed integer
E64-bit IEEE float
P64-bit Absolute unsigned address
Condition Codes
SymbolValueDescriptionOther Interpretation
u0UnconditionalAny result
z or eq1ZeroCompare equivalent
nz or ne2Not zeroCompare not equivalent
n or lt3NegativeCompare less than
p or gt4PositiveCompare greater than
nn or ge5Not negativeCompare greater or equal
np or le6Not positiveCompare less or equal
o or inf7OverflowInfinite
no or ninf8No overflowFinite
pe9Parity evenNone
po10Parity oddNone

No-op/Debug

Does nothing but take up a CPU cycle. If debugging is turn on for the virtual CPU, then debugging information is printed.

OpcodePneumonicOperandsOperation
0NOPNDoes nothing
0DEBUGY
YY
Prints contents of 1-4 registers if debugging is enabled.
0DEBUGAC
CC
Dump memory from starting address for number of words (walk heap if operand 2 is neg)

Register Load/Store Instructions

Clear

Used to move zero into registers.

OpcodePneumonicOperandsOperation
1CLEARN
X
XX
XXX
XXXX
Clear all registers or 1-4 specific registers.

Move (Register-to-Register)

MOVE is used to move data between registers. Conditional version moves the third operand into the destination register if the condition is met otherwise it moves the fourth operand.

OpcodePneumonicOperandsOperation
2MOVEYY
YC
AAR
AAC
ACA
ZYQQ
Y1 <- Y2
Y <- C
A1 <- A2 + R
A1 <- A2 + C
A1 <- C + A2
if Z, Y <- Q1 else Y <- Q2

Load (Memory-to-Register)

LOAD is used to move data from memory into registers.

OpcodePneumonicOperandsOperation
3LOADYC
YA
YAC
YCA
YCC
YAR
Y <- [C]
Y <- [A]
Y <- [A + C]
Y <- [C + A]
Y <- [C + C]
Y <- [A + R]

Store (Register-to-Memory)

STORE is used to move data from registers into memory.

OpcodePneumonicOperandsOperation
4STOREQC
QA
QAC
QCA
QCC
QAR
Q -> [C]
Q -> [A]
Q -> [A + C]
Q -> [C + A]
Q -> [C + C]
Q -> [A + R]

Pop

This instruction moves the SP register up by one and then pulls the value now pointed to by the SP.

OpcodePneumonicOperandsOperation
5POPN
Y
SP = SP + 1; discard <- [SP]
SP = SP + 1; Y <- [SP]

Push

This instruction pushes the operand onto the stack at the current value of the SP. It then moves the SP down by one.

OpcodePneumonicOperandsOperation
6PUSHY
C
Y -> [SP]; SP = SP - 1
C -> [SP]; SP = SP - 1

Control Instructions

Jump

The JUMP instruction branches control to the address specified by the operands. The conditional forms only branch if the SR condition specified is true.

OpcodePneumonicOperandsOperation
7JUMPA
C
AC
AR
ZA
ZC
ZAC
ZCA
ZCC
ZAR
PC <- A
PC <- C
PC <- A + C
PC <- A + R
if Z, PC <- A
if Z, PC <- C
if Z, PC <- A + C
if Z, PC <- C + A
if Z, PC <- C + C
if Z, PC <- A + R

Call

Before the operation listed in the table, all CALL instructions first perform the following actions: Push SP + 1 (Return Address), Push SF (Old Stack Frame) then set SF to SP.

PC + 1 -> [SP]; SP = SP - 1
SF -> [SP]; SP = SP - 1
SF <- SP
OpcodePneumonicOperandsOperation
8CALLA
C
AC
AR
ZA
ZC
ZAC
ZCA
ZCC
ZAR
PC <- A
PC <- C
PC <- A + C
PC <- A + R
if Z, PC <- A
if Z, PC <- C
if Z, PC <- A + C
if Z, PC <- C + A
if Z, PC <- C + C
if Z, PC <- A + R

Return

Returns from a CALL. RETURN resets the SP back to the SF which is where the SP was when the CALL started. Then pops the SF off the stack. Then pops the return address off the stack.

OpcodePneumonicOperandsOperation
9RETURNNSP <- SF
SP = SP + 1; SF <- [SP]
SP = SP + 1; PC <- [SP]

Interrupt

The INTERRUPT instruction invokes the software interrupt specified by its integer argument. This effectively calls the operating system function associated with the interrupt and then returns.

OpcodePneumonicOperandsOperation
10INTERRUPTR
C
ZR
ZC
See List of Software Interrupts

Stop

STOP halts execution of the virtual CPU.

OpcodePneumonicOperandsOperation
11STOPN

Arithmetic Instructions

Negate

OpcodePneumonicOperandsOperation
12NEGXX <- -X

Addition

OpcodePneumonicOperandsOperation
13ADDAR
FX
YC
AAR
FFX
AAC
FFC
ACA
FCF
A1 <- A1 + R
F1 <- F1 + X
Y1 <- Y1 + C
A1 <- A2 + R
F1 <- F2 + X
A1 <- A2 + C
F1 <- F2 + C
A1 <- C + A2
F1 <- C + F2

Subtraction

OpcodePneumonicOperandsOperation
14SUBAR
FX
YC
AAR
FFX
AAC
FFC
ACA
FCF
A1 <- A1 - R
F1 <- F1 - X
Y1 <- Y1 - C
A1 <- A2 - R
F1 <- F2 - X
A1 <- A2 - C
F1 <- F2 - C
A1 <- C - A2
F1 <- C - F2

Multiplication

OpcodePneumonicOperandsOperation
15MULTRR
FX
XC
RRR
FFX
RRC
FFC
RCR
FCF
R1 <- R1 * R2
F1 <- F1 * X
X1 <- X1 * C
R1 <- R2 * R3
F1 <- F2 * X
R1 <- R2 * C
F1 <- F2 * C
R1 <- C * R2
F1 <- C * F2

Division

OpcodePneumonicOperandsOperation
16DIVRR
FX
XC
RRR
FFX
RRC
FFC
RCR
FCF
RRRR
RRRC
R1 <- R1 / R
F1 <- F1 / X
X1 <- X1 / C
R1 <- R2 / R
F1 <- F2 / X
R1 <- R2 / C
F1 <- F2 / C
R1 <- C / R2
F1 <- C / F2
R1 <- R3 / R4; R2 <- R3 % R4
R1 <- R3 / C; R2 <- R3 % C
16RECIPFF <- 1 / F

Logical and Conditional Instructions

Complement

OpcodePneumonicOperandsOperation
17COMPLRR <- ~R

Bitwise AND

OpcodePneumonicOperandsOperation
18ANDRR
RC
RRR
RRC
R1 <- R1 & R2
R1 <- R1 & C
R1 <- R2 & R3
R1 <- R2 & C

Bitwise OR

OpcodePneumonicOperandsOperation
19ORRR
RC
RRR
RRC
R1 <- R1 | R2
R1 <- R1 | C
R1 <- R2 | R3
R1 <- R2 | C

Bitwise XOR

OpcodePneumonicOperandsOperation
20XORRR
RC
RRR
RRC
R1 <- R1 ^ R2
R1 <- R1 ^ C
R1 <- R2 ^ R3
R1 <- R2 ^ C

Test

OpcodePneumonicOperandsOperation
21TESTXSets SR based on X

Compare

OpcodePneumonicOperandsOperation
22CMPAA
AC
FF
Sets SR based on A1 - A2
Sets SR based on A - C
Sets SR based on F1 - F2

Shift Instructions

Logical & Arithmetic Left Shift

Shifts the bits in the integer register to the left. Zero bit(s) is always shifted in on the right. These can be used for either logical or arithmetic left shift. Arithmetic left shift is equivalent to multiplying by powers of 2, i.e x << 1 is equivalent to x * 2, x << 2 is equivalent to x * 4, x << 3 is equivalent to x * 8, etc.

OpcodePneumonicOperandsOperation
23LSHIFTRR
RC
RRR
RRC
R1 <- R1 << R2
R1 <- R1 << C
R1 <- R2 << R3
R1 <- R2 << C

Logical Right Shift

Shifts the bits in the integer register to the right. Zero bit(s) is always shifted in on the left.

OpcodePneumonicOperandsOperation
24RSHIFTRR
RC
RRR
RRC
R1 <- R1 >> R2
R1 <- R1 >> C
R1 <- R2 >> R3
R1 <- R2 >> C

Arithmetic Right Shift

Shifts the bits in the integer register to the right. Sign bit(s) is always shifted in on the right. This results in the equivalent of dividing a signed integer by powers of 2.

OpcodePneumonicOperandsOperation
25ARSHIFTRR
RC
RRR
RRC
R1 <- R1 >> R2
R1 <- R1 >> C
R1 <- R2 >> R3
R1 <- R2 >> C

Left Rotate

Shifts the bits in the integer register to the left. The high bit that is shifted off is shifted in on the right.

OpcodePneumonicOperandsOperation
26LROTATERR
RC
RRR
RRC
R1 <- R1 << R2
R1 <- R1 << C
R1 <- R2 << R3
R1 <- R2 << C

Right Rotate

Shifts the bits in the integer register to the right. The low bit that is shifted off is shifted in on the left.

OpcodePneumonicOperandsOperation
27RROTATERR
RC
RRR
RRC
R1 <- R1 >> R2
R1 <- R1 >> C
R1 <- R2 >> R3
R1 <- R2 >> C

I/O Instructions

Input and output instructions read/write a specified number of bytes to a port which can be a stream to the console if STDIN, STDOUT or STDERR are used for the port or to a file that has been opened.

I/O sizes are specified in <system/io.def> using the following symbols. The CHAR size is unique in that it refers to a UTF-8 sequence that encodes a single codepoint and is therefore a variable number of bytes.

SymbolSize
CHAR 0
BYTE 1
SHORT 2
WORD 4
SINGLE 4
DWORD 8
LONG 8
DOUBLE 8

Input

If the number of bytes requested can not be read, then status register bit for Overflow will be set.

OpcodePneumonicOperandsOperation
28INXZZ
XRR
XRZ
XZR
X <- Read Z1 bytes from port Z2
X <- Read R1 bytes from port R2
X <- Read R bytes from port Z
X <- Read Z bytes from port R

Output

OpcodePneumonicOperandsOperation
29OUTQZZ
QRR
QRZ
QZR
Write Z1 bytes to port Z2 <- Q
Write R1 bytes to port R2 <- Q
Write R bytes to port Z <- Q
Write Z bytes to port R <- Q

Pack

OpcodePneumonicOperandsOperation
30PACKRR
RRRR
Combines two 16-bit values and stores the resulting low 32-bits into R1. Most significant bits are in R1.
R1 <- R1R2
Combines four 8-bit values and stores the resulting low 32-bits into R1. Most significant bits are in R1.
R1 <- R1R2R3R4

Pack64

OpcodePneumonicOperandsOperation
31PACK64RR
RRRR
Combines two 32-bit values and stores the resulting 64-bits into R1. Most significant bits are in R1.
R1 <- R1R2
Combines four 16-bit values and stores the resulting 64-bits into R1. Most significant bits are in R1.
R1 <- R1R2R3R4

Unpack

OpcodePneumonicOperandsOperation
32UNPACKRR
RRRR
Breaks low 32-bits of R1 into two 16-bit values and stores the results across both registers. Most significant bits are in R1.
R1 -> R1R2
Breaks low 32-bits of R1 into four 8-bit values and stores the results across all four registers. Most significant bits are in R1.
R1 -> R1R2R3R4

Unpack64

OpcodePneumonicOperandsOperation
33UNPACK64RR
RRRR
Breaks R1 into two 32-bit values and stores the results across both registers. Most significant bits are in R1.
R1 -> R1R2
Breaks R1 into four 16-bit values and stores the results across all four registers. Most significant bits are in R1.
R1 -> R1R2R3R4

Compare and Set

Performs atomic set of a memory location. Only if the current value of the memory location matches the old value does it then set it to the new value. Sets status register bit Overflow if successful.

OpcodePneumonicOperandsOperation
34CASRRAO
CCAO
RCAO
CRAO
Atomic compare and set
First operand is old value
Second operand is new value
Remaining arguments are address + offset.
Sets overflow flag if successful.

Endian Mode

OpcodePneumonicOperandsOperation
35ENDIANRR
RZ
ZR
ZZ
Sets I/O Port endian mode to big-endian or little-endian
First operand is port [0-255]
Second operand is mode (TRUE for little-endian, FALSE for big-endian)

Protect Registers/Memory

Save Registers

OpcodePneumonicOperandsOperation
36SaveRR
FF
Saves registers R1 through R2 to the stack.
Saves registers F1 through F2 to the stack.

Restore Registers

OpcodePneumonicOperandsOperation
37RestoreRR
FF
Restores registers R1 through R2 from the stack.
Restores registers F1 through F2 from the stack.

Protect Read-Only Memory

OpcodePneumonicOperandsOperation
38ReadOnlyC1Protects memory addressed from SP through C1 as read-only memory. The Assembler will add a ReadOnly instruction at the beginning of your program that protects memory from 0 through __DATA__. Define label __DATA__ at the beginning of your read-write data directives.