Browse Source

Assembly version of fpc_ansistr_decr_ref for ARM

As fpc_ansistr_decr_ref is a very often called procedure in typical
pascal programs this optimized version will shave off some cycles
compared to the generic one.

It tries to avoid load latencies as much as possible and also uses the
new Z-flag functionality of the InterlockedDecrement from the previous
patch. Also FreeMem is called as a tail-function.

git-svn-id: trunk@22034 -
masta 13 years ago
parent
commit
b9770519f8
1 changed files with 44 additions and 0 deletions
  1. 44 0
      rtl/arm/arm.inc

+ 44 - 0
rtl/arm/arm.inc

@@ -499,6 +499,50 @@ end;
 {$endif}
 {$endif}
 
 
 
 
+{$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
+function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
+
+Procedure fpc_ansistr_decr_ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF'];assembler;nostackframe; compilerproc;
+asm
+  ldr     r1, [r0]
+  // On return the pointer will always be set to zero, so utilize the delay slots
+  mov     r2, #0
+  str     r2, [r0]
+
+  // Check for a zero string
+  cmp     r1, #0
+  // Load reference counter
+  ldrne   r2, [r1, #-8]
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+  moveq   pc,lr
+{$else}
+  bxeq    lr
+{$endif}
+  // Check for a constant string
+  cmp     r2, #0
+{$if defined(cpuarmv3) or defined(cpuarmv4)}
+  movlt   pc,lr
+{$else}
+  bxlt    lr
+{$endif}
+  stmfd   sp!, {r1, lr}
+  sub     r0, r1, #8
+  blx     InterLockedDecrement
+  // InterLockedDecrement is a nice guy and sets the z flag for us
+  // if the reference count dropped to 0
+  ldmnefd sp!, {r1, pc}
+  ldmfd sp!, {r0, lr}
+  // We currently can not use constant symbols in ARM-Assembly
+  // but we need to stay backward compatible with 2.6
+{$if defined(VER2_6)}
+  sub     r0, r0, #8 //AnsiFirstOff in 2.6
+{$else}
+  sub     r0, r0, #12 //AnsiFirstOff in 2.7 with codepage support
+{$endif}
+  // Jump without a link, so freemem directly returns to our caller
+  b       FPC_FREEMEM_X
+end;
+
 var
 var
   fpc_system_lock: longint; export name 'fpc_system_lock';
   fpc_system_lock: longint; export name 'fpc_system_lock';