浏览代码

Tried to reorganize the ARM define mess in rtl/arm/arm.inc. Instead of requiring to enumerate all possible ARM variants each time a CPU feature is used, add a define of the format CPUARM_HAS_XXX and use that. Note that a better solution would be to properly implement the compiler cpuinfo infrastructure, however that is much more work.

  + CPUARM_HAS_BX is defined if the CPU supports the BX* instruction
  + CPUARM_HAS_REV is defined if the CPU supports the REV instruction. Note that you still have to check for compiler versions > 2.6.0 since the assembler reader of 2.6.0 does not understand that instruction.
  + CPUARM_HAS_IDIV is defined if the CPU supports the sdiv, udiv instructions. Use of this fixes a bug where previously these instruction were only used for armv7-m, while cortex3m cpus also support it.
  + CPUARM_HAS_LDREX is defined if the CPU supports the ldrex/strex instructions. Use of this fixes a bug with armv7(-a) cpus where this path has not been used.
  + SYSTEM_HAS_KUSER_CMPXCHG is defined if the system (mainly OS) support the kuser_cmpxchg functions. Use of this fixes a bug where ARMHF systems did not use it for synchronization (although ARMHF is armv7+ only, i.e. the LDREX path is used anyway)

git-svn-id: trunk@22081 -
tom_at_work 13 年之前
父节点
当前提交
f252fd369e
共有 6 个文件被更改,包括 110 次插入71 次删除
  1. 1 0
      .gitattributes
  2. 62 61
      rtl/arm/arm.inc
  3. 35 0
      rtl/arm/armdefines.inc
  4. 10 10
      rtl/arm/divide.inc
  5. 1 0
      rtl/inc/system.inc
  6. 1 0
      rtl/java/jsystem.inc

+ 1 - 0
.gitattributes

@@ -7223,6 +7223,7 @@ rtl/android/jvm/java_sys_android.inc svneol=native#text/plain
 rtl/android/jvm/java_sysh_android.inc svneol=native#text/plain
 rtl/android/jvm/rtl.cfg svneol=native#text/plain
 rtl/arm/arm.inc svneol=native#text/plain
+rtl/arm/armdefines.inc svneol=native#text/plain
 rtl/arm/divide.inc svneol=native#text/plain
 rtl/arm/int64p.inc svneol=native#text/plain
 rtl/arm/makefile.cpu svneol=native#text/plain

+ 62 - 61
rtl/arm/arm.inc

@@ -146,10 +146,10 @@ Procedure FillChar(var x;count:longint;value:byte);assembler;nostackframe;
 asm
         // less than 0?
         cmp     r1,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-        movle   pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
         bxle    lr
+{$else}
+        movle   pc,lr
 {$endif}
         mov     r3,r0
 
@@ -177,10 +177,10 @@ asm
         // Do the rest
         adds    r1, r1, #8
 
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-        moveq   pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
         bxeq    lr
+{$else}
+        moveq   pc,lr
 {$endif}
 
         tst     r1, #4
@@ -189,10 +189,10 @@ asm
         strneh  r2,[r3],#2
         tst     r1, #1
         strneb  r2,[r3],#1
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-        mov pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
         bx  lr
+{$else}
+        mov pc,lr
 {$endif}
 
 // Special case for unaligned start
@@ -200,10 +200,10 @@ asm
 .LFillchar_do_align:
         strb r2,[r3],#1
         subs r1, r1, #1
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-        moveq pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
         bxeq  lr
+{$else}
+        moveq pc,lr
 {$endif}
         tst r3,#3
         bne .LFillchar_do_align
@@ -218,10 +218,10 @@ asm
   pld [r0]
   // count <=0 ?
   cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  movle pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxle  lr
+{$else}
+  movle pc,lr
 {$endif}
   // overlap?
   subs   r3, r1, r0    // if (dest > source) and
@@ -245,20 +245,20 @@ asm
   stmia r1!, {r3, ip}
   bge   .Ldwordloop
   cmp   r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  moveq pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxeq  lr
+{$else}
+  moveq pc,lr
 {$endif}
 .Lbyteloop:
   subs r2,r2,#1
   ldrb r3,[r0],#1
   strb r3,[r1],#1
   bne .Lbyteloop
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  mov pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bx  lr
+{$else}
+  mov pc,lr
 {$endif}
 .Loverlapped:
   subs r2,r2,#1
@@ -271,10 +271,10 @@ procedure Move_blended(const source;var dest;count:longint);assembler;nostackfra
 asm
   // count <=0 ?
   cmp r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  movle pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxle  lr
+{$else}
+  movle pc,lr
 {$endif}
   // overlap?
   subs   r3, r1, r0    // if (dest > source) and
@@ -295,20 +295,20 @@ asm
   stmia r1!, {r3, ip}
   bge   .Ldwordloop
   cmp   r2,#0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  moveq pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxeq  lr
+{$else}
+  moveq pc,lr
 {$endif}
 .Lbyteloop:
   subs r2,r2,#1
   ldrb r3,[r0],#1
   strb r3,[r1],#1
   bne .Lbyteloop
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  mov pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bx  lr
+{$else}
+  mov pc,lr
 {$endif}
 .Loverlapped:
   subs r2,r2,#1
@@ -488,10 +488,10 @@ asm
       terminating 0, due to the known carry flag sbc can do this.*)
     sbc r0,r1,r0
 .Ldone:
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-    mov pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
     bx  lr
+{$else}
+    mov pc,lr
 {$endif}
 .L01010101:
     .long 0x01010101
@@ -513,17 +513,17 @@ asm
   cmp     r1, #0
   // Load reference counter
   ldrne   r2, [r1, #-8]
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  moveq   pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxeq    lr
+{$else}
+  moveq   pc,lr
 {$endif}
   // Check for a constant string
   cmp     r2, #0
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  movlt   pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxlt    lr
+{$else}
+  movlt   pc,lr
 {$endif}
   stmfd   sp!, {r1, lr}
   sub     r0, r1, #8
@@ -544,7 +544,7 @@ var
 
 function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
 asm
-{$if defined(cpuarmv6) or defined(cpuarmv7m) or defined(cpucortexm3)}
+{$ifdef CPUARM_HAS_LDREX}
 .Lloop:
   ldrex r1, [r0]
   sub   r1, r1, #1
@@ -554,7 +554,7 @@ asm
   movs r0, r1
   bx  lr
 {$else}
-{$if defined(LINUX) and defined(CPUARMEL)}
+{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
   stmfd r13!, {lr}
   mov r2, r0   // kuser_cmpxchg does not clobber r2 by definition
 .Latomic_dec_loop:
@@ -613,10 +613,10 @@ asm
   ldrne   r1, [r0, #-8]
   // pointer to counter, calculate here for delay slot utilization
   subne   r0, r0, #8
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  moveq   pc,lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bxeq    lr
+{$else}
+  moveq   pc,lr
 {$endif}
   // Check for a constant string
   cmp     r1, #0
@@ -628,7 +628,7 @@ end;
 
 function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
 asm
-{$if defined(cpuarmv6) or defined(cpuarmv7m) or defined(cpucortexm3)}
+{$ifdef CPUARM_HAS_LDREX}
 .Lloop:
   ldrex r1, [r0]
   add   r1, r1, #1
@@ -638,7 +638,7 @@ asm
   mov r0, r1
   bx  lr
 {$else}
-{$if defined(LINUX) and defined(CPUARMEL)}
+{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
   stmfd r13!, {lr}
   mov r2, r0   // kuser_cmpxchg does not clobber r2 by definition
 .Latomic_inc_loop:
@@ -688,7 +688,7 @@ end;
 
 function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
 asm
-{$if defined(cpuarmv6) or defined(cpuarmv7m) or defined(cpucortexm3)}
+{$ifdef CPUARM_HAS_LDREX}
 // swp is deprecated on ARMv6 and above
 .Lloop:
   ldrex r2, [r0]
@@ -698,7 +698,7 @@ asm
   mov r0, r2
   bx  lr
 {$else}
-{$if defined(LINUX) and defined(CPUARMEL)}
+{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
   stmfd r13!, {r4, lr}
   mov r2, r0   // kuser_cmpxchg does not clobber r2 (and r1) by definition
 .Latomic_add_loop:
@@ -747,7 +747,7 @@ end;
 
 function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
 asm
-{$if defined(cpuarmv6) or defined(cpuarmv7m) or defined(cpucortexm3)}
+{$ifdef CPUARM_HAS_LDREX}
 .Lloop:
   ldrex r2, [r0]
   add   r12, r1, r2
@@ -757,7 +757,7 @@ asm
   mov  r0, r2
   bx  lr
 {$else}
-{$if defined(LINUX) and defined(CPUARMEL)}
+{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
   stmfd r13!, {r4, lr}
   mov r2, r0   // kuser_cmpxchg does not clobber r2 by definition
   mov r4, r1   // Save addend
@@ -812,7 +812,7 @@ end;
 
 function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
 asm
-{$if defined(cpuarmv6) or defined(cpuarmv7m) or defined(cpucortexm3)}
+{$ifdef CPUARM_HAS_LDREX}
 .Lloop:
   ldrex    r3, [r0]
   mov      r12, #0
@@ -823,7 +823,7 @@ asm
   mov      r0, r3
   bx       lr
 {$else}
-{$if defined(LINUX) and defined(CPUARMEL)}
+{$ifdef SYSTEM_HAS_KUSER_CMPXCHG}
   stmfd r13!, {r4, lr}
   mvn   r3, #0x0000f000
   sub   r3, r3, #0x3F
@@ -928,13 +928,13 @@ is bigger than the gain of the optimized function.
 function AsmSwapEndian(const AValue: SmallInt): SmallInt;{$ifdef SYSTEMINLINE}inline;{$endif};assembler;nostackframe;
 asm
 	// We're starting with 4321
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(VER2_6)}
+{$if defined(CPUARM_HAS_REV) and (FPC_FULLVERSION > 20600)}
+	rev r0, r0		// Reverse byteorder    r0 = 1234
+	mov r0, r0, shr #16	// Shift down to 16bits r0 = 0012
+{$else}
 	mov r0, r0, shl #16	// Shift to make that 2100
 	mov r0, r0, ror #24	// Rotate to 1002
 	orr r0, r0, r0 shr #16  // Shift and combine into 0012
-{$else}
-	rev r0, r0		// Reverse byteorder    r0 = 1234
-	mov r0, r0, shr #16	// Shift down to 16bits r0 = 0012
 {$endif}
 end;
 
@@ -966,7 +966,12 @@ end;
 
 function SwapEndian(const AValue: Int64): Int64; assembler; nostackframe;
 asm
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(VER2_6)}
+// fpc >2.6.0 adds the "rev" instruction in the internal assembler
+{$if defined(CPUARM_HAS_REV) and (FPC_FULLVERSION > 20600)}
+        rev r2, r0
+        rev r0, r1
+        mov r1, r2
+{$else}
         mov ip, r1
 
         // We're starting with r0 = $87654321
@@ -980,10 +985,6 @@ asm
         mov ip, ip, ror #8
         eor r0, ip, r0, lsr #8
 
-{$else}
-        rev r2, r0
-        rev r0, r1
-        mov r1, r2
 {$endif}
 end;
 

+ 35 - 0
rtl/arm/armdefines.inc

@@ -0,0 +1,35 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by the Free Pascal development team.
+
+    Processor dependent defines for the ARM runtime library.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$if not defined(cpuarmv3) and not defined(cpuarmv4)}
+{$define CPUARM_HAS_BX} // cpu has BX instruction
+{$endif}
+
+{$if not defined(CPUARMV3) and not defined(CPUARMV4) and not defined(CPUARMV5)}
+{$define CPUARM_HAS_REV} // cpu has REV instruction
+{$endif}
+
+{$if defined(CPUARMV7M) or defined(CPUARMCORTEXM3)}
+{$define CPUARM_HAS_IDIV} // cpu has SDIV/UDIV instructions
+{$endif}
+
+{$if defined(CPUARMV6) or defined(CPUARMV7) or defined(CPUARMV7M) or defined(CPUARMCORTEXM3)}
+{$define CPUARM_HAS_LDREX} // cpu has LDREX/STREX instructions
+{$endif}
+
+{$if defined(LINUX) and (defined(CPUARMEL) or defined(CPUARMHF))}
+{$define SYSTEM_HAS_KUSER_CMPXCHG} // system has kuser_cmpxchg method
+{$endif}

+ 10 - 10
rtl/arm/divide.inc

@@ -41,7 +41,7 @@
 function fpc_div_dword(n,z:dword):dword;[public,alias: 'FPC_DIV_DWORD'];assembler;nostackframe;
 
 asm
-{$if defined(CPUARMV7M)}
+{$ifdef CPUARM_HAS_IDIV}
   udiv r0, r0, r1
 {$else}
   mov r3, #0
@@ -96,19 +96,19 @@ asm
 .Ldiv_next:
   bcs .Ldiv_loop
   mov r0, r3
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  mov pc, lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bx  lr
+{$else}
+  mov pc, lr
 {$endif}
 .Ldiv_by_0:
   mov r0, #200
   mov r1, r11
   bl handleerrorframe
-{$if defined(cpuarmv3) or defined(cpuarmv4)}
-  mov pc, lr
-{$else}
+{$ifdef CPUARM_HAS_BX}
   bx  lr
+{$else}
+  mov pc, lr
 {$endif}
 {$endif}
 end;
@@ -122,7 +122,7 @@ function fpc_div_dword(n,z:dword):dword;external name 'FPC_DIV_DWORD';
 function fpc_div_longint(n,z:longint):longint;[public,alias: 'FPC_DIV_LONGINT'];assembler;nostackframe;
 
 asm
-{$if defined(CPUARMV7M)}
+{$ifdef CPUARM_HAS_IDIV}
   sdiv r0, r0, r1
 {$else}
   stmfd sp!, {lr}
@@ -147,7 +147,7 @@ function fpc_div_longint(n,z:longint):longint;external name 'FPC_DIV_LONGINT';
 function fpc_mod_dword(n,z:dword):dword;[public,alias: 'FPC_MOD_DWORD'];assembler;nostackframe;
 
 asm
-{$if defined(CPUARMV7M)}
+{$ifdef CPUARM_HAS_IDIV}
   udiv r2, r0, r1
   mul r2,r1,r2
   sub r0,r0,r2
@@ -168,7 +168,7 @@ function fpc_mod_dword(n,z:dword):dword;external name 'FPC_MOD_DWORD';
 function fpc_mod_longint(n,z:longint):longint;[public,alias: 'FPC_MOD_LONGINT'];assembler;nostackframe;
 
 asm
-{$if defined(CPUARMV7M)}
+{$ifdef CPUARM_HAS_IDIV}
   sdiv r2, r0, r1
   smull r2,r3,r1,r2
   sub r0,r0,r2

+ 1 - 0
rtl/inc/system.inc

@@ -217,6 +217,7 @@ function do_isdevice(handle:thandle):boolean;forward;
   {$ifdef SYSPROCDEFINED}
     {$Error Can't determine processor type !}
   {$endif}
+  {$i armdefines.inc}
   {$if defined(CPUCORTEXM3) or defined(CPUARMV7M)}
     {$i thumb2.inc}  { Case dependent, don't change }
   {$else}

+ 1 - 0
rtl/java/jsystem.inc

@@ -223,6 +223,7 @@ function do_isdevice(handle:thandle):boolean;forward;
   {$ifdef SYSPROCDEFINED}
     {$Error Can't determine processor type !}
   {$endif}
+  {$i armdefines.inc}
   {$if defined(CPUCORTEXM3) or defined(CPUARMV7M)}
     {$i thumb2.inc}  { Case dependent, don't change }
   {$else}