Windows x64 c backend.
Code: Select all
Procedure JIT(asm.s)
Protected oldProtection;
Protected fn,*asm
Protected fasmpath.s = #PB_Compiler_Home + "Compilers" + #PS$ + "FAsm.exe"
Inputfile.s = GetTemporaryDirectory() + "PBJit.txt"
outputfile.s = GetTemporaryDirectory() + "PBJit.bin"
fn = CreateFile(-1,outputfile)
CloseFile(fn)
fn = CreateFile(-1,Inputfile)
If fn
*asm= UTF8(asm)
WriteData(fn,*asm,MemorySize(*asm))
CloseFile(fn)
OpenConsole()
fasm = RunProgram(fasmpath,Inputfile,"", #PB_Program_Open | #PB_Program_Read)
If fasm
While ProgramRunning(fasm)
If AvailableProgramOutput(fasm)
PrintN(ReadProgramString(fasm))
EndIf
Wend
EndIf
FreeMemory(*asm)
If FileSize(outputfile)
fn = OpenFile(-1,outputfile)
len = Lof(fn)
*asm = AllocateMemory(Len)
ReadData(fn,*asm,len)
CloseFile(fn)
Protected *buffer = VirtualAlloc_(#Null, len, #MEM_COMMIT, #PAGE_READWRITE);
CopyMemory(*asm,*buffer,len)
FreeMemory(*asm) ;
VirtualProtect_(*buffer, len, #PAGE_EXECUTE_READ, @oldProtection) ;
ProcedureReturn *buffer
EndIf
EndIf
EndProcedure
Prototype FastHash64(*Buffer, Len, Seed.q=0)
Global *FastHash64.FastHash64
Procedure JiTFastHash64()
; FastHash64 algorithm by Zilong Tan ported by wilbert
Protected asm.s
asm + "use64 " + #LF$
asm + "MOV qword [rsp+8],rcx"+ #LF$
asm + "MOV qword [rsp+16],rdx"+ #LF$
asm + "MOV qword [rsp+24],r8"+ #LF$
asm + "PS20=48"+ #LF$
asm + "SUB rsp,40"+ #LF$
asm + "p.v_Seed equ rsp+PS20+16" + #LF$
asm + "p.v_Len equ rsp+PS20+8"+ #LF$
asm + "p.p_Buffer equ rsp+PS20+0"+ #LF$
asm + "mov r10, 0x2127599bf4325c37" + #LF$
asm + "mov r11, 0x880355f21e6d1965" + #LF$
asm + "mov rdx, [p.p_Buffer]" + #LF$
asm + "mov rcx, [p.v_Len]" + #LF$
asm + "mov rax, rcx" + #LF$ ; h = seed ^ (len * m);
asm + "imul rax, r11" + #LF$
asm + "xor rax, [p.v_Seed]" + #LF$
asm + "sub rcx, 8" + #LF$
asm + "jc .l1" + #LF$
; 8 byte loop
asm + ".l0: " + #LF$
asm + "mov r8, [rdx]" + #LF$ ; v = *pos++;
asm + "add rdx, 8" + #LF$
; -- mix(v) start --
asm + "mov r9, r8" + #LF$
asm + "shr r9, 23" + #LF$
asm + "xor r8, r9" + #LF$
asm + "imul r8, r10" + #LF$
asm + "mov r9, r8" + #LF$
asm + "shr r9, 47" + #LF$
asm + "xor r8, r9" + #LF$
; -- mix end --
asm + "xor rax, r8" + #LF$ ; h ^= mix(v);
asm + "imul rax, r11" + #LF$ ; h *= m;
asm + "sub rcx, 8" + #LF$
asm + "jnc .l0" + #LF$
; remaining bytes
asm + ".l1: " + #LF$
asm + "add rcx, 8" + #LF$
asm + "jz .l5" + #LF$
asm + "xor r8, r8" + #LF$
asm + "test rcx, 4" + #LF$
asm + "jz .l2" + #LF$
; get 4 bytes
asm + "mov r8d, [rdx]" + #LF$
asm + "add rdx, 4" + #LF$
asm + "ror r8, 32" + #LF$
asm + ".l2: " + #LF$
asm + "test rcx, 2" + #LF$
asm + "jz .l3" + #LF$
; get 2 bytes
asm + "movzx r9d, word [rdx]" + #LF$
asm + "add rdx, 2" + #LF$
asm + "xor r8, r9" + #LF$
asm + "ror r8, 16" + #LF$
asm + ".l3: " + #LF$
asm + "test rcx, 1" + #LF$
asm + "jz .l4" + #LF$
; get 1 byte
asm + "movzx r9d, byte [rdx]" + #LF$
asm + "xor r8, r9" + #LF$
asm + "ror r8, 8" + #LF$
asm + ".l4: "; + #LF$
asm + "and rcx, 7" + #LF$
asm + "shl rcx, 3" + #LF$
asm + "rol r8, cl" + #LF$
; -- mix(v) start --
asm + "mov r9, r8" + #LF$
asm + "shr r9, 23" + #LF$
asm + "xor r8, r9" + #LF$
asm + "imul r8, r10" + #LF$
asm + "mov r9, r8" + #LF$
asm + "shr r9, 47" + #LF$
asm + "xor r8, r9" + #LF$
; -- mix end --
asm + "xor rax, r8" + #LF$ ; h ^= mix(v);
asm + "imul rax, r11" + #LF$ ; h *= m;
; -- mix(h) start --
asm + ".l5: " + #LF$
asm + "mov r9, rax" + #LF$
asm + "shr r9, 23" + #LF$
asm + "xor rax, r9" + #LF$
asm + "imul rax, r10" + #LF$
asm + "mov r9, rax" + #LF$
asm + "shr r9, 47" + #LF$
asm + "xor rax, r9" + #LF$
asm + "add rsp,40"+ #LF$
asm + "ret" + #LF$
ProcedureReturn JIT(asm)
EndProcedure
Procedure.q FastHash64C(*buf,len,Seed.q=0)
Protected result.q
;FastHash64 algorithm by Zilong Tan
!typedef unsigned long long uint64_t;
!#define mix(h) ({ \
! (h) ^= (h) >> 23; \
! (h) *= 0x2127599bf4325c37ULL; \
! (h) ^= (h) >> 47; })
!
! const uint64_t m = 0x880355f21e6d1965ULL;
! const uint64_t *pos = (const uint64_t *)p_buf;
! const uint64_t *end = pos + (v_len / 8);
! const unsigned char *pos2;
! uint64_t h = v_seed ^ (v_len * m);
! uint64_t v;
! uint64_t result;
! while (pos != end) {
! v = *pos++;
! h ^= mix(v);
! h *= m;
! }
! pos2 = (const unsigned char*)pos;
! v = 0;
! switch (v_len & 7) {
! case 7: v ^= (uint64_t)pos2[6] << 48;
! case 6: v ^= (uint64_t)pos2[5] << 40;
! case 5: v ^= (uint64_t)pos2[4] << 32;
! case 4: v ^= (uint64_t)pos2[3] << 24;
! case 3: v ^= (uint64_t)pos2[2] << 16;
! case 2: v ^= (uint64_t)pos2[1] << 8;
! case 1: v ^= (uint64_t)pos2[0];
! h ^= mix(v);
! h *= m;
! }
!
! v_result = mix(h);
ProcedureReturn result
EndProcedure
Global str.s = "Hello JIT function"
*FastHash64 = JiTFastHash64()
If *FastHash64
Debug *FastHash64(@str,StringByteLength(str))
EndIf
Debug FastHash64C(@str,StringByteLength(str))
While this isn't really particularly useful as it is, it wouldn't be to hard to turn it into a compiler tool to embed the binary into a datasection and execute it from the virtualmemory and the same mechanism can be used on linux.
https://burnttoys.blogspot.com/2011/04/ ... ry-on.html