summary refs log tree commit diff stats
path: root/lib/system/atomics.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/atomics.nim')
-rw-r--r--lib/system/atomics.nim47
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 158fe91bc..a79dcb152 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -197,6 +197,51 @@ when defined(windows) and not someGcc:
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
     interlockedCompareExchange(p, cast[int](newValue), cast[int](oldValue)) != 0
   # XXX fix for 64 bit build
+elif defined(tcc) and not defined(windows):
+  when defined(amd64):
+    {.emit:"""
+static int __tcc_cas(int *ptr, int oldVal, int newVal)
+{
+    unsigned char ret;
+    __asm__ __volatile__ (
+            "  lock\n"
+            "  cmpxchgq %2,%1\n"
+            "  sete %0\n"
+            : "=q" (ret), "=m" (*ptr)
+            : "r" (newVal), "m" (*ptr), "a" (oldVal)
+            : "memory");
+
+    if (ret)
+      return 0;
+    else
+      return 1;
+}
+""".}
+  else:
+    assert sizeof(int) == 4
+    {.emit:"""
+static int __tcc_cas(int *ptr, int oldVal, int newVal)
+{
+    unsigned char ret;
+    __asm__ __volatile__ (
+            "  lock\n"
+            "  cmpxchgl %2,%1\n"
+            "  sete %0\n"
+            : "=q" (ret), "=m" (*ptr)
+            : "r" (newVal), "m" (*ptr), "a" (oldVal)
+            : "memory");
+
+    if (ret)
+      return 0;
+    else
+      return 1;
+}
+""".}
+    
+  proc tcc_cas(p: ptr int; oldValue, newValue: int): bool
+    {.importc: "__tcc_cas", nodecl.}
+  proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
+    tcc_cas(cast[ptr int](p), cast[int](oldValue), cast[int](newValue))
 else:
   # this is valid for GCC and Intel C++
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool
@@ -207,7 +252,7 @@ else:
 when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax* {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
-elif someGcc:
+elif someGcc or defined(tcc):
   proc cpuRelax* {.inline.} =
     {.emit: """asm volatile("" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):