diff options
author | Ayke van Laethem <[email protected]> | 2021-09-28 00:14:14 +0200 |
---|---|---|
committer | Ayke van Laethem <[email protected]> | 2021-09-28 00:21:12 +0200 |
commit | 4ddb10751abaf2f2dbbd8632b46377ec564d5b36 (patch) | |
tree | 2c5bad7eee07d947840ff757ea34759b1ed09ce4 | |
parent | 95c2fbaf5a7f156e6dc0b8aefa4ed0aa6e6e5099 (diff) | |
download | tinygo-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.go | 47 |
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() |