Remove zero register from vm bytecode
This commit is contained in:
parent
78b0645034
commit
b72f79a653
190
bytecode.go
Normal file
190
bytecode.go
Normal file
|
@ -0,0 +1,190 @@
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v2/asm"
|
||||
"math"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
type ByteCodeInstruction struct {
|
||||
dst, src byte
|
||||
idst, isrc *uint64
|
||||
fdst, fsrc *[2]float64
|
||||
imm uint64
|
||||
simm int64
|
||||
Opcode ByteCodeInstructionOp
|
||||
target int16
|
||||
shift uint8
|
||||
memMask uint32
|
||||
/*
|
||||
union {
|
||||
int_reg_t* idst;
|
||||
rx_vec_f128* fdst;
|
||||
};
|
||||
union {
|
||||
int_reg_t* isrc;
|
||||
rx_vec_f128* fsrc;
|
||||
};
|
||||
union {
|
||||
uint64_t imm;
|
||||
int64_t simm;
|
||||
};
|
||||
InstructionType type;
|
||||
union {
|
||||
int16_t target;
|
||||
uint16_t shift;
|
||||
};
|
||||
uint32_t memMask;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
func (i ByteCodeInstruction) getScratchpadSrcAddress() uint64 {
|
||||
return (*i.isrc + i.imm) & uint64(i.memMask)
|
||||
}
|
||||
|
||||
func (i ByteCodeInstruction) getScratchpadZeroAddress() uint64 {
|
||||
return i.imm & uint64(i.memMask)
|
||||
}
|
||||
|
||||
func (i ByteCodeInstruction) getScratchpadDestAddress() uint64 {
|
||||
return (*i.idst + i.imm) & uint64(i.memMask)
|
||||
}
|
||||
|
||||
type ByteCode [RANDOMX_PROGRAM_SIZE]ByteCodeInstruction
|
||||
|
||||
func (c *ByteCode) Interpret(vm *VM) {
|
||||
for pc := 0; pc < RANDOMX_PROGRAM_SIZE; pc++ {
|
||||
ibc := c[pc]
|
||||
switch ibc.Opcode {
|
||||
case VM_IADD_RS:
|
||||
*ibc.idst += (*ibc.isrc << ibc.shift) + ibc.imm
|
||||
case VM_IADD_M:
|
||||
*ibc.idst += vm.Load64(ibc.getScratchpadSrcAddress())
|
||||
case VM_IADD_MZ:
|
||||
*ibc.idst += vm.Load64(ibc.getScratchpadZeroAddress())
|
||||
case VM_ISUB_R:
|
||||
*ibc.idst -= *ibc.isrc
|
||||
case VM_ISUB_M:
|
||||
*ibc.idst -= vm.Load64(ibc.getScratchpadSrcAddress())
|
||||
case VM_ISUB_MZ:
|
||||
*ibc.idst -= vm.Load64(ibc.getScratchpadZeroAddress())
|
||||
case VM_IMUL_R:
|
||||
// also handles imul_rcp
|
||||
*ibc.idst *= *ibc.isrc
|
||||
case VM_IMUL_M:
|
||||
*ibc.idst *= vm.Load64(ibc.getScratchpadSrcAddress())
|
||||
case VM_IMUL_MZ:
|
||||
*ibc.idst *= vm.Load64(ibc.getScratchpadZeroAddress())
|
||||
case VM_IMULH_R:
|
||||
*ibc.idst, _ = bits.Mul64(*ibc.idst, *ibc.isrc)
|
||||
case VM_IMULH_M:
|
||||
*ibc.idst, _ = bits.Mul64(*ibc.idst, vm.Load64(ibc.getScratchpadSrcAddress()))
|
||||
case VM_IMULH_MZ:
|
||||
*ibc.idst, _ = bits.Mul64(*ibc.idst, vm.Load64(ibc.getScratchpadZeroAddress()))
|
||||
case VM_ISMULH_R:
|
||||
*ibc.idst = smulh(int64(*ibc.idst), int64(*ibc.isrc))
|
||||
case VM_ISMULH_M:
|
||||
*ibc.idst = smulh(int64(*ibc.idst), int64(vm.Load64(ibc.getScratchpadSrcAddress())))
|
||||
case VM_ISMULH_MZ:
|
||||
*ibc.idst = smulh(int64(*ibc.idst), int64(vm.Load64(ibc.getScratchpadZeroAddress())))
|
||||
case VM_INEG_R:
|
||||
*ibc.idst = (^(*ibc.idst)) + 1 // 2's complement negative
|
||||
case VM_IXOR_R:
|
||||
*ibc.idst ^= *ibc.isrc
|
||||
case VM_IXOR_M:
|
||||
*ibc.idst ^= vm.Load64(ibc.getScratchpadSrcAddress())
|
||||
case VM_IXOR_MZ:
|
||||
*ibc.idst ^= vm.Load64(ibc.getScratchpadZeroAddress())
|
||||
case VM_IROR_R:
|
||||
*ibc.idst = bits.RotateLeft64(*ibc.idst, 0-int(*ibc.isrc&63))
|
||||
case VM_IROL_R:
|
||||
*ibc.idst = bits.RotateLeft64(*ibc.idst, int(*ibc.isrc&63))
|
||||
case VM_ISWAP_R:
|
||||
*ibc.idst, *ibc.isrc = *ibc.isrc, *ibc.idst
|
||||
case VM_FSWAP_R:
|
||||
ibc.fdst[HIGH], ibc.fdst[LOW] = ibc.fdst[LOW], ibc.fdst[HIGH]
|
||||
case VM_FADD_R:
|
||||
ibc.fdst[LOW] += ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] += ibc.fsrc[HIGH]
|
||||
case VM_FADD_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadSrcAddress())
|
||||
ibc.fdst[LOW] += lo
|
||||
ibc.fdst[HIGH] += hi
|
||||
case VM_FSUB_R:
|
||||
ibc.fdst[LOW] -= ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] -= ibc.fsrc[HIGH]
|
||||
case VM_FSUB_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadSrcAddress())
|
||||
ibc.fdst[LOW] -= lo
|
||||
ibc.fdst[HIGH] -= hi
|
||||
case VM_FSCAL_R:
|
||||
// no dependent on rounding modes
|
||||
ibc.fdst[LOW] = math.Float64frombits(math.Float64bits(ibc.fdst[LOW]) ^ 0x80F0000000000000)
|
||||
ibc.fdst[HIGH] = math.Float64frombits(math.Float64bits(ibc.fdst[HIGH]) ^ 0x80F0000000000000)
|
||||
case VM_FMUL_R:
|
||||
ibc.fdst[LOW] *= ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] *= ibc.fsrc[HIGH]
|
||||
case VM_FDIV_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadSrcAddress())
|
||||
ibc.fdst[LOW] /= MaskRegisterExponentMantissa(lo, vm.config.eMask[LOW])
|
||||
ibc.fdst[HIGH] /= MaskRegisterExponentMantissa(hi, vm.config.eMask[HIGH])
|
||||
case VM_FSQRT_R:
|
||||
ibc.fdst[LOW] = math.Sqrt(ibc.fdst[LOW])
|
||||
ibc.fdst[HIGH] = math.Sqrt(ibc.fdst[HIGH])
|
||||
case VM_CBRANCH:
|
||||
*ibc.isrc += ibc.imm
|
||||
if (*ibc.isrc & uint64(ibc.memMask)) == 0 {
|
||||
pc = int(ibc.target)
|
||||
}
|
||||
case VM_CFROUND:
|
||||
tmp := (bits.RotateLeft64(*ibc.isrc, 0-int(ibc.imm))) % 4 // rotate right
|
||||
asm.SetRoundingMode(asm.RoundingMode(tmp))
|
||||
case VM_ISTORE:
|
||||
binary.LittleEndian.PutUint64(vm.ScratchPad[(*ibc.idst+ibc.imm)&uint64(ibc.memMask):], *ibc.isrc)
|
||||
case VM_NOP: // we do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ByteCodeInstructionOp int
|
||||
|
||||
const (
|
||||
VM_NOP = ByteCodeInstructionOp(iota)
|
||||
VM_IADD_RS
|
||||
VM_IADD_M
|
||||
VM_IADD_MZ
|
||||
VM_ISUB_R
|
||||
VM_ISUB_M
|
||||
VM_ISUB_MZ
|
||||
VM_IMUL_R
|
||||
VM_IMUL_M
|
||||
VM_IMUL_MZ
|
||||
VM_IMULH_R
|
||||
VM_IMULH_M
|
||||
VM_IMULH_MZ
|
||||
VM_ISMULH_R
|
||||
VM_ISMULH_M
|
||||
VM_ISMULH_MZ
|
||||
VM_IMUL_RCP
|
||||
VM_INEG_R
|
||||
VM_IXOR_R
|
||||
VM_IXOR_M
|
||||
VM_IXOR_MZ
|
||||
VM_IROR_R
|
||||
VM_IROL_R
|
||||
VM_ISWAP_R
|
||||
VM_FSWAP_R
|
||||
VM_FADD_R
|
||||
VM_FADD_M
|
||||
VM_FSUB_R
|
||||
VM_FSUB_M
|
||||
VM_FSCAL_R
|
||||
VM_FMUL_R
|
||||
VM_FDIV_M
|
||||
VM_FSQRT_R
|
||||
VM_CBRANCH
|
||||
VM_CFROUND
|
||||
VM_ISTORE
|
||||
)
|
|
@ -90,9 +90,6 @@ const CONDITIONOFFSET = RANDOMX_JUMP_OFFSET
|
|||
const CONDITIONMASK = ((1 << RANDOMX_JUMP_BITS) - 1)
|
||||
const STOREL3CONDITION = 14
|
||||
|
||||
const REGISTERSCOUNT = 8
|
||||
const REGISTERCOUNTFLT = 4
|
||||
|
||||
const mantissaSize = 52
|
||||
const exponentSize = 11
|
||||
const mantissaMask = (uint64(1) << mantissaSize) - 1
|
||||
|
|
16
register.go
16
register.go
|
@ -1,3 +1,17 @@
|
|||
package randomx
|
||||
|
||||
type RegisterLine [REGISTERSCOUNT]uint64
|
||||
const RegistersCount = 8
|
||||
const RegistersCountFloat = 4
|
||||
|
||||
type RegisterLine [RegistersCount]uint64
|
||||
|
||||
type RegisterFile struct {
|
||||
r RegisterLine
|
||||
f [RegistersCountFloat][2]float64
|
||||
e [RegistersCountFloat][2]float64
|
||||
a [RegistersCountFloat][2]float64
|
||||
}
|
||||
|
||||
type MemoryRegisters struct {
|
||||
mx, ma uint64
|
||||
}
|
||||
|
|
|
@ -85,8 +85,8 @@ func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc {
|
|||
for i := range p {
|
||||
instr := &p[i]
|
||||
|
||||
dst := instr.Dst_Reg % REGISTERSCOUNT
|
||||
src := instr.Src_Reg % REGISTERSCOUNT
|
||||
dst := instr.Dst_Reg % RegistersCount
|
||||
src := instr.Src_Reg % RegistersCount
|
||||
|
||||
switch instr.Opcode {
|
||||
case S_ISUB_R:
|
||||
|
|
30
vm.go
30
vm.go
|
@ -49,13 +49,13 @@ type VM struct {
|
|||
Prog []byte
|
||||
ScratchPad [ScratchpadSize]byte
|
||||
|
||||
ByteCode [RANDOMX_PROGRAM_SIZE]InstructionByteCode
|
||||
ByteCode ByteCode
|
||||
|
||||
// program configuration see program.hpp
|
||||
|
||||
entropy [16]uint64
|
||||
|
||||
reg REGISTER_FILE // the register file
|
||||
reg RegisterFile // the register file
|
||||
mem MemoryRegisters
|
||||
config Config // configuration
|
||||
datasetOffset uint64
|
||||
|
@ -75,16 +75,6 @@ type Config struct {
|
|||
readReg [4]uint64
|
||||
}
|
||||
|
||||
type REGISTER_FILE struct {
|
||||
r RegisterLine
|
||||
f [4][2]float64
|
||||
e [4][2]float64
|
||||
a [4][2]float64
|
||||
}
|
||||
type MemoryRegisters struct {
|
||||
mx, ma uint64
|
||||
}
|
||||
|
||||
const LOW = 0
|
||||
const HIGH = 1
|
||||
|
||||
|
@ -120,7 +110,7 @@ func (vm *VM) Run(input_hash [64]byte) {
|
|||
vm.config.eMask[LOW] = getFloatMask(vm.entropy[14])
|
||||
vm.config.eMask[HIGH] = getFloatMask(vm.entropy[15])
|
||||
|
||||
vm.Compile_TO_Bytecode()
|
||||
vm.CompileToBytecode()
|
||||
|
||||
spAddr0 := vm.mem.mx
|
||||
spAddr1 := vm.mem.ma
|
||||
|
@ -135,23 +125,23 @@ func (vm *VM) Run(input_hash [64]byte) {
|
|||
spAddr1 ^= spMix >> 32
|
||||
spAddr1 &= ScratchpadL3Mask64
|
||||
|
||||
for i := uint64(0); i < REGISTERSCOUNT; i++ {
|
||||
for i := uint64(0); i < RegistersCount; i++ {
|
||||
vm.reg.r[i] ^= vm.Load64(spAddr0 + 8*i)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < REGISTERCOUNTFLT; i++ {
|
||||
for i := uint64(0); i < RegistersCountFloat; i++ {
|
||||
vm.reg.f[i] = vm.Load32FA(spAddr1 + 8*i)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < REGISTERCOUNTFLT; i++ {
|
||||
vm.reg.e[i] = vm.Load32FA(spAddr1 + 8*(i+REGISTERCOUNTFLT))
|
||||
for i := uint64(0); i < RegistersCountFloat; i++ {
|
||||
vm.reg.e[i] = vm.Load32FA(spAddr1 + 8*(i+RegistersCountFloat))
|
||||
|
||||
vm.reg.e[i][LOW] = MaskRegisterExponentMantissa(vm.reg.e[i][LOW], vm.config.eMask[LOW])
|
||||
vm.reg.e[i][HIGH] = MaskRegisterExponentMantissa(vm.reg.e[i][HIGH], vm.config.eMask[HIGH])
|
||||
}
|
||||
|
||||
// todo: pass register file directly!
|
||||
vm.InterpretByteCode()
|
||||
vm.ByteCode.Interpret(vm)
|
||||
|
||||
vm.mem.mx ^= vm.reg.r[vm.config.readReg[2]] ^ vm.reg.r[vm.config.readReg[3]]
|
||||
vm.mem.mx &= CacheLineAlignMask
|
||||
|
@ -163,11 +153,11 @@ func (vm *VM) Run(input_hash [64]byte) {
|
|||
// swap the elements
|
||||
vm.mem.mx, vm.mem.ma = vm.mem.ma, vm.mem.mx
|
||||
|
||||
for i := uint64(0); i < REGISTERSCOUNT; i++ {
|
||||
for i := uint64(0); i < RegistersCount; i++ {
|
||||
binary.LittleEndian.PutUint64(vm.ScratchPad[spAddr1+8*i:], vm.reg.r[i])
|
||||
}
|
||||
|
||||
for i := uint64(0); i < REGISTERCOUNTFLT; i++ {
|
||||
for i := uint64(0); i < RegistersCountFloat; i++ {
|
||||
vm.reg.f[i][LOW] = math.Float64frombits(math.Float64bits(vm.reg.f[i][LOW]) ^ math.Float64bits(vm.reg.e[i][LOW]))
|
||||
vm.reg.f[i][HIGH] = math.Float64frombits(math.Float64bits(vm.reg.f[i][HIGH]) ^ math.Float64bits(vm.reg.e[i][HIGH]))
|
||||
|
||||
|
|
|
@ -30,17 +30,12 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/go-randomx/v2/asm"
|
||||
"math"
|
||||
"math/bits"
|
||||
"unsafe"
|
||||
)
|
||||
import "encoding/binary"
|
||||
|
||||
//reference https://github.com/tevador/RandomX/blob/master/doc/specs.md#51-instruction-encoding
|
||||
|
||||
var Zero uint64 = 0
|
||||
|
||||
// since go does not have union, use byte array
|
||||
type VM_Instruction []byte // it is hardcode 8 bytes
|
||||
|
||||
|
@ -60,80 +55,11 @@ func (ins VM_Instruction) Opcode() byte {
|
|||
return ins[0]
|
||||
}
|
||||
|
||||
type VM_Instruction_Type int
|
||||
|
||||
const (
|
||||
VM_IADD_RS VM_Instruction_Type = 0
|
||||
VM_IADD_M VM_Instruction_Type = 1
|
||||
VM_ISUB_R VM_Instruction_Type = 2
|
||||
VM_ISUB_M VM_Instruction_Type = 3
|
||||
VM_IMUL_R VM_Instruction_Type = 4
|
||||
VM_IMUL_M VM_Instruction_Type = 5
|
||||
VM_IMULH_R VM_Instruction_Type = 6
|
||||
VM_IMULH_M VM_Instruction_Type = 7
|
||||
VM_ISMULH_R VM_Instruction_Type = 8
|
||||
VM_ISMULH_M VM_Instruction_Type = 9
|
||||
VM_IMUL_RCP VM_Instruction_Type = 10
|
||||
VM_INEG_R VM_Instruction_Type = 11
|
||||
VM_IXOR_R VM_Instruction_Type = 12
|
||||
VM_IXOR_M VM_Instruction_Type = 13
|
||||
VM_IROR_R VM_Instruction_Type = 14
|
||||
VM_IROL_R VM_Instruction_Type = 15
|
||||
VM_ISWAP_R VM_Instruction_Type = 16
|
||||
VM_FSWAP_R VM_Instruction_Type = 17
|
||||
VM_FADD_R VM_Instruction_Type = 18
|
||||
VM_FADD_M VM_Instruction_Type = 19
|
||||
VM_FSUB_R VM_Instruction_Type = 20
|
||||
VM_FSUB_M VM_Instruction_Type = 21
|
||||
VM_FSCAL_R VM_Instruction_Type = 22
|
||||
VM_FMUL_R VM_Instruction_Type = 23
|
||||
VM_FDIV_M VM_Instruction_Type = 24
|
||||
VM_FSQRT_R VM_Instruction_Type = 25
|
||||
VM_CBRANCH VM_Instruction_Type = 26
|
||||
VM_CFROUND VM_Instruction_Type = 27
|
||||
VM_ISTORE VM_Instruction_Type = 28
|
||||
VM_NOP VM_Instruction_Type = 29
|
||||
)
|
||||
|
||||
var Names = map[VM_Instruction_Type]string{
|
||||
|
||||
VM_IADD_RS: "VM_IADD_RS",
|
||||
VM_IADD_M: "VM_IADD_M",
|
||||
VM_ISUB_R: "VM_ISUB_R",
|
||||
VM_ISUB_M: "VM_ISUB_M",
|
||||
VM_IMUL_R: "VM_IMUL_R",
|
||||
VM_IMUL_M: "VM_IMUL_M",
|
||||
VM_IMULH_R: "VM_IMULH_R",
|
||||
VM_IMULH_M: "VM_IMULH_M",
|
||||
VM_ISMULH_R: "VM_ISMULH_R",
|
||||
VM_ISMULH_M: "VM_ISMULH_M",
|
||||
VM_IMUL_RCP: "VM_IMUL_RCP",
|
||||
VM_INEG_R: "VM_INEG_R",
|
||||
VM_IXOR_R: "VM_IXOR_R",
|
||||
VM_IXOR_M: "VM_IXOR_M",
|
||||
VM_IROR_R: "VM_IROR_R",
|
||||
VM_IROL_R: "VM_IROL_R",
|
||||
VM_ISWAP_R: "VM_ISWAP_R",
|
||||
VM_FSWAP_R: "VM_FSWAP_R",
|
||||
VM_FADD_R: "VM_FADD_R",
|
||||
VM_FADD_M: "VM_FADD_M",
|
||||
VM_FSUB_R: "VM_FSUB_R",
|
||||
VM_FSUB_M: "VM_FSUB_M",
|
||||
VM_FSCAL_R: "VM_FSCAL_R",
|
||||
VM_FMUL_R: "VM_FMUL_R",
|
||||
VM_FDIV_M: "VM_FDIV_M",
|
||||
VM_FSQRT_R: "VM_FSQRT_R",
|
||||
VM_CBRANCH: "VM_CBRANCH",
|
||||
VM_CFROUND: "VM_CFROUND",
|
||||
VM_ISTORE: "VM_ISTORE",
|
||||
VM_NOP: "VM_NOP",
|
||||
}
|
||||
|
||||
// this will interpret single vm instruction
|
||||
// CompileToBytecode this will interpret single vm instruction
|
||||
// reference https://github.com/tevador/RandomX/blob/master/doc/specs.md#52-integer-instructions
|
||||
func (vm *VM) Compile_TO_Bytecode() {
|
||||
func (vm *VM) CompileToBytecode() {
|
||||
|
||||
var registerUsage [REGISTERSCOUNT]int
|
||||
var registerUsage [RegistersCount]int
|
||||
for i := range registerUsage {
|
||||
registerUsage[i] = -1
|
||||
}
|
||||
|
@ -143,8 +69,8 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc := &vm.ByteCode[i]
|
||||
|
||||
opcode := instr.Opcode()
|
||||
dst := instr.Dst() % REGISTERSCOUNT // bit shift optimization
|
||||
src := instr.Src() % REGISTERSCOUNT
|
||||
dst := instr.Dst() % RegistersCount // bit shift optimization
|
||||
src := instr.Src() % RegistersCount
|
||||
ibc.dst = dst
|
||||
ibc.src = src
|
||||
switch opcode {
|
||||
|
@ -174,7 +100,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_IADD_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -202,7 +128,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_ISUB_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -230,7 +156,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_IMUL_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -251,7 +177,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_IMULH_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -272,7 +198,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_ISMULH_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -316,7 +242,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.memMask = ScratchpadL2Mask
|
||||
}
|
||||
} else {
|
||||
ibc.isrc = &Zero
|
||||
ibc.Opcode = VM_IXOR_MZ
|
||||
ibc.memMask = ScratchpadL3Mask
|
||||
}
|
||||
registerUsage[dst] = i
|
||||
|
@ -360,20 +286,20 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
// below are floating point instructions
|
||||
case 120, 121, 122, 123: // 4
|
||||
ibc.Opcode = VM_FSWAP_R
|
||||
if dst < REGISTERCOUNTFLT {
|
||||
if dst < RegistersCountFloat {
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
} else {
|
||||
ibc.fdst = &vm.reg.e[dst-REGISTERCOUNTFLT]
|
||||
ibc.fdst = &vm.reg.e[dst-RegistersCountFloat]
|
||||
}
|
||||
case 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139: //16
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
src := instr.Src() % REGISTERCOUNTFLT
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
src := instr.Src() % RegistersCountFloat
|
||||
ibc.Opcode = VM_FADD_R
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
ibc.fsrc = &vm.reg.a[src]
|
||||
|
||||
case 140, 141, 142, 143, 144: //5
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
ibc.Opcode = VM_FADD_M
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
ibc.isrc = &vm.reg.r[src]
|
||||
|
@ -385,13 +311,13 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.imm = signExtend2sCompl(instr.IMM())
|
||||
|
||||
case 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160: //16
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
src := instr.Src() % REGISTERCOUNTFLT
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
src := instr.Src() % RegistersCountFloat
|
||||
ibc.Opcode = VM_FSUB_R
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
ibc.fsrc = &vm.reg.a[src]
|
||||
case 161, 162, 163, 164, 165: //5
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
ibc.Opcode = VM_FSUB_M
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
ibc.isrc = &vm.reg.r[src]
|
||||
|
@ -403,17 +329,17 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
ibc.imm = signExtend2sCompl(instr.IMM())
|
||||
|
||||
case 166, 167, 168, 169, 170, 171: //6
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
ibc.Opcode = VM_FSCAL_R
|
||||
ibc.fdst = &vm.reg.f[dst]
|
||||
case 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203: //32
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
src := instr.Src() % REGISTERCOUNTFLT
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
src := instr.Src() % RegistersCountFloat
|
||||
ibc.Opcode = VM_FMUL_R
|
||||
ibc.fdst = &vm.reg.e[dst]
|
||||
ibc.fsrc = &vm.reg.a[src]
|
||||
case 204, 205, 206, 207: //4
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
ibc.Opcode = VM_FDIV_M
|
||||
ibc.fdst = &vm.reg.e[dst]
|
||||
ibc.isrc = &vm.reg.r[src]
|
||||
|
@ -424,13 +350,13 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
}
|
||||
ibc.imm = signExtend2sCompl(instr.IMM())
|
||||
case 208, 209, 210, 211, 212, 213: //6
|
||||
dst := instr.Dst() % REGISTERCOUNTFLT // bit shift optimization
|
||||
dst := instr.Dst() % RegistersCountFloat // bit shift optimization
|
||||
ibc.Opcode = VM_FSQRT_R
|
||||
ibc.fdst = &vm.reg.e[dst]
|
||||
|
||||
case 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238: //25 // CBRANCH and CFROUND are interchanged
|
||||
ibc.Opcode = VM_CBRANCH
|
||||
reg := instr.Dst() % REGISTERSCOUNT
|
||||
reg := instr.Dst() % RegistersCount
|
||||
ibc.isrc = &vm.reg.r[reg]
|
||||
ibc.target = int16(registerUsage[reg])
|
||||
shift := uint64(instr.Mod()>>4) + CONDITIONOFFSET
|
||||
|
@ -441,7 +367,7 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
}
|
||||
ibc.memMask = CONDITIONMASK << shift
|
||||
|
||||
for j := 0; j < REGISTERSCOUNT; j++ {
|
||||
for j := 0; j < RegistersCount; j++ {
|
||||
registerUsage[j] = i
|
||||
}
|
||||
|
||||
|
@ -474,47 +400,6 @@ func (vm *VM) Compile_TO_Bytecode() {
|
|||
|
||||
}
|
||||
|
||||
type InstructionByteCode struct {
|
||||
dst, src byte
|
||||
idst, isrc *uint64
|
||||
fdst, fsrc *[2]float64
|
||||
imm uint64
|
||||
simm int64
|
||||
Opcode VM_Instruction_Type
|
||||
target int16
|
||||
shift uint8
|
||||
memMask uint32
|
||||
/*
|
||||
union {
|
||||
int_reg_t* idst;
|
||||
rx_vec_f128* fdst;
|
||||
};
|
||||
union {
|
||||
int_reg_t* isrc;
|
||||
rx_vec_f128* fsrc;
|
||||
};
|
||||
union {
|
||||
uint64_t imm;
|
||||
int64_t simm;
|
||||
};
|
||||
InstructionType type;
|
||||
union {
|
||||
int16_t target;
|
||||
uint16_t shift;
|
||||
};
|
||||
uint32_t memMask;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
func (ibc *InstructionByteCode) getScratchpadAddress() uint64 {
|
||||
return (*ibc.isrc + ibc.imm) & uint64(ibc.memMask)
|
||||
}
|
||||
|
||||
func (ibc *InstructionByteCode) getScratchpadDestAddress() uint64 {
|
||||
return (*ibc.idst + ibc.imm) & uint64(ibc.memMask)
|
||||
}
|
||||
|
||||
func (vm *VM) Load64(addr uint64) uint64 {
|
||||
return *(*uint64)(unsafe.Pointer(&vm.ScratchPad[addr]))
|
||||
}
|
||||
|
@ -531,85 +416,3 @@ func (vm *VM) Load32FA(addr uint64) [2]float64 {
|
|||
a := *(*[2]int32)(unsafe.Pointer(&vm.ScratchPad[addr]))
|
||||
return [2]float64{float64(a[LOW]), float64(a[HIGH])}
|
||||
}
|
||||
|
||||
func (vm *VM) InterpretByteCode() {
|
||||
for pc := 0; pc < RANDOMX_PROGRAM_SIZE; pc++ {
|
||||
ibc := &vm.ByteCode[pc]
|
||||
switch ibc.Opcode {
|
||||
case VM_IADD_RS:
|
||||
*ibc.idst += (*ibc.isrc << ibc.shift) + ibc.imm
|
||||
case VM_IADD_M:
|
||||
*ibc.idst += vm.Load64(ibc.getScratchpadAddress())
|
||||
case VM_ISUB_R:
|
||||
*ibc.idst -= *ibc.isrc
|
||||
case VM_ISUB_M:
|
||||
*ibc.idst -= vm.Load64(ibc.getScratchpadAddress())
|
||||
case VM_IMUL_R:
|
||||
// also handles imul_rcp
|
||||
*ibc.idst *= *ibc.isrc
|
||||
case VM_IMUL_M:
|
||||
*ibc.idst *= vm.Load64(ibc.getScratchpadAddress())
|
||||
case VM_IMULH_R:
|
||||
*ibc.idst, _ = bits.Mul64(*ibc.idst, *ibc.isrc)
|
||||
case VM_IMULH_M:
|
||||
*ibc.idst, _ = bits.Mul64(*ibc.idst, vm.Load64(ibc.getScratchpadAddress()))
|
||||
case VM_ISMULH_R:
|
||||
*ibc.idst = smulh(int64(*ibc.idst), int64(*ibc.isrc))
|
||||
case VM_ISMULH_M:
|
||||
*ibc.idst = smulh(int64(*ibc.idst), int64(vm.Load64(ibc.getScratchpadAddress())))
|
||||
case VM_INEG_R:
|
||||
*ibc.idst = (^(*ibc.idst)) + 1 // 2's complement negative
|
||||
case VM_IXOR_R:
|
||||
*ibc.idst ^= *ibc.isrc
|
||||
case VM_IXOR_M:
|
||||
*ibc.idst ^= vm.Load64(ibc.getScratchpadAddress())
|
||||
case VM_IROR_R:
|
||||
*ibc.idst = bits.RotateLeft64(*ibc.idst, 0-int(*ibc.isrc&63))
|
||||
case VM_IROL_R:
|
||||
*ibc.idst = bits.RotateLeft64(*ibc.idst, int(*ibc.isrc&63))
|
||||
case VM_ISWAP_R:
|
||||
*ibc.idst, *ibc.isrc = *ibc.isrc, *ibc.idst
|
||||
case VM_FSWAP_R:
|
||||
ibc.fdst[HIGH], ibc.fdst[LOW] = ibc.fdst[LOW], ibc.fdst[HIGH]
|
||||
case VM_FADD_R:
|
||||
ibc.fdst[LOW] += ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] += ibc.fsrc[HIGH]
|
||||
case VM_FADD_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadAddress())
|
||||
ibc.fdst[LOW] += lo
|
||||
ibc.fdst[HIGH] += hi
|
||||
case VM_FSUB_R:
|
||||
ibc.fdst[LOW] -= ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] -= ibc.fsrc[HIGH]
|
||||
case VM_FSUB_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadAddress())
|
||||
ibc.fdst[LOW] -= lo
|
||||
ibc.fdst[HIGH] -= hi
|
||||
case VM_FSCAL_R:
|
||||
// no dependent on rounding modes
|
||||
ibc.fdst[LOW] = math.Float64frombits(math.Float64bits(ibc.fdst[LOW]) ^ 0x80F0000000000000)
|
||||
ibc.fdst[HIGH] = math.Float64frombits(math.Float64bits(ibc.fdst[HIGH]) ^ 0x80F0000000000000)
|
||||
case VM_FMUL_R:
|
||||
ibc.fdst[LOW] *= ibc.fsrc[LOW]
|
||||
ibc.fdst[HIGH] *= ibc.fsrc[HIGH]
|
||||
case VM_FDIV_M:
|
||||
lo, hi := vm.Load32F(ibc.getScratchpadAddress())
|
||||
ibc.fdst[LOW] /= MaskRegisterExponentMantissa(lo, vm.config.eMask[LOW])
|
||||
ibc.fdst[HIGH] /= MaskRegisterExponentMantissa(hi, vm.config.eMask[HIGH])
|
||||
case VM_FSQRT_R:
|
||||
ibc.fdst[LOW] = math.Sqrt(ibc.fdst[LOW])
|
||||
ibc.fdst[HIGH] = math.Sqrt(ibc.fdst[HIGH])
|
||||
case VM_CBRANCH:
|
||||
*ibc.isrc += ibc.imm
|
||||
if (*ibc.isrc & uint64(ibc.memMask)) == 0 {
|
||||
pc = int(ibc.target)
|
||||
}
|
||||
case VM_CFROUND:
|
||||
tmp := (bits.RotateLeft64(*ibc.isrc, 0-int(ibc.imm))) % 4 // rotate right
|
||||
asm.SetRoundingMode(asm.RoundingMode(tmp))
|
||||
case VM_ISTORE:
|
||||
binary.LittleEndian.PutUint64(vm.ScratchPad[(*ibc.idst+ibc.imm)&uint64(ibc.memMask):], *ibc.isrc)
|
||||
case VM_NOP: // we do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue