mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 12:07:58 +02:00
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 -
This commit is contained in:
parent
7b6bcd315f
commit
f252fd369e
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
123
rtl/arm/arm.inc
123
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
rtl/arm/armdefines.inc
Normal file
35
rtl/arm/armdefines.inc
Normal file
@ -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}
|
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user