summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryury <yury@3ad0048d-3df7-0310-abae-a5850022a9f2>2006-06-30 15:36:49 +0000
committeryury <yury@3ad0048d-3df7-0310-abae-a5850022a9f2>2006-06-30 15:36:49 +0000
commitd8ef0df89b78ebd0cf34ae7c92ce5a6c037235b8 (patch)
tree0e639083d6fe28c867f08deb785c0f58a023063c
parent9940412a2ae2beb2fd63f197d8f5ecd429839c5a (diff)
downloadfpc-d8ef0df89b78ebd0cf34ae7c92ce5a6c037235b8.tar.gz
* Assembler Interlocked* functions for ARM.
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@4011 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--rtl/arm/arm.inc120
1 files changed, 92 insertions, 28 deletions
diff --git a/rtl/arm/arm.inc b/rtl/arm/arm.inc
index 2dd8cbb613..0ecb5e8b22 100644
--- a/rtl/arm/arm.inc
+++ b/rtl/arm/arm.inc
@@ -182,39 +182,103 @@ asm
end;
*)
+var
+ fpc_system_lock: longint; export name 'fpc_system_lock';
-{ the ARM doesn't know multiprocessor system which would require locking }
+function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
+asm
+// lock
+ ldr r3, .Lfpc_system_lock
+ mov r1, #1
+.Lloop:
+ swp r2, r1, [r3]
+ cmp r2, #0
+ bne .Lloop
+// do the job
+ ldr r1, [r0]
+ sub r1, r1, #1
+ str r1, [r0]
+ mov r0, r1
+// unlock and return
+ str r2, [r3]
+ mov pc, lr
+
+.Lfpc_system_lock:
+ .long fpc_system_lock
+end;
-function InterLockedDecrement (var Target: longint) : longint;
- begin
- dec(Target);
- result:=target;
- end;
+function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
+asm
+// lock
+ ldr r3, .Lfpc_system_lock
+ mov r1, #1
+.Lloop:
+ swp r2, r1, [r3]
+ cmp r2, #0
+ bne .Lloop
+// do the job
+ ldr r1, [r0]
+ add r1, r1, #1
+ str r1, [r0]
+ mov r0, r1
+// unlock and return
+ str r2, [r3]
+ mov pc, lr
+
+.Lfpc_system_lock:
+ .long fpc_system_lock
+end;
-function InterLockedIncrement (var Target: longint) : longint;
- begin
- inc(Target);
- result:=target;
- end;
+function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+asm
+ swp r0, r1, [r0]
+end;
-function InterLockedExchange (var Target: longint;Source : longint) : longint;
- begin
- Result:=Target;
- Target:=Source;
- end;
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+asm
+// lock
+ ldr r3, .Lfpc_system_lock
+ mov r2, #1
+.Lloop:
+ swp r2, r2, [r3]
+ cmp r2, #0
+ bne .Lloop
+// do the job
+ ldr r2, [r0]
+ add r1, r1, r2
+ str r1, [r0]
+ mov r0, r2
+// unlock and return
+ mov r2, #0
+ str r2, [r3]
+ mov pc, lr
+
+.Lfpc_system_lock:
+ .long fpc_system_lock
+end;
-function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
- begin
- Result:=Target;
- inc(Target,Source);
- end;
-
-function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
- begin
- Result:=Target; //return initial value
- if (Target=Comperand)
- then Target:=NewValue;
- end;
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
+asm
+// lock
+ ldr r12, .Lfpc_system_lock
+ mov r3, #1
+.Lloop:
+ swp r3, r3, [r12]
+ cmp r3, #0
+ bne .Lloop
+// do the job
+ ldr r3, [r0]
+ cmp r3, r2
+ streq r1, [r0]
+ mov r0, r3
+// unlock and return
+ mov r3, #0
+ str r3, [r12]
+ mov pc, lr
+
+.Lfpc_system_lock:
+ .long fpc_system_lock
+end;