diff options
Diffstat (limited to 'zap/src/mem/foreach.S')
-rw-r--r-- | zap/src/mem/foreach.S | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/zap/src/mem/foreach.S b/zap/src/mem/foreach.S new file mode 100644 index 0000000..fe96538 --- /dev/null +++ b/zap/src/mem/foreach.S @@ -0,0 +1,71 @@ +/* + Copyright 2022 Gabriel Jensen. + This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. +*/ + +#include <zap/priv.h> + +.globl zap_foreach + +zap_foreach: + + /* + void * ptr + zap_sz sz + zap_sz num + void (* fn)(void *) + */ + +#if defined(__amd64__) + + # rbx: Address of the current element. + # r12: Address of the element after the last input element. + # r13: Size of each input element. + # r14: Address of the function. + + # We're gonna use callee-saved registers for storing values so they don't get overwritten with each function call. + + # Push the callee-saved registers: + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + + # Move registers into place: + movq %rdi,%rbx + movq %rsi,%r13 + movq %rcx,%r14 + + # Get the one-past-the-end address: + movq %rdx,%r12 + imulq %r13,%r12 # Calculate the array size in bytes (sz * num). We're using signed multiply because the equivalent using the unsigned instruction would use more instructions. + addq %rbx,%r12 + + # Iterate through the array: +.loop: + + # Check if we have reached the one-past-the-end address: + cmpq %rbx,%r12 + je .done + + # Call the provided function: + movq %rbx,%rdi # Provide the current address to the function. + call *%r14 # We don't need to save any registers for this as we only use callee-saved registers. + + # Continue to the next element: + addq %r13,%rbx + jmp .loop + + # Finish: +.done: + + # Restore the callee-saved registers: + popq %r14 + popq %r13 + popq %r12 + popq %rbx + + ret + +#endif |