@@ -97,7 +97,7 @@ procedure FreeCallBacks;
97
97
implementation
98
98
99
99
uses
100
- Windows, Classes;
100
+ { $IFDEF MSWINDOWS } Windows,{ $ENDIF } Classes;
101
101
102
102
type
103
103
PByte = ^Byte;
@@ -136,7 +136,11 @@ procedure GetCodeMem(var ptr: PByte; size: integer);
136
136
if (page = nil ) or (Longint(CodeMemPages^.CodeBlocks) - Longint(Pointer(CodeMemPages)) <= (size + 3 *sizeof(PCodeMemBlock))) then
137
137
begin
138
138
// allocate new Page
139
+ { $IFDEF MSWINDOWS}
139
140
page:=VirtualAlloc(nil , PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
141
+ { $ELSE}
142
+ page := GetMem(PageSize);
143
+ { $ENDIF}
140
144
page^.next:=CodeMemPages;
141
145
CodeMemPages:=page;
142
146
// init pointer to end of page
@@ -189,7 +193,11 @@ procedure FreeCodeMem(ptr: Pointer);
189
193
CodeMemPages:=page^.Next;
190
194
191
195
// free the memory
196
+ { $IFDEF MSWINDOWS}
192
197
VirtualFree(page, 0 , MEM_RELEASE);
198
+ { $ELSE}
199
+ FreeMem(page);
200
+ { $ENDIF}
193
201
end ;
194
202
195
203
exit;
@@ -233,7 +241,10 @@ function GetOfObjectCallBack( CallBack: TCallBack;
233
241
argnum, calltype);
234
242
end ;
235
243
236
- function GetCallBack ( self: TObject; method: Pointer;
244
+ { $IFDEF MSWINDOWS}
245
+ { $IFNDEF CPUX64}
246
+ // win32 inplementation
247
+ function GetCallBack ( self: TObject; method: Pointer;
237
248
argnum: Integer; calltype: tcalltype): Pointer;
238
249
const
239
250
// Short handling of stdcalls:
@@ -307,6 +318,187 @@ function GetCallBack( self: TObject; method: Pointer;
307
318
end ;
308
319
result := Q;
309
320
end ;
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}
310
502
311
503
procedure DeleteCallBack ( Proc: Pointer);
312
504
begin
@@ -324,7 +516,11 @@ procedure FreeCallBacks;
324
516
nextpage := page^.Next;
325
517
326
518
// 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}
328
524
329
525
page := nextpage;
330
526
end ;
0 commit comments