@@ -97,7 +97,7 @@ procedure FreeCallBacks;
9797implementation 
9898
9999uses 
100-  Windows, Classes;
100+  { $IFDEF MSWINDOWS } { $ENDIF } 
101101
102102type 
103103 PByte = ^Byte;
@@ -136,7 +136,11 @@ procedure GetCodeMem(var ptr: PByte; size: integer);
136136 if  (page = nil ) or  (Longint(CodeMemPages^.CodeBlocks) - Longint(Pointer(CodeMemPages)) <= (size + 3 *sizeof(PCodeMemBlock))) then 
137137 begin 
138138 //  allocate new Page
139+ { $IFDEF MSWINDOWS} 
139140 page:=VirtualAlloc(nil , PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
141+ { $ELSE} 
142+  page := GetMem(PageSize);
143+ { $ENDIF} 
140144 page^.next:=CodeMemPages;
141145 CodeMemPages:=page;
142146 //  init pointer to end of page
@@ -189,7 +193,11 @@ procedure FreeCodeMem(ptr: Pointer);
189193 CodeMemPages:=page^.Next;
190194
191195 //  free the memory
196+  { $IFDEF MSWINDOWS} 
192197 VirtualFree(page, 0 , MEM_RELEASE);
198+  { $ELSE} 
199+  FreeMem(page);
200+  { $ENDIF} 
193201 end ;
194202
195203 exit;
@@ -233,7 +241,10 @@ function GetOfObjectCallBack( CallBack: TCallBack;
233241 argnum, calltype);
234242end ;
235243
236- function  GetCallBack ( self: TObject; method: Pointer;
244+ { $IFDEF MSWINDOWS} 
245+ { $IFNDEF CPUX64} 
246+ //  win32 inplementation
247+ function  GetCallBack ( self: TObject; method: Pointer;
237248 argnum: Integer; calltype: tcalltype): Pointer;
238249const 
239250//  Short handling of stdcalls:
@@ -307,6 +318,187 @@ function GetCallBack( self: TObject; method: Pointer;
307318 end ;
308319 result := Q;
309320end ;
321+ { $ELSE} 
322+ procedure  test ;
323+ asm 
324+ mov r9,[rbp+$2020 ]
325+ end ;
326+ 
327+ //  win 64 implementation
328+ function  GetCallBack ( self: TObject; method: Pointer;
329+  argnum: Integer; calltype: tcalltype): Pointer;
330+ const 
331+ //  64 bit
332+ c64stack: array [0 ..14 ] of  byte = (
333+ $48 , $81 , $ec, 00 , 00 , 00 , 00 ,//  sub rsp,$0
334+ $4c, $89 , $8c, $24 , $20 , 00 , 00 , 00 //  mov [rsp+$20],r9
335+ );
336+ 
337+ c64copy: array [0 ..14 ] of  byte = (
338+ $4c, $8b, $8d, 00 , 00 , 00 , 00 ,//  mov r9,[rbp+0]
339+ $4c, $89 , $8c, $24 , 00 , 00 , 00 , 00 //  mov [rsp+0],r9
340+ );
341+ 
342+ c64regs: array [0 ..28 ] of  byte = (
343+ $4d, $89 , $c1, //  mov r9,r8
344+ $49 , $89 , $d0, //  mov r8,rdx
345+ $48 , $89 , $ca, //  mov rdx,rcx
346+ $48 , $b9, 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00 , //  mov rcx, self
347+ $48 , $b8, 00 , 00 , 00 , 00 , 00 , 00 , 00 , 00  //  mov rax, method
348+ );
349+ 
350+ c64jump: array [0 ..2 ] of  byte = (
351+ $48 , $ff, $e0 //  jump rax
352+ );
353+ 
354+ c64call: array [0 ..10 ] of  byte = (
355+ $48 , $ff, $d0, //  call rax
356+ $48 , $81 ,$c4, 00 , 00 , 00 , 00 , //  add rsp,$0
357+ $c3//  ret
358+ );
359+ var 
360+  i: Integer;
361+  P,Q: PByte;
362+  lCount : integer;
363+  lSize : integer;
364+  lOffset : integer;
365+ begin 
366+ // test;
367+  lCount := SizeOf(c64regs);
368+  if  argnum>3  then 
369+  Inc(lCount,sizeof(c64stack)+(argnum-4 )*sizeof(c64copy)+sizeof(c64call))
370+  else 
371+  Inc(lCount,sizeof(c64jump));
372+ 
373+  GetCodeMem(Q,lCount);
374+  P := Q;
375+ 
376+  if  argnum>3  then 
377+  begin 
378+  move(c64stack,P^,SizeOf(c64stack));
379+  Inc(P,3 );
380+  lSize := (argnum +1  ) * sizeof(Int64);
381+  move(lSize,P^,sizeof(Int32));
382+  Inc(P,SizeOf(c64stack)-3 );
383+  for  I := 5  to  argnum do 
384+  begin 
385+  move(c64copy,P^,SizeOf(c64copy));
386+  Inc(P,3 );
387+  lOffset := (i-1 )*sizeof(Int64);
388+  move(lOffset,P^,sizeof(Int32));
389+  Inc(P,8 );
390+  lOffset := i*sizeof(Int64);
391+  move(lOffset,P^,sizeof(Int32));
392+  Inc(P,4 );
393+  end ;
394+  end ;
395+ 
396+  move(c64regs,P^,SizeOf(c64regs));
397+  Inc(P,11 );
398+  move(self,P^,SizeOf(self));
399+  Inc(P,10 );
400+  move(method,P^,SizeOf(method));
401+ 
402+  Inc(P,SizeOf(c64regs)-21 );
403+ 
404+  if  argnum<4  then 
405+  move(c64jump,P^,SizeOf(c64jump))
406+  else 
407+  begin 
408+  move(c64call,P^,SizeOf(c64call));
409+  Inc(P,6 );
410+  lSize := (argnum+1 ) * sizeof(Int64);
411+  move(lSize,P^,sizeof(Int32));
412+  end ;
413+  result := Q;
414+ end ;
415+ { $ENDIF} 
416+ { $ELSE} 
417+ //  32 bit with stack align
418+ function  GetCallBack ( self: TObject; method: Pointer;
419+  argnum: Integer; calltype: tcalltype): Pointer;
420+ const 
421+ //  Short handling of stdcalls:
422+ S1: array  [0 ..14 ] of  byte = (
423+ $5A, // 00 pop edx // pop return address
424+ $B8,0 ,0 ,0 ,0 , // 01 mov eax, self
425+ $50 , // 06 push eax
426+ $52 , // 07 push edx // now push return address
427+ //  call the real callback
428+ $B8,0 ,0 ,0 ,0 , // 08 mov eax, Method
429+ $FF,$E0); // 13 jmp eax
430+ 
431+ // Handling for ctCDECL:
432+ C1: array  [0 ..5 ] of  byte = (
433+ //  begin of call
434+ $55 , // 00 push ebp
435+ $8B,$EC, // 01 mov ebp, esp
436+ $83 ,$EC,$0 ); // 03 sub esp, align
437+ 
438+ //  push arguments
439+ //  for i:= argnum-1 downto 0 do begin
440+ C2: array  [0 ..3 ] of  byte = (
441+ $8B,$45 ,0 , // 06+4*s mov eax,[ebp+8+4*i]
442+ $50 ); // 09+4*s push eax
443+ //  end;
444+ 
445+ //  self parameter
446+ C3: array  [0 ..17 ] of  byte = (
447+ $B8,0 ,0 ,0 ,0 , // 06+4*s mov eax, self
448+ $50 , // 11+4*s push eax
449+ //  call the real callback
450+ $B8,0 ,0 ,0 ,0 , // 12+4*s mov eax,Method
451+ $FF,$D0, // 17+4*s call eax
452+ //  clear stack
453+ $83 ,$C4,0 , // 20+4*s add esp, 4+bytes+align
454+ $5D, // 23+4*s pop ebp
455+ $C3); // 24+4*s ret
456+ 
457+ 
458+ 
459+ var 
460+  bytes: Word;
461+  i: Integer;
462+  P,Q: PByte;
463+  align : integer;
464+ begin 
465+  if  calltype = ctSTDCALL then  begin 
466+  GetCodeMem(Q,15 );
467+  P := Q;
468+  move(S1,P^,SizeOf(S1));
469+  Inc(P,2 );
470+  move(self,P^,SizeOf(self));
471+  Inc(P,7 );
472+  move(method,P^,SizeOf(method));
473+  { Inc(P,6); End of proc} 
474+  end  else  begin  { ctCDECL} 
475+  bytes := argnum * 4 ;
476+ align := ($10  - (bytes + 4 { self} 4 { address} 4 { push bp} and  $f) and  $f; //  align to $10 for Mac compatibility
477+ 
478+  GetCodeMem(Q,24 +4 *argnum);
479+  P := Q;
480+  move(C1,P^,SizeOf(C1));
481+  Inc(P,SizeOf(C1)-1 );
482+  p^ := align;
483+  Inc(P);
484+  for  i:=argnum-1  downto  0  do  begin 
485+  move(C2,P^,SizeOf(C2));
486+  Inc(P,2 );
487+  P^:=8 +4 *i;
488+  Inc(P,2 );
489+  end ;
490+  move(C3,P^,SizeOf(C3));
491+  Inc(P,1 );
492+  move(self,P^,SizeOf(self));
493+  Inc(P,6 );
494+  move(method,P^,SizeOf(method));
495+  Inc(P,8 );
496+  P^ := 4 +bytes+align;
497+  { Inc(P,3); End of proc} 
498+  end ;
499+  result := Q;
500+ end ;
501+ { $ENDIF} 
310502
311503procedure  DeleteCallBack ( Proc: Pointer);
312504begin 
@@ -324,7 +516,11 @@ procedure FreeCallBacks;
324516 nextpage := page^.Next;
325517
326518 //  free the memory
327-  VirtualFree(page, 0 , MEM_RELEASE);
519+  { $IFDEF MSWINDOWS} 
520+  VirtualFree(page, 0 , MEM_RELEASE);
521+  { $ELSE} 
522+ FreeMem(page);
523+  { $ENDIF} 
328524
329525 page := nextpage;
330526 end ;
0 commit comments