aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-09-28 00:14:14 +0200
committerAyke van Laethem <[email protected]>2021-09-28 00:21:12 +0200
commit4ddb10751abaf2f2dbbd8632b46377ec564d5b36 (patch)
tree2c5bad7eee07d947840ff757ea34759b1ed09ce4
parent95c2fbaf5a7f156e6dc0b8aefa4ed0aa6e6e5099 (diff)
downloadtinygo-4ddb10751abaf2f2dbbd8632b46377ec564d5b36.tar.gz
tinygo-4ddb10751abaf2f2dbbd8632b46377ec564d5b36.zip
riscv: implement 32-bit atomic operations
This is necessary to support the ESP32-C3, which lacks the A (atomic) extension and thus requires these 32-bit atomic operations. With this commit, flashing ./testdata/atomic.go to the ESP32-C3 works correctly and produces the expected output on the serial console.
-rw-r--r--src/runtime/arch_tinygoriscv.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/runtime/arch_tinygoriscv.go b/src/runtime/arch_tinygoriscv.go
index 3dcbcec25..d7b0fee29 100644
--- a/src/runtime/arch_tinygoriscv.go
+++ b/src/runtime/arch_tinygoriscv.go
@@ -18,6 +18,53 @@ func getCurrentStackPointer() uintptr {
// supported RISC-V chips have a single hart, we can simply disable interrupts
// to get the same behavior.
+//export __atomic_load_4
+func __atomic_load_4(ptr *uint32, ordering int32) uint32 {
+ mask := riscv.DisableInterrupts()
+ value := *ptr
+ riscv.EnableInterrupts(mask)
+ return value
+}
+
+//export __atomic_store_4
+func __atomic_store_4(ptr *uint32, value uint32, ordering int32) {
+ mask := riscv.DisableInterrupts()
+ *ptr = value
+ riscv.EnableInterrupts(mask)
+}
+
+//export __atomic_exchange_4
+func __atomic_exchange_4(ptr *uint32, value uint32, ordering int32) uint32 {
+ mask := riscv.DisableInterrupts()
+ oldValue := *ptr
+ *ptr = value
+ riscv.EnableInterrupts(mask)
+ return oldValue
+}
+
+//export __atomic_compare_exchange_4
+func __atomic_compare_exchange_4(ptr, expected *uint32, desired uint32, success_ordering, failure_ordering int32) bool {
+ mask := riscv.DisableInterrupts()
+ oldValue := *ptr
+ success := oldValue == *expected
+ if success {
+ *ptr = desired
+ } else {
+ *expected = oldValue
+ }
+ riscv.EnableInterrupts(mask)
+ return success
+}
+
+//export __atomic_fetch_add_4
+func __atomic_fetch_add_4(ptr *uint32, value uint32, ordering int32) uint32 {
+ mask := riscv.DisableInterrupts()
+ oldValue := *ptr
+ *ptr = oldValue + value
+ riscv.EnableInterrupts(mask)
+ return oldValue
+}
+
//export __atomic_load_8
func __atomic_load_8(ptr *uint64, ordering int32) uint64 {
mask := riscv.DisableInterrupts()