redo JIT superscalar to include less custom assembly
This commit is contained in:
parent
a71d8f6a2e
commit
34cfab4176
5
cache.go
5
cache.go
|
@ -12,8 +12,7 @@ type MemoryBlock [128]uint64
|
||||||
|
|
||||||
func (m *MemoryBlock) GetLine(addr uint64) *RegisterLine {
|
func (m *MemoryBlock) GetLine(addr uint64) *RegisterLine {
|
||||||
addr >>= 3
|
addr >>= 3
|
||||||
//[addr : addr+8 : addr+8]
|
return (*RegisterLine)(unsafe.Pointer(unsafe.SliceData(m[addr : addr+8 : addr+8])))
|
||||||
return (*RegisterLine)(unsafe.Add(unsafe.Pointer(m), addr*8))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Randomx_Cache struct {
|
type Randomx_Cache struct {
|
||||||
|
@ -21,7 +20,7 @@ type Randomx_Cache struct {
|
||||||
|
|
||||||
Programs [RANDOMX_PROGRAM_COUNT]SuperScalarProgram
|
Programs [RANDOMX_PROGRAM_COUNT]SuperScalarProgram
|
||||||
|
|
||||||
JitPrograms [RANDOMX_PROGRAM_COUNT]ProgramFunc
|
JitPrograms [RANDOMX_PROGRAM_COUNT]SuperScalarProgramFunc
|
||||||
|
|
||||||
Flags uint64
|
Flags uint64
|
||||||
}
|
}
|
||||||
|
|
2
exec.go
2
exec.go
|
@ -1,3 +1,3 @@
|
||||||
package randomx
|
package randomx
|
||||||
|
|
||||||
type ProgramFunc []byte
|
type SuperScalarProgramFunc []byte
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
package randomx
|
package randomx
|
||||||
|
|
||||||
func (f ProgramFunc) Execute(v uintptr) {
|
func (f SuperScalarProgramFunc) Close() error {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f ProgramFunc) Close() error {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,35 +4,13 @@ package randomx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"runtime"
|
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f ProgramFunc) Execute(v uintptr) {
|
func (f SuperScalarProgramFunc) Close() error {
|
||||||
if f == nil {
|
|
||||||
panic("program is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
var reservedStackHack [8 * 8]byte
|
|
||||||
for i := range reservedStackHack {
|
|
||||||
reservedStackHack[i] = uint8(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryPtr := &f
|
|
||||||
fun := *(*func(v uintptr))(unsafe.Pointer(&memoryPtr))
|
|
||||||
fun(v)
|
|
||||||
|
|
||||||
for i := range reservedStackHack {
|
|
||||||
reservedStackHack[i] = uint8(-i)
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(reservedStackHack)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f ProgramFunc) Close() error {
|
|
||||||
return unix.Munmap(f)
|
return unix.Munmap(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapProgram(program []byte) ProgramFunc {
|
func mapProgram(program []byte) []byte {
|
||||||
// Write only
|
// Write only
|
||||||
execFunc, err := unix.Mmap(-1, 0, len(program), unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANONYMOUS)
|
execFunc, err := unix.Mmap(-1, 0, len(program), unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANONYMOUS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
54
jit_amd64.go
54
jit_amd64.go
|
@ -11,8 +11,8 @@ package randomx
|
||||||
; rcx -> temporary
|
; rcx -> temporary
|
||||||
; rdx -> temporary
|
; rdx -> temporary
|
||||||
; rsi -> scratchpad pointer
|
; rsi -> scratchpad pointer
|
||||||
; rdi -> dataset pointer
|
; rdi -> return address // dataset pointer
|
||||||
; rbp -> memory registers "ma" (high 32 bits), "mx" (low 32 bits)
|
; rbp -> (do not use, it's used by Golang sampling) jump target //todo: memory registers "ma" (high 32 bits), "mx" (low 32 bits)
|
||||||
; rsp -> stack pointer
|
; rsp -> stack pointer
|
||||||
; r8 -> "r0"
|
; r8 -> "r0"
|
||||||
; r9 -> "r1"
|
; r9 -> "r1"
|
||||||
|
@ -154,53 +154,3 @@ var NOP8 = []byte{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||||
func genSIB(scale, index, base int) byte {
|
func genSIB(scale, index, base int) byte {
|
||||||
return byte((scale << 6) | (index << 3) | base)
|
return byte((scale << 6) | (index << 3) | base)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
push rbp
|
|
||||||
push rbx
|
|
||||||
push rsi
|
|
||||||
push r12
|
|
||||||
push r13
|
|
||||||
push r14
|
|
||||||
push r15
|
|
||||||
mov rbp,rsp
|
|
||||||
sub rsp,(0x8*7)
|
|
||||||
|
|
||||||
mov rsi, rax; # register dataset
|
|
||||||
|
|
||||||
prefetchnta byte ptr [rsi]
|
|
||||||
|
|
||||||
mov r8, qword ptr [rsi+0]
|
|
||||||
mov r9, qword ptr [rsi+8]
|
|
||||||
mov r10, qword ptr [rsi+16]
|
|
||||||
mov r11, qword ptr [rsi+24]
|
|
||||||
mov r12, qword ptr [rsi+32]
|
|
||||||
mov r13, qword ptr [rsi+40]
|
|
||||||
mov r14, qword ptr [rsi+48]
|
|
||||||
mov r15, qword ptr [rsi+56]
|
|
||||||
*/
|
|
||||||
var codeInitBlock = []byte{0x55, 0x53, 0x56, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x89, 0xC6, 0x0F, 0x18, 0x06, 0x4C, 0x8B, 0x06, 0x4C, 0x8B, 0x4E, 0x08, 0x4C, 0x8B, 0x56, 0x10, 0x4C, 0x8B, 0x5E, 0x18, 0x4C, 0x8B, 0x66, 0x20, 0x4C, 0x8B, 0x6E, 0x28, 0x4C, 0x8B, 0x76, 0x30, 0x4C, 0x8B, 0x7E, 0x38}
|
|
||||||
|
|
||||||
/*
|
|
||||||
prefetchw byte ptr [rsi]
|
|
||||||
|
|
||||||
mov qword ptr [rsi+0], r8
|
|
||||||
mov qword ptr [rsi+8], r9
|
|
||||||
mov qword ptr [rsi+16], r10
|
|
||||||
mov qword ptr [rsi+24], r11
|
|
||||||
mov qword ptr [rsi+32], r12
|
|
||||||
mov qword ptr [rsi+40], r13
|
|
||||||
mov qword ptr [rsi+48], r14
|
|
||||||
mov qword ptr [rsi+56], r15
|
|
||||||
|
|
||||||
add rsp,(0x8*7)
|
|
||||||
pop r15
|
|
||||||
pop r14
|
|
||||||
pop r13
|
|
||||||
pop r12
|
|
||||||
pop rsi
|
|
||||||
pop rbx
|
|
||||||
pop rbp
|
|
||||||
ret
|
|
||||||
*/
|
|
||||||
var codeRetBlock = []byte{0x0F, 0x0D, 0x0E, 0x4C, 0x89, 0x06, 0x4C, 0x89, 0x4E, 0x08, 0x4C, 0x89, 0x56, 0x10, 0x4C, 0x89, 0x5E, 0x18, 0x4C, 0x89, 0x66, 0x20, 0x4C, 0x89, 0x6E, 0x28, 0x4C, 0x89, 0x76, 0x30, 0x4C, 0x89, 0x7E, 0x38, 0x48, 0x83, 0xC4, 0x38, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5E, 0x5B, 0x5D, 0xC3}
|
|
||||||
|
|
|
@ -4,15 +4,41 @@ package randomx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func superscalar_run(rf, jmp uintptr)
|
||||||
|
|
||||||
|
func (f SuperScalarProgramFunc) Execute(rf uintptr) {
|
||||||
|
if f == nil {
|
||||||
|
panic("program is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
superscalar_run(rf, uintptr(unsafe.Pointer(unsafe.SliceData(f))))
|
||||||
|
return
|
||||||
|
|
||||||
|
var reservedStackHack [8 * 8]byte
|
||||||
|
for i := range reservedStackHack {
|
||||||
|
reservedStackHack[i] = uint8(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryPtr := &f
|
||||||
|
fun := *(*func(v uintptr))(unsafe.Pointer(&memoryPtr))
|
||||||
|
fun(rf)
|
||||||
|
|
||||||
|
for i := range reservedStackHack {
|
||||||
|
reservedStackHack[i] = uint8(-i)
|
||||||
|
}
|
||||||
|
runtime.KeepAlive(reservedStackHack)
|
||||||
|
}
|
||||||
|
|
||||||
// generateSuperscalarCode
|
// generateSuperscalarCode
|
||||||
func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc {
|
func generateSuperscalarCode(scalarProgram SuperScalarProgram) SuperScalarProgramFunc {
|
||||||
|
|
||||||
var program []byte
|
var program []byte
|
||||||
|
|
||||||
program = append(program, codeInitBlock...)
|
|
||||||
|
|
||||||
p := scalarProgram.Program()
|
p := scalarProgram.Program()
|
||||||
for i := range p {
|
for i := range p {
|
||||||
instr := &p[i]
|
instr := &p[i]
|
||||||
|
@ -78,7 +104,7 @@ func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
program = append(program, codeRetBlock...)
|
program = append(program, RET)
|
||||||
|
|
||||||
return mapProgram(program)
|
return mapProgram(program)
|
||||||
}
|
}
|
||||||
|
|
39
superscalar_jit_amd64.s
Normal file
39
superscalar_jit_amd64.s
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//go:build unix && amd64 && !disable_jit && !purego
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT ·superscalar_run(SB),$0-16
|
||||||
|
|
||||||
|
MOVQ rf+0(FP), SI
|
||||||
|
|
||||||
|
PREFETCHNTA 0(SI)
|
||||||
|
|
||||||
|
// move register line to registers
|
||||||
|
MOVQ 0(SI), R8
|
||||||
|
MOVQ 8(SI), R9
|
||||||
|
MOVQ 16(SI), R10
|
||||||
|
MOVQ 24(SI), R11
|
||||||
|
MOVQ 32(SI), R12
|
||||||
|
MOVQ 40(SI), R13
|
||||||
|
MOVQ 48(SI), R14
|
||||||
|
MOVQ 56(SI), R15
|
||||||
|
|
||||||
|
MOVQ jmp+8(FP), AX
|
||||||
|
// jump to JIT code
|
||||||
|
CALL AX
|
||||||
|
|
||||||
|
|
||||||
|
// todo: not supported by golang
|
||||||
|
// PREFETCHW 0(SI)
|
||||||
|
|
||||||
|
// move registers back to register line
|
||||||
|
MOVQ R8, 0(SI)
|
||||||
|
MOVQ R9, 8(SI)
|
||||||
|
MOVQ R10, 16(SI)
|
||||||
|
MOVQ R11, 24(SI)
|
||||||
|
MOVQ R12, 32(SI)
|
||||||
|
MOVQ R13, 40(SI)
|
||||||
|
MOVQ R14, 48(SI)
|
||||||
|
MOVQ R15, 56(SI)
|
||||||
|
|
||||||
|
RET
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
package randomx
|
package randomx
|
||||||
|
|
||||||
|
func (f SuperScalarProgramFunc) Execute(rf uintptr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// generateSuperscalarCode
|
// generateSuperscalarCode
|
||||||
func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc {
|
func generateSuperscalarCode(scalarProgram SuperScalarProgram) SuperScalarProgramFunc {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue