diff --git a/components/newlib/port/CMakeLists.txt b/components/newlib/port/CMakeLists.txt index a9187d56a4..c4c37abfd0 100644 --- a/components/newlib/port/CMakeLists.txt +++ b/components/newlib/port/CMakeLists.txt @@ -1 +1,5 @@ target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/esp_time_impl.c") + +if(CONFIG_IDF_TARGET_ARCH_RISCV) + target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/riscv/port_stdatomic.S") +endif() diff --git a/components/newlib/port/riscv/port_stdatomic.S b/components/newlib/port/riscv/port_stdatomic.S new file mode 100644 index 0000000000..b43fb03db9 --- /dev/null +++ b/components/newlib/port/riscv/port_stdatomic.S @@ -0,0 +1,659 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#if __riscv_atomic == 1 + +.macro ALIGNED_PTR_2 ptr, offset + andi \ptr, a0, -4 // aligned ptr + sub \offset, a0, \ptr + slli \offset, \offset, 3 // offset (in bits) between ptr and aligned ptr + li t6, 24 + bne \offset, t6, 1f // do atomic operation in case var is not splited between 2 words + lr.w t2, (a0) // invokes 'Load access fault!' +1: +.endm + + .global __atomic_load_2 + .type __atomic_load_2, @function +__atomic_load_2: + ALIGNED_PTR_2 t0, t1 + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_load_2, . - __atomic_load_2 + + + .global __atomic_store_2 + .type __atomic_store_2, @function +__atomic_store_2: + ALIGNED_PTR_2 t0, t1 + li t6, 0xffff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + sll t5, a1, t1 // t5 - shifted new value to easy place into aligned memory +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - masked aliged memory. Atomic variable part is zeroed here + or t4, t5, t3 // t4 - combine desire half-word with half-word from origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + ret + .size __atomic_store_2, . - __atomic_store_2 + + + .global __atomic_exchange_2 + .type __atomic_exchange_2, @function +__atomic_exchange_2: + ALIGNED_PTR_2 t0, t1 + li t6, 0xffff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + sll t5, a1, t1 // t5 - shifted new value to easy place into aligned memory +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - masked aliged memory. Atomic variable part is zeroed here + or t4, t5, t3 // t4 - combine desire half-word with half-word from origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + srl t4, t2, t1 + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_exchange_2, . - __atomic_exchange_2 + + + .global __atomic_compare_exchange_2 + .type __atomic_compare_exchange_2, @function +__atomic_compare_exchange_2: + ALIGNED_PTR_2 t0, t1 + li t6, 0xffff0000 + srl t6, t6, t1 // t6 - bitwise mask (0xffff0000/0x0000ffff) + lhu t5, (a1) + sll t5, t5, t1 // t5 - shifted expect value to easy compare with aligned memory + sll t4, a2, t1 // t4 - shifted desired value to easy place into aligned memory +1: // do not change registers (t0, t1, t4, t5) after this label + not t6, t6 + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - prepare half-word from aligned memory to compare with expected (t5) + bne t3, t5, 2f + not t6, t6 + and t2, t2, t6 + or t3, t4, t2 // t3 - combine desire half-word with half-word from origin aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + li a0, 1 + ret +2: + srl t3, t3, t1 + sh t3, (a1) // store atomic value into expect variable + li a0, 0 + ret + .size __atomic_compare_exchange_2, . - __atomic_compare_exchange_2 + + + .global __atomic_fetch_or_2 + .type __atomic_fetch_or_2, @function +__atomic_fetch_or_2: + ALIGNED_PTR_2 t0, t1 + sll t2, a1, t1 // t2 - shifted value half-word. + amoor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + slli a0, t0, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_fetch_or_2, . - __atomic_fetch_or_2 + + + .global __atomic_or_fetch_2 + .type __atomic_or_fetch_2, @function +__atomic_or_fetch_2: + ALIGNED_PTR_2 t0, t1 + sll t2, a1, t1 // t2 - shifted value half-word. + amoor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + slli a0, t2, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_or_fetch_2, . - __atomic_or_fetch_2 + + + .global __atomic_fetch_xor_2 + .type __atomic_fetch_xor_2, @function +__atomic_fetch_xor_2: + ALIGNED_PTR_2 t0, t1 + sll t2, a1, t1 // t2 - shifted value half-word. + amoxor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + slli a0, t0, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_fetch_xor_2, . - __atomic_fetch_xor_2 + + + .global __atomic_xor_fetch_2 + .type __atomic_xor_fetch_2, @function +__atomic_xor_fetch_2: + ALIGNED_PTR_2 t0, t1 + sll t2, a1, t1 // t2 - shifted value half-word. + amoxor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + slli a0, t2, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_xor_fetch_2, . - __atomic_xor_fetch_2 + + + .global __atomic_fetch_and_2 + .type __atomic_fetch_and_2, @function +__atomic_fetch_and_2: + ALIGNED_PTR_2 t0, t1 + li t6, 0xffff0000 // t6 - bitwise mask + srl t6, t6, t1 // t6 - using to fill non-atomic bytes with 0xff in aligned memory + sll t2, a1, t1 // t2 - shifted value half-word. + or t2, t2, t6 // t2 - 0xXXXXffff or 0xffffXXXX where is value halfword + amoand.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + slli a0, t0, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_fetch_and_2, . - __atomic_fetch_and_2 + + + .global __atomic_and_fetch_2 + .type __atomic_and_fetch_2, @function +__atomic_and_fetch_2: + ALIGNED_PTR_2 t0, t1 + li t6, 0xffff0000 // t6 - bitwise mask + srl t6, t6, t1 // t6 - using to fill non-atomic bytes with 0xff in aligned memory + sll t2, a1, t1 // t2 - shifted value half-word. + or t2, t2, t6 // t2 - 0xXXXXffff or 0xffffXXXX where XXXX is value halfword + amoand.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + slli a0, t2, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_and_fetch_2, . - __atomic_and_fetch_2 + + + .global __atomic_fetch_nand_2 + .type __atomic_fetch_nand_2, @function +__atomic_fetch_nand_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff + sll t5, t5, t1 // t5 - bitwise mask + not t6, t5 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + and t3, t3, a1 + not t3, t3 // t3 - atomic value to write + sll t3, t3, t1 + and t4, t2, t6 // t4 - masked aliged memory. Atomic variable part is zeroed here + or t4, t4, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t4, t4, (t0) // t3 - atomic write result (0 - success) + bnez t4, 1b + srl t4, t2, t1 + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_fetch_nand_2, . - __atomic_fetch_nand_2 + + + .global __atomic_nand_fetch_2 + .type __atomic_nand_fetch_2, @function +__atomic_nand_fetch_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff + sll t5, t5, t1 // t5 - bitwise mask + not t6, t5 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + and t3, t3, a1 + not t3, t3 // t3 - atomic value to write + sll t3, t3, t1 + and t4, t2, t6 // t4 - masked aliged memory. Atomic variable part is zeroed here + or t4, t4, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t4, t4, (t0) // t3 - atomic write result (0 - success) + bnez t4, 1b + srl t4, t2, t1 + slli a0, t3, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_nand_fetch_2, . - __atomic_nand_fetch_2 + + + .global __atomic_fetch_sub_2 + .type __atomic_fetch_sub_2, @function +__atomic_fetch_sub_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff // t5 - bitwise mask + not t6, t5 + srl t6, t6, t1 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl a0, t2, t1 + and a0, a0, t5 // a0 - value in atomic before performing operation + sub t3, a0, a1 + and t3, t3, t5 // t3 - value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + ret + .size __atomic_fetch_sub_2, . - __atomic_fetch_sub_2 + + + .global __atomic_sub_fetch_2 + .type __atomic_sub_fetch_2, @function +__atomic_sub_fetch_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff // t5 - bitwise mask + not t6, t5 + srl t6, t6, t1 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + and t4, t4, t5 + sub t4, t4, a1 + and t4, t4, t5 // t4 - value to be written to atomic + sll t4, t4, t1 + and t2, t2, t6 + or t4, t4, t2 // t4 - value to be written into aligned memory + sc.w t2, t4, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + srl t4, t4, t1 + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_sub_fetch_2, . - __atomic_sub_fetch_2 + + + .global __atomic_fetch_add_2 + .type __atomic_fetch_add_2, @function +__atomic_fetch_add_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff // t5 - bitwise mask + not t6, t5 + srl t6, t6, t1 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + and t4, t4, t5 // t4 - half-word value in atomic before performing operation + add t3, t4, a1 + and t4, t4, t5 // t3 - half-word value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_fetch_add_2, . - __atomic_fetch_add_2 + + + .global __atomic_add_fetch_2 + .type __atomic_add_fetch_2, @function +__atomic_add_fetch_2: + ALIGNED_PTR_2 t0, t1 + li t5, 0xffff // t5 - bitwise mask + not t6, t5 + srl t6, t6, t1 // t6 - bitwise mask +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + and t4, t4, t5 + add t4, t4, a1 + and t4, t4, t5 // t4 - value to be written to atomic + sll t4, t4, t1 + and t2, t2, t6 + or t4, t4, t2 // t4 - value to be written into aligned memory + sc.w t2, t4, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + srl t4, t4, t1 + slli a0, t4, 0x10 + srli a0, a0, 0x10 + ret + .size __atomic_add_fetch_2, . - __atomic_add_fetch_2 + + + .global __atomic_load_1 + .type __atomic_load_1, @function +__atomic_load_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + andi a0, t4, 0xff + ret + .size __atomic_load_1, . - __atomic_load_1 + + + .global __atomic_store_1 + .type __atomic_store_1, @function +__atomic_store_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + sll t5, a1, t1 // t5 - shifted new value to easy place into aligned memory +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - masked aliged memory. Atomic variable part is zeroed here + or t4, t5, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + ret + .size __atomic_store_1, . - __atomic_store_1 + + + .global __atomic_exchange_1 + .type __atomic_exchange_1, @function +__atomic_exchange_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + sll t5, a1, t1 // t5 - shifted new value to easy place into aligned memory +1: // do not change registers (t0, t1, t5, t6) after this label + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - masked aliged memory. Atomic variable part is zeroed here + or t4, t5, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + srl t4, t2, t1 + andi a0, t4, 0xff + ret + .size __atomic_exchange_1, . - __atomic_exchange_1 + + + .global __atomic_compare_exchange_1 + .type __atomic_compare_exchange_1, @function +__atomic_compare_exchange_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask + lbu t5, (a1) + sll t5, t5, t1 // t5 - shifted expect value to easy compare with aligned memory + sll t4, a2, t1 // t4 - shifted desired value to easy place into aligned memory +1: // do not change registers (t0, t1, t4, t5) after this label + not t6, t6 + lr.w t2, (t0) // t2 - load atomic + and t3, t2, t6 // t3 - prepare half-word from aligned memory to compare with expected (t5) + bne t3, t5, 2f // goto fail + not t6, t6 + and t2, t2, t6 + or t3, t4, t2 // t3 - combine desire half-word with half-word from origin aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b // retry + li a0, 1 + ret +2: + srl t3, t3, t1 + sb t3, (a1) // store atomic value into expect variable + li a0, 0 + ret + .size __atomic_compare_exchange_1, . - __atomic_compare_exchange_1 + + + .global __atomic_fetch_or_1 + .type __atomic_fetch_or_1, @function +__atomic_fetch_or_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + sll t2, a1, t1 // t2 - shifted value half-word. + amoor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + andi a0, t0, 0xff + ret + .size __atomic_fetch_or_1, . - __atomic_fetch_or_1 + + + .global __atomic_or_fetch_1 + .type __atomic_or_fetch_1, @function +__atomic_or_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + sll t2, a1, t1 // t2 - shifted byte-word value. + amoor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + andi a0, t2, 0xff + ret + .size __atomic_or_fetch_1, . - __atomic_or_fetch_1 + + + .global __atomic_fetch_xor_1 + .type __atomic_fetch_xor_1, @function +__atomic_fetch_xor_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + sll t2, a1, t1 // t2 - shifted value byte-word. + amoxor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + andi a0, t0, 0xff + ret + .size __atomic_fetch_xor_1, . - __atomic_fetch_xor_1 + + + .global __atomic_xor_fetch_1 + .type __atomic_xor_fetch_1, @function +__atomic_xor_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + sll t2, a1, t1 // t2 - shifted value byte-word. + amoxor.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + andi a0, t2, 0xff + ret + .size __atomic_xor_fetch_1, . - __atomic_xor_fetch_1 + + + .global __atomic_fetch_and_1 + .type __atomic_fetch_and_1, @function +__atomic_fetch_and_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 + li t6, 0xff // t6 - bitwise mask + sll t6, t6, t1 // t6 - using to fill non-atomic bytes with 0xff in aligned memory + not t6, t6 + sll t2, a1, t1 // t2 - shifted value byte-word. + or t2, t2, t6 // t2 - (0xXXffffff or 0xffXXffff ...) where XX - new value to write + amoand.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t0, t0, t1 + andi a0, t0, 0xff + ret + .size __atomic_fetch_and_1, . - __atomic_fetch_and_1 + + + .global __atomic_and_fetch_1 + .type __atomic_and_fetch_1, @function +__atomic_and_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 + li t6, 0xff // t6 - bitwise mask + sll t6, t6, t1 // t6 - using to fill non-atomic bytes with 0xff in aligned memory + not t6, t6 + sll t2, a1, t1 // t2 - shifted value byte-word. + or t2, t2, t6 // t2 - (0xXXffffff or 0xffXXffff ...) where XX - new value to write + amoand.w t0, t2, (t0) // t0 - shifted value before atomic operation performed + srl t2, t2, t1 + andi a0, t2, 0xff + ret + .size __atomic_and_fetch_1, . - __atomic_and_fetch_1 + + + .global __atomic_nand_fetch_1 + .type __atomic_nand_fetch_1, @function +__atomic_nand_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + and t3, t3, a1 + not t3, t3 // t3 - atomic value to write + sll t3, t3, t1 + and t4, t2, t6 // t4 - masked aliged memory. Atomic variable part is zeroed here + or t4, t4, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + srl t4, t4, t1 + andi a0, t4, 0xff + ret + .size __atomic_nand_fetch_1, . - __atomic_nand_fetch_1 + + + .global __atomic_fetch_nand_1 + .type __atomic_fetch_nand_1, @function +__atomic_fetch_nand_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + and t3, t3, a1 + not t3, t3 // t3 - atomic value to write + sll t3, t3, t1 + and t4, t2, t6 // t4 - masked aliged memory. Atomic variable part is zeroed here + or t4, t4, t3 // t4 - combine desire byte-word with origin aligned memory + sc.w t3, t4, (t0) // t3 - atomic write result (0 - success) + bnez t3, 1b + srl t4, t2, t1 + andi a0, t4, 0xff + ret + .size __atomic_fetch_nand_1, . - __atomic_fetch_nand_1 + + + .global __atomic_fetch_sub_1 + .type __atomic_fetch_sub_1, @function +__atomic_fetch_sub_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + andi t4, t4, 0xff // t4 - value in atomic before performing operation + sub t3, t4, a1 + andi t3, t3, 0xff // t3 - value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + andi a0, t4, 0xff + ret + .size __atomic_fetch_sub_1, . - __atomic_fetch_sub_1 + + + .global __atomic_sub_fetch_1 + .type __atomic_sub_fetch_1, @function +__atomic_sub_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + andi t3, t3, 0xff // t3 - value in atomic before performing operation + sub t3, t3, a1 + andi t3, t3, 0xff // t3 - value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + srl t3, t3, t1 + andi a0, t3, 0xff + ret + .size __atomic_sub_fetch_1, . - __atomic_sub_fetch_1 + + + .global __atomic_fetch_add_1 + .type __atomic_fetch_add_1, @function +__atomic_fetch_add_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t4, t2, t1 + andi t4, t4, 0xff // t4 - value in atomic before performing operation + add t3, t4, a1 + andi t3, t3, 0xff // t3 - value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + andi a0, t4, 0xff + ret + .size __atomic_fetch_add_1, . - __atomic_fetch_add_1 + + + .global __atomic_add_fetch_1 + .type __atomic_add_fetch_1, @function +__atomic_add_fetch_1: + andi t0, a0, -4 // t0 - aligned ptr + sub t1, a0, t0 + slli t1, t1, 3 // t1 - offset (in bits) between ptr and aligned ptr + li t6, 0xff + sll t6, t6, t1 + not t6, t6 // t6 - bitwise mask +1: // do not change registers (t0, t1, t6) after this label + lr.w t2, (t0) // t2 - load atomic + srl t3, t2, t1 + andi t3, t3, 0xff // t3 - value in atomic before performing operation + add t3, t3, a1 + andi t3, t3, 0xff // t3 - value to be written to atomic + sll t3, t3, t1 + and t2, t2, t6 + or t3, t3, t2 // t3 - value to be written into aligned memory + sc.w t2, t3, (t0) // t2 - atomic write result (0 - success) + bnez t2, 1b + srl t3, t3, t1 + andi a0, t3, 0xff + ret + .size __atomic_add_fetch_1, . - __atomic_add_fetch_1 + +#endif // if __riscv_atomic == 1 diff --git a/components/newlib/stdatomic.c b/components/newlib/stdatomic.c index 54de84e6d2..ae52f83ed5 100644 --- a/components/newlib/stdatomic.c +++ b/components/newlib/stdatomic.c @@ -434,6 +434,18 @@ ATOMIC_STORE(1, unsigned char) ATOMIC_STORE(2, short unsigned int) ATOMIC_STORE(4, unsigned int) +#elif __riscv_atomic == 1 + +bool CLANG_ATOMIC_SUFFIX(__atomic_always_lock_free) (unsigned int size, const volatile void *) { + return size <= sizeof(int); +} +CLANG_DECLARE_ALIAS( __atomic_always_lock_free) + +bool CLANG_ATOMIC_SUFFIX(__atomic_is_lock_free) (unsigned int size, const volatile void *) { + return size <= sizeof(int); +} +CLANG_DECLARE_ALIAS( __atomic_is_lock_free) + #endif // !HAS_ATOMICS_32 #if !HAS_ATOMICS_64