asm { //************************************ SYS_HASH_STR:: // IN: RSI = Address of string // OUT: RAX XOR RAX, RAX TEST RSI, RSI JZ @@15 PUSH RSI PUSH RBX XOR RBX, RBX JMP @@10 @@05: SHL1 RBX ADC RBX, RAX @@10: LODSB TEST AL, AL JNZ @@05 MOV RAX, RBX SHR RBX, 16 ADC RAX, RBX POP RBX POP RSI @@15: RET //************************************ SYS_HASH_SINGLE_TABLE_FIND1:: // IN: RAX = HASHED STRING VALUE // RSI = STR // RBX = TYPE MASK // RDI = TABLE // RCX = INSTANCE, NOT ZERO // OUT: RAX = ENTRY OR ZERO NOT FOUND // RDX = POINTER TO POINTER TO ENTRY // RCX IF NOT FOUND ENOUGH, DECREMENTED BY NUM MATCHES // ZERO FLAG SET NOT FOUND MOV RCX, 1 SYS_HASH_SINGLE_TABLE_FIND:: TEST RCX, RCX JNZ @@05 XOR RAX, RAX RET @@05: AND RAX, U64 CHashTable.mask[RDI] MOV RDX, U64 CHashTable.body[RDI] LEA RDX, U64 [RDX + RAX * 8] @@10: MOV RAX, U64 [RDX] TEST RAX, RAX JNZ @@15 RET @@15: TEST U32 CHash.type[RAX], EBX JZ @@30 PUSH RAX PUSH RDI PUSH RSI MOV RDI, U64 CHash.str[RAX] @@20: LODSB CMP U8 [RDI], AL JNE @@25 INC RDI TEST AL, AL JNZ @@20 POP RSI POP RDI POP RAX LOOP @@30 INC U32 CHash.use_count[RAX] TEST RAX, RAX RET @@25: POP RSI POP RDI POP RAX @@30: LEA RDX, U64 CHash.next[RAX] JMP @@10 //************************************ SYS_HASH_FIND1:: // IN: RSI = STR // RBX = TYPE MASK // RDI = TABLE // RCX = INSTANCE NUM // OUT: RAX = ENTRY OR ZERO NOT FOUND // ZERO FLAG SET NOT FOUND MOV RCX, 1 SYS_HASH_FIND:: PUSH RDI CALL SYS_HASH_STR @@05: PUSH RAX CALL SYS_HASH_SINGLE_TABLE_FIND JNZ @@15 POP RAX @@10: MOV RDI, U64 CHashTable.next[RDI] TEST RDI, RDI JNZ @@05 POP RDI XOR RAX, RAX RET @@15: ADD RSP, 8 POP RDI TEST RAX, RAX RET //************************************ SYS_HASH_BUCKET_FIND:: // IN: RSI = STR // RDI = TABLE // OUT: RAX = BUCKET PUSH RDX CALL SYS_HASH_STR AND RAX, U64 CHashTable.mask[RDI] MOV RDX, U64 CHashTable.body[RDI] LEA RAX, U64 [RDX+RAX * 8] POP RDX RET _HASH_STR:: PUSH RBP MOV RBP, RSP PUSH RSI MOV RSI, U64 SF_ARG1[RBP] CALL SYS_HASH_STR POP RSI POP RBP RET1 8 _HASH_FIND:: PUSH RBP MOV RBP, RSP PUSH RSI PUSH RDI MOV RSI, U64 SF_ARG1[RBP] MOV RDI, U64 SF_ARG2[RBP] MOV RBX, U64 SF_ARG3[RBP] MOV RCX, U64 SF_ARG4[RBP] CALL SYS_HASH_FIND POP RDI POP RSI POP RBP RET1 32 _HASH_SINGLE_TABLE_FIND:: PUSH RBP MOV RBP, RSP PUSH RSI PUSH RDI MOV RSI, U64 SF_ARG1[RBP] MOV RDI, U64 SF_ARG2[RBP] MOV RBX, U64 SF_ARG3[RBP] MOV RCX, U64 SF_ARG4[RBP] CALL SYS_HASH_STR CALL SYS_HASH_SINGLE_TABLE_FIND POP RDI POP RSI POP RBP RET1 32 _HASH_BUCKET_FIND:: PUSH RBP MOV RBP, RSP PUSH RSI PUSH RDI MOV RSI, U64 SF_ARG1[RBP] MOV RDI, U64 SF_ARG2[RBP] CALL SYS_HASH_BUCKET_FIND POP RDI POP RSI POP RBP RET1 16 _HASH_ADD:: PUSH RBP MOV RBP, RSP PUSH RSI PUSH RDI MOV RCX, U64 SF_ARG1[RBP] MOV RSI, U64 CHash.str[RCX] MOV RDI, U64 SF_ARG2[RBP] CALL SYS_HASH_BUCKET_FIND MOV RCX, U64 SF_ARG1[RBP] PUSHFD CLI MOV RBX, U64 [RAX] MOV U64 CHash.next[RCX], RBX MOV U64 [RAX], RCX POPFD POP RDI POP RSI POP RBP RET1 16 _HASH_ADD_AFTER:: PUSH RBP MOV RBP, RSP PUSH RDI MOV RCX, U64 SF_ARG1[RBP] MOV RDI, U64 SF_ARG3[RBP] PUSHFD CLI MOV RAX, SF_ARG2[RBP] MOV RBX, U64 [RAX] MOV U64 CHash.next[RCX], RBX MOV U64 [RAX], RCX POPFD POP RDI POP RBP RET1 24 _HASH_REM_DEL:: PUSH RBP MOV RBP, RSP PUSH RSI PUSH RDI MOV RCX, U64 SF_ARG1[RBP] TEST RCX, RCX JZ @@10 MOV RSI, U64 CHash.str[RCX] XOR RBX, RBX MOV EBX, U32 CHash.type[RCX] AND EBX, ~HTG_FLAGS_MASK & 0xFFFFFFFF MOV RDI, U64 SF_ARG2[RBP] MOV RCX, U64 SF_ARG3[RBP] CALL SYS_HASH_STR PUSHFD CLI CALL SYS_HASH_SINGLE_TABLE_FIND JZ @@05 CMP RAX, U64 SF_ARG1[RBP] JNE @@05 MOV RBX, U64 CHash.next[RAX] MOV U64 [RDX], RBX POPFD PUSH_C_REGS PUSH RAX CALL &HashDel POP_C_REGS POP RDI POP RSI MOV RAX, 1 POP RBP RET1 24 @@05: POPFD @@10: POP RDI POP RSI XOR RAX, RAX POP RBP RET1 24 } // Hash a string. _extern _HASH_STR I64 HashStr(U8 *st); // Find string in hash table. _extern _HASH_FIND CHash *HashFind(U8 *needle_str, CHashTable *haystack_table, I64 mask, I64 instance=1); // Find string in single hash table. _extern _HASH_SINGLE_TABLE_FIND CHash *HashSingleTableFind(U8 *needle_str, CHashTable *haystack_table, I64 mask, I64 instance=1); // Find hash bucket. _extern _HASH_BUCKET_FIND CHash **HashBucketFind(U8 *needle_str, CHashTable *haystack_table); // Add entry to hash table. _extern _HASH_ADD U0 HashAdd(CHash *tmph, CHashTable *table); // Remove hash entry and del. Instance must match. _extern _HASH_REM_DEL Bool HashRemDel(CHash *tmph, CHashTable *table, I64 instance=1);