|
@@ -14,92 +14,6 @@
|
|
|
|
|
|
**********************************************************************}
|
|
|
|
|
|
-var
|
|
|
- // This is a BSS variable, so it will be initialized to #0
|
|
|
- // This HAS to be larger than the amount if FPC_SETJMP call in the binary
|
|
|
- // To avoid excessive linear searches use at least Calls*1.5 rounded up to the next power of 2
|
|
|
- // If the size gets changed, the code below also needs adjustment
|
|
|
- setjmp_counter: array[0..$2000-1] of TSetJmpCounter;
|
|
|
-
|
|
|
-// This function MUST return 0
|
|
|
-function fpc_count_setjmp: LongInt; assembler; nostackframe;
|
|
|
-asm
|
|
|
- // lr = Original Address
|
|
|
- // r0 = HashValue = (Address >> 2) and $1FFF
|
|
|
- // r1 = HashBase
|
|
|
- // r2 = CallerAddress in hashtable
|
|
|
- // r3 = Counter
|
|
|
-
|
|
|
- // Those two shifts are the "hashfunction"
|
|
|
- // The result can be used as an index into the hashtable
|
|
|
- // These required shift amount can be calculated like this
|
|
|
- // lshift = 32-clz($hashmask)-2
|
|
|
- // rshift = rshift - 1
|
|
|
- // This only works on ARM-Code where the lower two lr bits are always 0
|
|
|
- ldr r1, .LCounterBuffer
|
|
|
- mov r0, lr, lsl #17
|
|
|
- mov r0, r0, lsr #16
|
|
|
-
|
|
|
-.LSlotLoop:
|
|
|
- // Did we wrap?
|
|
|
- tst r0, #0x10000
|
|
|
- // If so, reset to #0
|
|
|
- movne r0, #0
|
|
|
-
|
|
|
- // Load Address and counter
|
|
|
- ldrd r2, r3, [r1, r0]
|
|
|
-
|
|
|
- // If the Address is 0, create a new slot
|
|
|
- cmp r2, #0
|
|
|
- beq .LNewSlot
|
|
|
-
|
|
|
- // A once set Address is not going to change!
|
|
|
- cmp r2, lr
|
|
|
- // Address did not match? Next!
|
|
|
- addne r0, r0, #8
|
|
|
- bne .LSlotLoop
|
|
|
-
|
|
|
- // We'll not increment atomicaly here, because that has a lot of overhead
|
|
|
- // and very little gain, we might miss a small amount of calls, but thats not a big issue
|
|
|
- // Increment counter
|
|
|
- add r3, r3, #1
|
|
|
- // Adjust base to be on the counter
|
|
|
- add r0, r0, #4
|
|
|
- str r3, [r1, r0]
|
|
|
- mov r0, #0
|
|
|
- bx lr
|
|
|
-
|
|
|
-.LNewSlot:
|
|
|
- stmfd sp!, {r0, r1, r2, lr}
|
|
|
- add r0, r0, r1 // Address of the address ...
|
|
|
- mov r1, lr // New value
|
|
|
- mov r2, #0 // OldValue
|
|
|
- blx InterlockedCompareExchange
|
|
|
- ldmfd sp!, {r0, r1, r2, lr}
|
|
|
- b .LSlotLoop
|
|
|
-
|
|
|
-.LCounterBuffer:
|
|
|
- .long setjmp_counter
|
|
|
-end;
|
|
|
-
|
|
|
-procedure fpc_dump_setjmp;
|
|
|
-var cnt: LongInt;
|
|
|
-begin
|
|
|
- for cnt:=Low(setjmp_counter) to High(setjmp_counter) do
|
|
|
- begin
|
|
|
- if setjmp_counter[cnt].counter > 0 then
|
|
|
- begin
|
|
|
- writeln('Address: [$',hexstr(setjmp_counter[cnt].Address - 4,8), '] Count:',setjmp_counter[cnt].Counter);
|
|
|
- end;
|
|
|
- end;
|
|
|
-end;
|
|
|
-
|
|
|
-function fpc_setjmp_table_entry(idx: LongWord): PSetJmpCounter;
|
|
|
-begin
|
|
|
- fpc_setjmp_table_entry:=nil;
|
|
|
- if (idx < $2000) then fpc_setjmp_table_entry:=@setjmp_counter[idx];
|
|
|
-end;
|
|
|
-
|
|
|
function fpc_setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJMP'];nostackframe; compilerproc;
|
|
|
asm
|
|
|
{$if defined(FPUVFPV2) or defined(FPUVFPV3) or defined(FPUVFPV3_D16)}
|
|
@@ -138,7 +52,12 @@ function fpc_setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_S
|
|
|
bx lr
|
|
|
{$else}
|
|
|
stmia r0,{v1-v6, sl, fp, sp, lr}
|
|
|
- b fpc_count_setjmp
|
|
|
+ mov r0,#0
|
|
|
+ {$ifdef CPUARM_HAS_BX}
|
|
|
+ bx lr
|
|
|
+ {$else}
|
|
|
+ mov pc,lr
|
|
|
+ {$endif}
|
|
|
{$endif}
|
|
|
end;
|
|
|
|