From 9ed3de91a2d76885ab85d71f50d7fe82da632d83 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Tue, 16 Mar 2021 23:59:48 +0300 Subject: [PATCH] stdatomic: i386/x86_64 support --- lib/Makefile | 4 ++-- lib/atomic-gen32.c | 25 +++++++++++++++++++++++++ lib/atomic-gen64.c | 8 ++++++++ lib/atomic-i386.c | 19 +++++++++++++++++++ lib/atomic-x86.h | 31 +++++++++++++++++++++++++++++++ lib/atomic-x86_64.c | 12 ++++++++++++ lib/atomic.h | 39 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 lib/atomic-gen32.c create mode 100644 lib/atomic-gen64.c create mode 100644 lib/atomic-i386.c create mode 100644 lib/atomic-x86.h create mode 100644 lib/atomic-x86_64.c create mode 100644 lib/atomic.h diff --git a/lib/Makefile b/lib/Makefile index 9121d330..fe2fd32e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -42,8 +42,8 @@ $(X)BT_O += tcov.o DSO_O = dsohandle.o -I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) -X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) +I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) atomic-i386.o +X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) atomic-x86_64.o ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O) ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O) RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O) diff --git a/lib/atomic-gen32.c b/lib/atomic-gen32.c new file mode 100644 index 00000000..64575cd5 --- /dev/null +++ b/lib/atomic-gen32.c @@ -0,0 +1,25 @@ +#include "atomic.h" + +ATOMIC_EXCHANGE(uint8_t, 1) +ATOMIC_EXCHANGE(uint16_t, 2) +ATOMIC_EXCHANGE(uint32_t, 4) + +ATOMIC_FETCH_ADD(uint8_t, 1) +ATOMIC_FETCH_ADD(uint16_t, 2) +ATOMIC_FETCH_ADD(uint32_t, 4) + +ATOMIC_FETCH_SUB(uint8_t, 1) +ATOMIC_FETCH_SUB(uint16_t, 2) +ATOMIC_FETCH_SUB(uint32_t, 4) + +ATOMIC_FETCH_AND(uint8_t, 1) +ATOMIC_FETCH_AND(uint16_t, 2) +ATOMIC_FETCH_AND(uint32_t, 4) + +ATOMIC_FETCH_OR(uint8_t, 1) +ATOMIC_FETCH_OR(uint16_t, 2) +ATOMIC_FETCH_OR(uint32_t, 4) + +ATOMIC_FETCH_XOR(uint8_t, 1) +ATOMIC_FETCH_XOR(uint16_t, 2) +ATOMIC_FETCH_XOR(uint32_t, 4) diff --git a/lib/atomic-gen64.c b/lib/atomic-gen64.c new file mode 100644 index 00000000..edd82632 --- /dev/null +++ b/lib/atomic-gen64.c @@ -0,0 +1,8 @@ +#include "atomic.h" + +ATOMIC_EXCHANGE(uint64_t, 8) +ATOMIC_FETCH_ADD(uint64_t, 8) +ATOMIC_FETCH_SUB(uint64_t, 8) +ATOMIC_FETCH_AND(uint64_t, 8) +ATOMIC_FETCH_OR(uint64_t, 8) +ATOMIC_FETCH_XOR(uint64_t, 8) diff --git a/lib/atomic-i386.c b/lib/atomic-i386.c new file mode 100644 index 00000000..ca8b2a49 --- /dev/null +++ b/lib/atomic-i386.c @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "atomic-x86.h" + +ATOMIC_X86_STORE(uint8_t, 1) +ATOMIC_X86_STORE(uint16_t, 2) +ATOMIC_X86_STORE(uint32_t, 4) + +ATOMIC_X86_LOAD(uint8_t, 1) +ATOMIC_X86_LOAD(uint16_t, 2) +ATOMIC_X86_LOAD(uint32_t, 4) + +ATOMIC_X86_COMPARE_EXCHANGE(uint8_t, 1, "b") +ATOMIC_X86_COMPARE_EXCHANGE(uint16_t, 2, "w") +ATOMIC_X86_COMPARE_EXCHANGE(uint32_t, 4, "l") + +#include "atomic-gen32.c" diff --git a/lib/atomic-x86.h b/lib/atomic-x86.h new file mode 100644 index 00000000..ad4e1f07 --- /dev/null +++ b/lib/atomic-x86.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#define ATOMIC_X86_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \ + bool __atomic_compare_exchange_##MODE(_Atomic(TYPE) *atom, TYPE *ref, TYPE xchg) \ + { \ + TYPE rv; \ + TYPE cmp = *ref; \ + asm volatile( \ + "lock cmpxchg" SUFFIX " %2,%1\n" \ + : "=a" (rv), "+m" (*atom) \ + : "q" (xchg), "0" (cmp) \ + : "memory" \ + ); \ + *ref = rv; \ + return (rv == cmp); \ + } + +#define ATOMIC_X86_LOAD(TYPE, MODE) \ + TYPE __atomic_load_##MODE(const _Atomic(TYPE) *atom) \ + { \ + return *(volatile TYPE *)atom; \ + } + +#define ATOMIC_X86_STORE(TYPE, MODE) \ + void __atomic_store_##MODE(_Atomic(TYPE) *atom, TYPE value) \ + { \ + *(volatile TYPE *)atom = value; \ + } diff --git a/lib/atomic-x86_64.c b/lib/atomic-x86_64.c new file mode 100644 index 00000000..974615d1 --- /dev/null +++ b/lib/atomic-x86_64.c @@ -0,0 +1,12 @@ +#pragma once + +#include + +#include "atomic-x86.h" +#include "atomic-i386.c" + +ATOMIC_X86_STORE(uint64_t, 8) +ATOMIC_X86_LOAD(uint64_t, 8) +ATOMIC_X86_COMPARE_EXCHANGE(uint64_t, 8, "q") + +#include "atomic-gen64.c" diff --git a/lib/atomic.h b/lib/atomic.h new file mode 100644 index 00000000..6c9190a6 --- /dev/null +++ b/lib/atomic.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP) \ + TYPE __atomic_##NAME##_##MODE(_Atomic(TYPE) *atom, TYPE value) \ + { \ + TYPE xchg; \ + TYPE cmp = __atomic_load(atom, __ATOMIC_RELAXED); \ + do { \ + xchg = (OP); \ + } while (!__atomic_compare_exchange(atom, &cmp, xchg, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \ + return cmp; \ + } + +#ifndef ATOMIC_EXCHANGE +# define ATOMIC_EXCHANGE(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, exchange, value) +#endif + +#ifndef ATOMIC_FETCH_ADD +# define ATOMIC_FETCH_ADD(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value)) +#endif + +#ifndef ATOMIC_FETCH_SUB +# define ATOMIC_FETCH_SUB(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value)) +#endif + +#ifndef ATOMIC_FETCH_AND +# define ATOMIC_FETCH_AND(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value)) +#endif + +#ifndef ATOMIC_FETCH_OR +# define ATOMIC_FETCH_OR(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value)) +#endif + +#ifndef ATOMIC_FETCH_XOR +# define ATOMIC_FETCH_XOR(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value)) +#endif