diff --git a/cache.go b/cache.go index 9f3ec04..67b65cf 100644 --- a/cache.go +++ b/cache.go @@ -12,8 +12,7 @@ type MemoryBlock [128]uint64 func (m *MemoryBlock) GetLine(addr uint64) *RegisterLine { addr >>= 3 - //[addr : addr+8 : addr+8] - return (*RegisterLine)(unsafe.Add(unsafe.Pointer(m), addr*8)) + return (*RegisterLine)(unsafe.Pointer(unsafe.SliceData(m[addr : addr+8 : addr+8]))) } type Randomx_Cache struct { @@ -21,7 +20,7 @@ type Randomx_Cache struct { Programs [RANDOMX_PROGRAM_COUNT]SuperScalarProgram - JitPrograms [RANDOMX_PROGRAM_COUNT]ProgramFunc + JitPrograms [RANDOMX_PROGRAM_COUNT]SuperScalarProgramFunc Flags uint64 } diff --git a/exec.go b/exec.go index 3345abd..c10b7b5 100644 --- a/exec.go +++ b/exec.go @@ -1,3 +1,3 @@ package randomx -type ProgramFunc []byte +type SuperScalarProgramFunc []byte diff --git a/exec_generic.go b/exec_generic.go index 0bf1318..00d14aa 100644 --- a/exec_generic.go +++ b/exec_generic.go @@ -2,10 +2,6 @@ package randomx -func (f ProgramFunc) Execute(v uintptr) { - -} - -func (f ProgramFunc) Close() error { +func (f SuperScalarProgramFunc) Close() error { return nil } diff --git a/exec_mmap_unix.go b/exec_mmap_unix.go index d89f2be..5471cd5 100644 --- a/exec_mmap_unix.go +++ b/exec_mmap_unix.go @@ -4,35 +4,13 @@ package randomx import ( "golang.org/x/sys/unix" - "runtime" - "unsafe" ) -func (f ProgramFunc) Execute(v uintptr) { - 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 { +func (f SuperScalarProgramFunc) Close() error { return unix.Munmap(f) } -func mapProgram(program []byte) ProgramFunc { +func mapProgram(program []byte) []byte { // Write only execFunc, err := unix.Mmap(-1, 0, len(program), unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANONYMOUS) if err != nil { diff --git a/jit_amd64.go b/jit_amd64.go index 7dfca68..96fe7c7 100644 --- a/jit_amd64.go +++ b/jit_amd64.go @@ -11,8 +11,8 @@ package randomx ; rcx -> temporary ; rdx -> temporary ; rsi -> scratchpad pointer - ; rdi -> dataset pointer - ; rbp -> memory registers "ma" (high 32 bits), "mx" (low 32 bits) + ; rdi -> return address // dataset pointer + ; 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 ; r8 -> "r0" ; r9 -> "r1" @@ -154,53 +154,3 @@ var NOP8 = []byte{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00} func genSIB(scale, index, base int) byte { 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} diff --git a/superscalar_jit_amd64.go b/superscalar_jit_amd64.go index cf2f017..562532d 100644 --- a/superscalar_jit_amd64.go +++ b/superscalar_jit_amd64.go @@ -4,15 +4,41 @@ package randomx import ( "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 -func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc { +func generateSuperscalarCode(scalarProgram SuperScalarProgram) SuperScalarProgramFunc { var program []byte - program = append(program, codeInitBlock...) - p := scalarProgram.Program() for i := range p { instr := &p[i] @@ -78,7 +104,7 @@ func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc { } } - program = append(program, codeRetBlock...) + program = append(program, RET) return mapProgram(program) } diff --git a/superscalar_jit_amd64.s b/superscalar_jit_amd64.s new file mode 100644 index 0000000..2b078aa --- /dev/null +++ b/superscalar_jit_amd64.s @@ -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 diff --git a/superscalar_noasm.go b/superscalar_noasm.go index 08379ec..1cfa203 100644 --- a/superscalar_noasm.go +++ b/superscalar_noasm.go @@ -2,7 +2,11 @@ package randomx +func (f SuperScalarProgramFunc) Execute(rf uintptr) { + +} + // generateSuperscalarCode -func generateSuperscalarCode(scalarProgram SuperScalarProgram) ProgramFunc { +func generateSuperscalarCode(scalarProgram SuperScalarProgram) SuperScalarProgramFunc { return nil }