From e309ee4fda3895fc437acfb00a38dcde7a4064b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Tue, 15 Sep 2026 23:56:35 +0200 Subject: [PATCH] Added contains function. Changed find_index returning flags now too --- src/array.asm | 3 + src/hashset.asm | 151 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 136 insertions(+), 18 deletions(-) diff --git a/src/array.asm b/src/array.asm index c90ba38..30b4c2c 100644 --- a/src/array.asm +++ b/src/array.asm @@ -7,6 +7,7 @@ ; r5 - Predicate context ; Result: ; r1 - The index of the first element matching the provided predicate function (or -1 if not found) +; flags - 0, if the element does not exist in the array. 1 if the element does exist. ; Clobbers: r2, r3, r4, r5, r6, + what the predicate clobbers ; Info: ; The predicate function should follow the stdlib calling convention @@ -74,4 +75,6 @@ pub find_index: pop r10 pop r11 pop r12 + lsr flags, r1, 31 + xor flags, flags, 1 jmp r13 ; Return diff --git a/src/hashset.asm b/src/hashset.asm index ee98a32..5fee078 100644 --- a/src/hashset.asm +++ b/src/hashset.asm @@ -5,21 +5,139 @@ ;} ;struct HashSet { -; count: U32 -; capacity: U32 -; alloc_ptr: U32 -; hash_ptr: U32 +; buckets: U32 +; alloc_ptr: *Allocator +; hash_ptr: *(Item) -> U32 ; hash_context: U32 -; eq_ptr: U32 +; eq_ptr: *(Item, Item) -> Bool ; eq_context: U32 -; data_ptr: U32 -;} - 28 bytes - -;struct HashItem { -; hash: U32 -; value: U32 +; data_ptr: *HashBucket ;} +;struct HashBucket { +; hash0: U32 +; item0: Item +; hash1: U32 +; item1: Item +; hash2: U32 +; item2: Item +; hash3: U32 +; item3: Item +;} + +; Checks if the hashset contains a specified element +; Arguments: +; r1 - The element to check +; r2 - The pointer to the hashset +; Result: +; r1 - 0, if the element does not exist in the hashset. 1 if the element does exist. +; r2 - The pointer to the hashset +; flags - 0, if the element does not exist in the hashset. 1 if the element does exist. +pub contains: + push r13 + push r8 + push r9 + push r10 + push r11 + push r12 + + mov r8, r1 + mov r9, r2 + + add r3, r2, 8 + load_32 r3, [r3] ; Loading the hash pointer + add r2, r2, 12 + load_32 r2, [r2] ; Loading the hash context + + counter r13 + add r13, r13, 12 + jmp r3 ; Calling the hash function with element in r1, context in r2 + + mov r12, r1 + + add r10, r9, 16 + load_32 r10, [r10] ; Loading the eq pointer + add r11, r9, 20 + load_32 r11, [r11] ; Loading the eq context + + ; We have: + ; item in r8 + ; bucket pointer in r9 + ; eq pointer in r10 + ; eq context in r11 + ; item hash in r12 + + load_32 r2, [r9] ; Loading buckets + sub r2, r2, 1 + and r2, r1, r2 ; bucket_index = hash & (buckets - 1) + + add r3, r9, 24 + load_32 r3, [r3] ; Loading data pointer + lsl r2, r2, 5 ; Each bucket is 32 bytes + push r9 + add r9, r2, r3 ; Pointer to bucket + + load_32 r3, [r9] ; First hash + cmp r12, r3 + jne contains_notfirst + ; First item hash passed - checking equality + mov r13, contains_notfirst + jmp contains_eqcheck + + contains_notfirst: + add r9, r9, 8 + load_32 r3, [r9] ; Second hash + cmp r12, r3 + jne contains_notsecond + ; Second item hash passed - checking equality + mov r13, contains_notsecond + jmp contains_eqcheck + + contains_notsecond: + add r9, r9, 8 + load_32 r3, [r9] ; Third hash + cmp r12, r3 + jne contains_notthird + ; Third item hash passed - checking equality + mov r13, contains_notthird + jmp contains_eqcheck + + contains_notthird: + add r9, r9, 8 + load_32 r3, [r9] ; Fourth hash + cmp r12, r3 + jne contains_notfourth + ; Fourth item hash passed - checking equality + mov r13, contains_notfourth + jmp contains_eqcheck + + contains_notfourth: + mov r1, 0 + contains_finish: + pop r2 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop r13 + mov flags, r1 + jmp r13 + + contains_found: + mov r1, 1 + jmp contains_finish + + contains_eqcheck: + add r3, r9, 4 + load_32 r2, [r3] + mov r3, r11 + mov r1, r8 + jmp r10 ; Calling eq check + cmp r1, zr + jne contains_found + jmp r13 + ; Creates a hashset for the specified allocator, hash function and equality function ; Arguments: ; r1 - The pointer to the allocator @@ -34,7 +152,7 @@ ; The hash function receives one argument (the value of the item) and should return an integer which remains the same for the lifetime of the value. ; The equality function should follow the stdlib calling convention ; The equality function receives two arguments (the value of the two items) and should return either a zero (when the items are not equal) or any other value (if they are equal). -pub new_hashset: +pub new: ; First let's free up all the registers push r8 push r9 @@ -57,11 +175,8 @@ pub new_hashset: ; Now r1 has the pointer to memory, r2-r7 are clobbered - store_32 [r1], rz ; count is 0 at the start - - add r1, r1, 4 mov r2, 8 - store_32 [r1], r2 ; initial capacity at 8 item slots + store_32 [r1], r2 ; initial capacity at 8 buckets add r1, r1, 4 store_32 [r1], r8 ; allocator pointer is in r8 @@ -81,14 +196,14 @@ pub new_hashset: add r12, r1, 4 ; Now r12 is hashset pointer at data_ptr load_32 r5, [r8] ; Loading the alloc function address - mov r1, 64 + mov r1, 256 ; 8 buckets * 4 items * 8 bytes per each counter r13 add r13, r13, 12 jmp r5 ; allocating the space for the data store_32 [r2], r1 ; data pointer saved - sub r1, r12, 28 ; Getting the pointer to start of the hashset + sub r1, r12, 24 ; Getting the pointer to start of the hashset pop r13 ; Everything's set up, return pop r12