summaryrefslogtreecommitdiff
path: root/zap/source/amd64/mem/memcnt.S
diff options
context:
space:
mode:
Diffstat (limited to 'zap/source/amd64/mem/memcnt.S')
-rw-r--r--zap/source/amd64/mem/memcnt.S75
1 files changed, 75 insertions, 0 deletions
diff --git a/zap/source/amd64/mem/memcnt.S b/zap/source/amd64/mem/memcnt.S
new file mode 100644
index 0000000..5323301
--- /dev/null
+++ b/zap/source/amd64/mem/memcnt.S
@@ -0,0 +1,75 @@
+# 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/.
+
+.globl zap_memcnt
+
+zap_memcnt:
+# Address of the current element:
+#define addr %rbx
+# Address of the element after the last input element:
+#define afterbuf %r12
+# Size of each input element:
+#define sz %r13
+# Address of the function:
+#define fn %r14
+# Count:
+#define cnt %r15
+
+ # Push the callee-saved registers:
+ pushq addr
+ pushq afterbuf
+ pushq sz
+ pushq fn
+ pushq cnt
+
+ # Move registers into place:
+ movq %rdi,addr
+ movq %rsi,sz
+ movq %rdx,afterbuf
+ movq %rcx,fn
+
+ # Get the one-past-the-end address:
+ imulq sz,afterbuf # afterbuf *= sz
+ addq addr,afterbuf # afterbuf += addr
+
+ movq $0x0,cnt # cnt = 0x0
+
+ # Iterate through the array:
+.loop:
+
+ # Check if we have reached the one-past-the-end address:
+ cmpq addr,afterbuf # if (addr == afterbuf)
+ je .done # goto done
+
+ # Call the provided function:
+ movq addr,%rdi
+ call *fn # fn(addr)
+
+ # Check the return value of the function:
+ testb %al,%al # if (fn(addr) == zap_false)
+ jz .skip # goto skip
+
+ incq cnt # ++cnt
+
+ # Skip the incrementation:
+.skip:
+
+ # Continue to the next element:
+ addq sz,addr # addr += sz
+ jmp .loop # goto loop
+
+ # Finish:
+.done:
+
+ # Move count into return register:
+ movq cnt,%rax
+
+ # Restore the callee-saved registers:
+ popq cnt
+ popq fn
+ popq sz
+ popq afterbuf
+ popq addr
+
+ ret # return cnt