RandomWOW/doc/isa.md
tevador 2756bcdcfe Added magic division to JIT compiler
New B operand selection rules
2019-01-11 16:53:52 +01:00

5.9 KiB

RandomX instruction encoding

The instruction set was designed in such way that any random 16-byte word is a valid instruction and any sequence of valid instructions is a valid program. There are no syntax rules.

The encoding of each 128-bit instruction word is following:

Imgur

opcode

There are 256 opcodes, which are distributed between 3 groups of instructions. There are 31 distinct operations (each operation can be encoded using multiple opcodes - for example opcodes 0x00 to 0x0d correspond to integer addition).

Table 1: Instruction groups

group # operations # opcodes
integer (IA) 22 144 56.3%
floating point (FP) 5 76 29.7%
control (CL) 4 36 14.0%
31 256 100%

Full description of all instructions: isa-ops.md.

A.LOC

Table 2: A.LOC encoding

bits description
0-1 A.LOC.W flag
2-5 Reserved
6-7 A.LOC.X flag

The A.LOC.W flag determines the address width when reading operand A from the scratchpad:

Table 3: Operand A read address width

A.LOC.W address width (W)
0 15 bits (256 KiB)
1-3 11 bits (16 KiB)

If the A.LOC.W flag is zero, the address space covers the whole 256 KiB scratchpad. Otherwise, just the first 16 KiB of the scratchpad are addressed.

If the A.LOC.X flag is zero, the instruction mixes the scratchpad read address into the mx register using XOR. This mixing happens before the address is truncated to W bits (see pseudocode below).

A.REG

Table 4: A.REG encoding

bits description
0-2 A.REG.R flag
3-7 Reserved

The A.REG.R flag encodes "readAddressRegister", which is an integer register r0-r7 to be used for scratchpad read address generation. Read address is generated as follows (pseudocode):

readAddressRegister = IntegerRegister(A.REG.R)
readAddressRegister = readAddressRegister XOR SignExtend(A.mask32)
readAddress = readAddressRegister[31:0]
# dataset is read if the ic register is divisible by 64
IF ic mod 64 == 0:
  DatasetRead(readAddress)
# optional mixing into the mx register
IF A.LOC.X == 0:
  mx = mx XOR readAddress
# truncate to W bits
W = GetAddressWidth(A.LOC.W)
readAddress = readAddress[W-1:0]

Note that the value of the read address register is modified during address generation.

B.LOC

Table 5: B.LOC encoding

bits description
0-1 B.LOC.L flag
0-2 B.LOC.C flag
3-7 Reserved

The B.LOC.L flag determines the B operand. It can be either a register or immediate value.

Table 6: Operand B

B.LOC.L IA/DIV IA/SHIFT IA/MATH FP CL
0 register imm8 imm32 register register
1 imm32 register register register register
2 imm32 imm8 register register register
3 imm32 register register register register

Integer instructions are split into 3 classes: integer division (IA/DIV), shift and rotate (IA/SHIFT) and other (IA/MATH). Floating point (FP) and control (CL) instructions always use a register operand.

Register to be used as operand B is encoded in the B.REG.R flag (see below).

The B.LOC.C flag determines the condition for the JUMP and CALL instructions. The flag partially overlaps with the B.LOC.L flag.

B.REG

Table 7: B.REG encoding

bits description
0-2 B.REG.R flag
3-7 Reserved

Register encoded by the B.REG.R depends on the instruction group:

Table 8: Register operands by group

group registers
IA r0-r7
FP f0-f7
CL r0-r7

C.LOC

Table 9: C.LOC encoding

bits description
0-1 C.LOC.W flag
2 C.LOC.R flag
3-6 Reserved
7 C.LOC.H flag

The C.LOC.W flag determines the address width when writing operand C to the scratchpad:

Table 10: Operand C write address width

C.LOC.W address width (W)
0 15 bits (256 KiB)
1-3 11 bits (16 KiB)

If the C.LOC.W flag is zero, the address space covers the whole 256 KiB scratchpad. Otherwise, just the first 16 KiB of the scratchpad are addressed.

The C.LOC.R determines the destination where operand C is written:

Table 11: Operand C destination

C.LOC.R groups IA, CL group FP
0 scratchpad register
1 register register + scratchpad

Integer and control instructions (groups IA and CL) write either to the scratchpad or to a register. Floating point instructions always write to a register and can also write to the scratchpad. In that case, flag C.LOC.H determines if the low or high half of the register is written:

Table 12: Floating point register write

C.LOC.H write bits
0 0-63
1 64-127

C.REG

Table 13: C.REG encoding

bits description
0-2 C.REG.R flag
3-7 Reserved

The destination register encoded in the C.REG.R flag encodes both the write address register (if writing to the scratchpad) and the destination register (if writing to a register). The destination register depends on the instruction group (see Table 8). Write address is always generated from an integer register:

writeAddressRegister = IntegerRegister(C.REG.R)
writeAddress = writeAddressRegister[31:0] XOR C.mask32
# truncate to W bits
W = GetAddressWidth(C.LOC.W)
writeAddress = writeAddress [W-1:0]

imm8

imm8 is an 8-bit immediate value that is used as the B operand by IA/SHIFT instructions (see Table 6). Additionally, it's used by some control instructions.

A.mask32

A.mask32 is a 32-bit address mask that is used to calculate the read address for the A operand. It's sign-extended to 64 bits before use.

imm32

imm32 is a 32-bit immediate value which is used for integer instructions from groups IA/DIV and IA/OTHER (see Table 6). The immediate value is sign-extended for instructions that expect 64-bit operands.

C.mask32

C.mask32 is a 32-bit address mask that is used to calculate the write address for the C operand. C.mask32 is equal to imm32.