asm {
//************************************
SYS_HASH_STR::
// IN: RSI=Addr 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 VAL
// 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_cnt[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
}
_extern _HASH_STR I64 HashStr(U8 *st); //Hash a string.
_extern _HASH_FIND CHash *HashFind(U8 *needle_str,CHashTable *haystack_table,
I64 mask,I64 instance=1);//Find string in hash table.
_extern _HASH_SINGLE_TABLE_FIND CHash *HashSingleTableFind(U8 *needle_str,
CHashTable *haystack_table,
I64 mask,I64 instance=1);//Find string in single hash table.
_extern _HASH_BUCKET_FIND CHash **HashBucketFind(U8 *needle_str,
CHashTable *haystack_table); //Find hash bucket.
_extern _HASH_ADD U0 HashAdd(CHash *tmph,
CHashTable *table); //Add entry to hash table.
_extern _HASH_REM_DEL Bool HashRemDel(CHash *tmph,CHashTable *table,
I64 instance=1);//Remove hash entry and del. Instance must match.