From f252fd369e08ab96641e720dc5051402eab1cb70 Mon Sep 17 00:00:00 2001 From: tom_at_work Date: Tue, 14 Aug 2012 19:45:03 +0000 Subject: [PATCH] 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 - --- .gitattributes | 1 + rtl/arm/arm.inc | 123 +++++++++++++++++++++-------------------- rtl/arm/armdefines.inc | 35 ++++++++++++ rtl/arm/divide.inc | 20 +++---- rtl/inc/system.inc | 1 + rtl/java/jsystem.inc | 1 + 6 files changed, 110 insertions(+), 71 deletions(-) create mode 100644 rtl/arm/armdefines.inc diff --git a/.gitattributes b/.gitattributes index b911f56893..7343b59d9b 100644 --- a/.gitattributes +++ b/.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 diff --git a/rtl/arm/arm.inc b/rtl/arm/arm.inc index 70f4196b0f..561eff3ffb 100644 --- a/rtl/arm/arm.inc +++ b/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; diff --git a/rtl/arm/armdefines.inc b/rtl/arm/armdefines.inc new file mode 100644 index 0000000000..22808908ff --- /dev/null +++ b/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} diff --git a/rtl/arm/divide.inc b/rtl/arm/divide.inc index 42dfe7dd58..95edd28e92 100644 --- a/rtl/arm/divide.inc +++ b/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 diff --git a/rtl/inc/system.inc b/rtl/inc/system.inc index d1fd0f0628..b53d92cf51 100644 --- a/rtl/inc/system.inc +++ b/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} diff --git a/rtl/java/jsystem.inc b/rtl/java/jsystem.inc index c7fe79f666..a2b9aa4e9c 100644 --- a/rtl/java/jsystem.inc +++ b/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}