DataHoarder
8b063bde61
All checks were successful
continuous-integration/drone/push Build is passing
158 lines
3.7 KiB
Go
158 lines
3.7 KiB
Go
package randomx
|
|
|
|
import "git.gammaspectra.live/P2Pool/go-randomx/v3/internal/blake2"
|
|
|
|
// SuperScalarInstruction superscalar program is built with superscalar instructions
|
|
type SuperScalarInstruction struct {
|
|
Opcode byte
|
|
Dst uint8
|
|
Src uint8
|
|
Mod byte
|
|
Imm32 uint32
|
|
Imm64 uint64
|
|
OpGroup int
|
|
OpGroupPar int
|
|
GroupParIsSource int
|
|
ins *Instruction
|
|
CanReuse bool
|
|
}
|
|
|
|
func (sins *SuperScalarInstruction) FixSrcReg() {
|
|
if sins.Src == 0xff {
|
|
sins.Src = sins.Dst
|
|
}
|
|
|
|
}
|
|
func (sins *SuperScalarInstruction) Reset() {
|
|
sins.Opcode = 99
|
|
sins.Src = 0xff
|
|
sins.Dst = 0xff
|
|
sins.CanReuse = false
|
|
sins.GroupParIsSource = 0
|
|
}
|
|
|
|
func createSuperScalarInstruction(sins *SuperScalarInstruction, ins *Instruction, gen *blake2.Generator) {
|
|
sins.Reset()
|
|
sins.ins = ins
|
|
sins.OpGroupPar = -1
|
|
sins.Opcode = ins.Opcode
|
|
|
|
switch ins.Opcode {
|
|
case S_ISUB_R:
|
|
sins.Mod = 0
|
|
sins.Imm32 = 0
|
|
sins.OpGroup = S_IADD_RS
|
|
sins.GroupParIsSource = 1
|
|
case S_IXOR_R:
|
|
sins.Mod = 0
|
|
sins.Imm32 = 0
|
|
sins.OpGroup = S_IXOR_R
|
|
sins.GroupParIsSource = 1
|
|
case S_IADD_RS:
|
|
sins.Mod = gen.GetByte()
|
|
// set modshift on Imm32
|
|
sins.Imm32 = uint32((sins.Mod >> 2) % 4) // bits 2-3
|
|
//sins.Imm32 = 0
|
|
sins.OpGroup = S_IADD_RS
|
|
sins.GroupParIsSource = 1
|
|
case S_IMUL_R:
|
|
sins.Mod = 0
|
|
sins.Imm32 = 0
|
|
sins.OpGroup = S_IMUL_R
|
|
sins.GroupParIsSource = 1
|
|
case S_IROR_C:
|
|
sins.Mod = 0
|
|
|
|
for sins.Imm32 = 0; sins.Imm32 == 0; {
|
|
sins.Imm32 = uint32(gen.GetByte() & 63)
|
|
}
|
|
|
|
sins.OpGroup = S_IROR_C
|
|
sins.OpGroupPar = -1
|
|
case S_IADD_C7, S_IADD_C8, S_IADD_C9:
|
|
sins.Mod = 0
|
|
sins.Imm32 = gen.GetUint32()
|
|
sins.OpGroup = S_IADD_C7
|
|
sins.OpGroupPar = -1
|
|
case S_IXOR_C7, S_IXOR_C8, S_IXOR_C9:
|
|
sins.Mod = 0
|
|
sins.Imm32 = gen.GetUint32()
|
|
sins.OpGroup = S_IXOR_C7
|
|
sins.OpGroupPar = -1
|
|
|
|
case S_IMULH_R:
|
|
sins.CanReuse = true
|
|
sins.Mod = 0
|
|
sins.Imm32 = 0
|
|
sins.OpGroup = S_IMULH_R
|
|
sins.OpGroupPar = int(gen.GetUint32())
|
|
case S_ISMULH_R:
|
|
sins.CanReuse = true
|
|
sins.Mod = 0
|
|
sins.Imm32 = 0
|
|
sins.OpGroup = S_ISMULH_R
|
|
sins.OpGroupPar = int(gen.GetUint32())
|
|
|
|
case S_IMUL_RCP:
|
|
|
|
sins.Mod = 0
|
|
for {
|
|
sins.Imm32 = gen.GetUint32()
|
|
if (sins.Imm32&sins.Imm32 - 1) != 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
sins.Imm64 = reciprocal(sins.Imm32)
|
|
|
|
sins.OpGroup = S_IMUL_RCP
|
|
|
|
default:
|
|
panic("should not occur")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var slot3 = []*Instruction{&ISUB_R, &IXOR_R} // 3 length instruction will be filled with these
|
|
var slot3L = []*Instruction{&ISUB_R, &IXOR_R, &IMULH_R, &ISMULH_R}
|
|
|
|
var slot4 = []*Instruction{&IROR_C, &IADD_RS}
|
|
var slot7 = []*Instruction{&IXOR_C7, &IADD_C7}
|
|
var slot8 = []*Instruction{&IXOR_C8, &IADD_C8}
|
|
var slot9 = []*Instruction{&IXOR_C9, &IADD_C9}
|
|
var slot10 = []*Instruction{&IMUL_RCP}
|
|
|
|
func CreateSuperScalarInstruction(sins *SuperScalarInstruction, gen *blake2.Generator, instructionLen int, decoderType DecoderType, last, first bool) {
|
|
|
|
switch instructionLen {
|
|
case 3:
|
|
if last {
|
|
createSuperScalarInstruction(sins, slot3L[gen.GetByte()&3], gen)
|
|
} else {
|
|
createSuperScalarInstruction(sins, slot3[gen.GetByte()&1], gen)
|
|
}
|
|
case 4:
|
|
//if this is the 4-4-4-4 buffer, issue multiplications as the first 3 instructions
|
|
if decoderType == Decoder4444 && !last {
|
|
createSuperScalarInstruction(sins, &IMUL_R, gen)
|
|
} else {
|
|
createSuperScalarInstruction(sins, slot4[gen.GetByte()&1], gen)
|
|
}
|
|
case 7:
|
|
createSuperScalarInstruction(sins, slot7[gen.GetByte()&1], gen)
|
|
|
|
case 8:
|
|
createSuperScalarInstruction(sins, slot8[gen.GetByte()&1], gen)
|
|
|
|
case 9:
|
|
createSuperScalarInstruction(sins, slot9[gen.GetByte()&1], gen)
|
|
case 10:
|
|
createSuperScalarInstruction(sins, slot10[0], gen)
|
|
|
|
default:
|
|
panic("should not be possible")
|
|
}
|
|
|
|
}
|