User:Virtlink/My dream CPU/ISA
Registers
The CPU has the following registers:
Value | 64-bit GP | 256-bit SIMD |
---|---|---|
0 | R0 | V0 |
1 | R1 | V1 |
2 | R2 | V2 |
3 | R3 | V3 |
4 | R4 | V4 |
5 | R5 | V5 |
6 | R6 | V6 |
7 | R7 | V7 |
8 | R8 | V8 |
9 | R9 | V9 |
10 | R10 | V10 |
11 | R11 | V11 |
12 | R12 | V12 |
13 | R13 | V13 |
14 | R14 | V14 |
15 | R15 | V15 |
Value | 64-bit GP | 256-bit SIMD |
---|---|---|
16 | R16 | V16 |
17 | R17 | V17 |
18 | R18 | V18 |
19 | R19 | V19 |
20 | R20 | V20 |
21 | R21 | V21 |
22 | R22 | V22 |
23 | R23 | V23 |
24 | R24 | V24 |
25 | R25 | V25 |
26 | R26 | V26 |
27 | R27 | V27 |
28 | R28 | V28 |
29 | R29 | V29 |
30 | R30 | V30 |
31 | PC | V31 |
Instruction encoding
Every instruction consists of an opcode, an operand specifier and a number of operands. The source operands (if any) come before the destination operands (if any), in the order specified in the opcode specification. An opcode represents an operation, and the operand size and operands of the operation are encoded explicitly in the instruction. This allows tools to determine the instruction boundaries without knowing the instruction. The CPU can determine the length of the instruction from the opcode and operand specifier alone.
Opcode
Opcodes may be encoded in various sizes. Compilers are encouraged to choose the smallest opcode size that fits the opcode, but this is not required.
7-bit opcode
7 0 +---+---+---+---+---+---+---+---+ | 0 | OPCODE | +---+---+---+---+---+---+---+---+
This 7-bit opcode has all explicit operands set to none, and uses the default operand size, and assumes the values are unsigned. It is used for instructions that have no (explicit) operands and no need to set the operand size to anything other than 64-bit.
An example of a single byte instruction is the NOP instruction, with opcode 0.
11, 18 and 25-bit opcodes
These opcodes are more advanced. The CPU can decode the operand size from the opcode and expects an operand specifier to follow the opcode. Note that the opcode encoding allows for future CPUs to support opcodes values larger than 25-bit.
15 14 3 2 0 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 1 | 0 | OPCODE | US| OS | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
23 22 21 3 2 0 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 1 | 1 | 0 | OPCODE | US| OS | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
31 30 29 28 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 1 | 1 | 1 | 0 | OPCODE .. +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 3 2 0 +---+---+---+---+---+---+---+---+ .. | US| OS | +---+---+---+---+---+---+---+---+
Field | Size | Description |
---|---|---|
US | 1-bit | Specifies the interpretation of the values: 0: Unsigned 1: Signed |
OS | 2-bit | Specifies the operand size ((1 << (6 - OS))-bit): 0: 64-bit 1: 32-bit 2: 16-bit 3: 8-bit |
Operand specifier
The operand specifier can specify from one up to six operands. The encoding may seem arbitrary, but is chosen in such way that the operands are encoded as efficiently as possible. Note that the operand specifier encoding allows for future CPUs to support instructions with more than six operands.
7 6 5 0 +---+---+---+---+---+---+---+---+ | 1 | 1 | 0 | OP1 | +---+---+---+---+---+---+---+---+
15 10 5 0 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 0 | OP1 | OP2 | OP3 | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
23 22 21 20 15 10 5 0 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 1 | 1 | 1 | 0 | OP1 | OP2 | OP3 | OP4 | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
31 30 25 20 15 10 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 1 | 0 | OP1 | OP2 | OP3 | OP4 | OP5 .. +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 5 0 +---+---+---+---+---+---+---+---+ .. OP5 | OP6 | +---+---+---+---+---+---+---+---+
Each operand specification has the following layout:
4 0 +---+---+---+---+---+ | M | I | B | S | +---+---+---+---+---+
Field | Size | Description |
---|---|---|
M | 1-bit | 0: Direct 1: Indirect |
I | 1-bit | 0: No index 1: Index register * scale |
B | 1-bit | 0: No base 1: Base register |
S | 2-bit | 0: No immediate/offset/displacement 1: 16-bit immediate/offset/displacement 2: 32-bit immediate/offset/displacement 3: 64-bit immediate/offset/displacement |
Some examples:
To encode | M | I | B | S |
---|---|---|---|---|
nothing or literal 0 | 0 | 0 | 0 | 0 |
reg | 0 | 0 | 1 | 0 |
[reg] | 1 | 0 | 1 | 0 |
[offset32] | 1 | 0 | 0 | 2 |
[base+index*scale+disp16] | 1 | 1 | 1 | 1 |
imm64 | 0 | 0 | 0 | 3 |
reg+imm32 | 0 | 0 | 1 | 2 |
base+index*scale+imm16 (like LEA) | 0 | 1 | 1 | 1 |
[0] (null reference) | 1 | 0 | 0 | 0 |
Note however that not all possible operand types are allowed for all operands. For example, destination operands must either be indirect (M=1) or be only a register (B=1, I=0, S=0). When an operand is not specified or none (M=I=B=S=0) then the behavior depends on the instruction. Some instructions missing a destination operand use a source operand also as destination, others treat the operand as the literal value 0, offset 0 or as register R0. Instructions that have not enough or incorrect operands throw an exception.
Operand encoding
Immediates, displacements and offsets
Immediate, displacement and offset values are encoded in little-endian order with the number of bits specified in the operand specifier.
When the immediate value is less than the operand size, it is sign-extended or zero-extended depending on the instruction. When the immediate value is greater than the operand size, excess bits are trimmed off.
When the displacement value is less than the address size (64-bit), it is sign-extended.
When the offset value is less than the address size (64-bit), it is zero-extended.
Register, base register
A register operand or base register (both indirect and direct) is encoded as:
7 6 5 0 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | REG | +---+---+---+---+---+---+---+---+
This encoding may seem wasteful, but instruction size is not such a big issue with modern CPUs. This encoding of a register is consistent, simple and future CPUs may extend the syntax to support more than 32 registers.
The PC (program counter) register has value 31 and may be used everywhere a register is expected. However, its use is not allowed as a destination operand, and in some addressing modes the use of PC is meaningless (e.g. using PC as an index register with a scale other than 1).
Index * scale
An index register with a scaling factor is encoded as:
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | INDEX | | 0 | 0 | 0 | 0 | 0 | SCALE | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
The scaling factor is not encoded with the index register to keep register encoding consistent and to allow for future register extensions. The scaling factor is a power of two (1 << SCALE).
Value SCALE | Scaling factor |
---|---|
b000 | 1 |
b001 | 2 |
b010 | 4 |
b011 | 8 |
b100 | 16 |
b101 | 32 |
b110 | 64 |
b111 | 128 |
Instruction sizes
0-7 bit operand | 8-11 bit operand | 12-18 bit operand | 19-25 bit operand | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Min | Max | Ineff. | Min | Max | Ineff. | Min | Max | Ineff. | Min | Max | Ineff. | |
0 operands | 1 | 1 | 6 | 3 | 3 | 6 | 4 | 4 | 7 | 5 | 5 | 8 |
1 operand | 4 | 14 | 17 | 4 | 14 | 17 | 5 | 15 | 18 | 6 | 16 | 19 |
2 operands | 6 | 26 | 28 | 6 | 26 | 28 | 7 | 27 | 29 | 8 | 28 | 30 |
3 operands | 7 | 37 | 39 | 7 | 37 | 39 | 8 | 38 | 40 | 9 | 39 | 41 |
4 operands | 9 | 47 | 48 | 9 | 47 | 48 | 10 | 48 | 49 | 11 | 49 | 50 |
5 operands | 11 | 61 | 61 | 11 | 61 | 61 | 12 | 62 | 62 | 13 | 63 | 63 |
6 operands | 12 | 72 | 72 | 12 | 72 | 72 | 13 | 73 | 73 | 14 | 74 | 74 |
Min: minimum size with smallest operands
Max: maximum size with largest operands
Ineff: maximum size with largest operands and unnecessarily inefficient encoding