@@ -97,7 +97,7 @@ procedure FreeCallBacks;
9797implementation
9898
9999uses
100- Windows, Classes;
100+ { $IFDEF MSWINDOWS } Windows,{ $ENDIF } Classes;
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