Project: OSMain asm { USE64 // ************************************ // IN: RSI // OUT: RAX HASH_STR:: PUSH RSI PUSH RBX XOR RAX,RAX XOR RBX,RBX JMP @@10 @@1: SHL RBX,1 ADC RBX,RAX @@10: LODSB OR AL,AL JNZ @@1 @@100: MOV RAX,RBX SHR RBX,16 ADC RAX,RBX POP RBX POP RSI RET // ************************************ // IN: RAX=HASHED_STRING // RSI=STR // RBX=TYPE MASK // RDI=TABLE // OUT: RAX=ENTRY OR ZERO NOT FOUND // RDX=POINTER TO POINTER TO ENTRY // ZERO FLAG SET NOT FOUND HASH_SINGLE_TABLE_FIND:: AND RAX,U8 HT_MASK[RDI] MOV RCX,U8 HT_BODY[RDI] LEA RDX,U8 [RCX+RAX*8] @@1: MOV RAX,U8 [RDX] OR RAX,RAX JNZ @@3 RET @@3: TEST U4 HTE_TYPE[RAX],EBX JZ @@90 PUSH RAX PUSH RDI PUSH RSI MOV RDI,U8 HTE_STR[RAX] @@2: LODSB CMP U1 [RDI],AL JNE @@80 INC RDI OR AL,AL JNZ @@2 POP RSI POP RDI POP RAX INC U4 HTE_USE_CNT[RAX] OR RAX,RAX RET @@80: POP RSI POP RDI POP RAX @@90: LEA RDX,U8 HTE_NEXT[RAX] JMP @@1 // ************************************ // IN: RSI=STR // RBX=TYPE MASK // RDI=TABLE // OUT: RAX=ENTRY OR ZERO NOT FOUND // ZERO FLAG SET NOT FOUND HASH_FIND:: PUSH RDI CALL HASH_STR @@4: PUSH RAX CALL HASH_SINGLE_TABLE_FIND JNZ @@100 POP RAX MOV RDI,U8 HT_NEXT[RDI] OR RDI,RDI JNZ @@4 POP RDI XOR RAX,RAX RET @@100: ADD RSP,8 POP RDI OR RAX,RAX RET // ************************************ // IN: RSI=STR // RDI=TABLE // OUT: RAX=BUCKET HASH_BUCKET_FIND:: PUSH RDX CALL HASH_STR AND RAX,U8 HT_MASK[RDI] MOV RDX,U8 HT_BODY[RDI] LEA RAX,U8 [RDX+RAX*8] POP RDX RET // ************************************ EXT_FIND:: //IN: RSI //OUT: RSI PUSH RDI PUSH RBX XOR RAX,RAX MOV RDI,U8 FS:TASK_HASH_TABLE[RAX] MOV RBX,HTT_FUNCTION|HTT_EXPORT_SYS_SYMBOL CALL HASH_FIND JNZ @@1 XOR RAX,RAX JMP @@3 @@1: TEST U4 HTE_TYPE[RAX],HTT_FUNCTION JZ @@2 MOV RAX,U8 offset(ClassStruct.executable_address)[RAX] JMP @@3 @@2: MOV RAX,U8 HTE_VAL[RAX] @@3: POP RBX POP RDI OR RAX,RAX RET _EXT_FIND:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI XOR RAX,RAX MOV RDI,U8 FS:TASK_HASH_TABLE[RAX] MOV RSI,U8 SF_ARG1[RBP] MOV RBX,HTT_FUNCTION|HTT_EXPORT_SYS_SYMBOL CALL HASH_FIND JNZ @@1 XOR RAX,RAX JMP @@3 @@1: TEST U4 HTE_TYPE[RAX],HTT_FUNCTION JZ @@2 MOV RAX,U8 offset(ClassStruct.executable_address)[RAX] JMP @@3 @@2: MOV RAX,U8 HTE_VAL[RAX] @@3: POP RDI POP RSI POP RBP RET // ************************************ _HASH_STR:: PUSH RBP MOV RBP,RSP PUSH RSI MOV RSI,U8 SF_ARG1[RBP] CALL HASH_STR POP RSI POP RBP RET // ************************************ _HASH_FIND:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RSI,U8 SF_ARG1[RBP] MOV RDI,U8 SF_ARG2[RBP] MOV RBX,U8 SF_ARG3[RBP] CALL HASH_FIND POP RDI POP RSI POP RBP RET // ************************************ _HASH_SINGLE_TABLE_FIND:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RSI,U8 SF_ARG1[RBP] MOV RDI,U8 SF_ARG2[RBP] MOV RBX,U8 SF_ARG3[RBP] CALL HASH_STR CALL HASH_SINGLE_TABLE_FIND POP RDI POP RSI POP RBP RET // ************************************ _HASH_BUCKET_FIND:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RSI,U8 SF_ARG1[RBP] MOV RDI,U8 SF_ARG2[RBP] CALL HASH_BUCKET_FIND POP RDI POP RSI POP RBP RET // ************************************ _HASH_ADD:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RCX,U8 SF_ARG1[RBP] MOV RSI,U8 HTE_STR[RCX] MOV RDI,U8 SF_ARG2[RBP] CALL HASH_BUCKET_FIND MOV RCX,U8 SF_ARG1[RBP] PUSHFD CLI MOV RBX,U8 [RAX] MOV U8 HTE_NEXT[RCX],RBX MOV U8 [RAX],RCX //Insque MOV RBX,U8 HT_LAST_ADDED[RDI] MOV U8 HTE_LAST_ADDED[RCX],RBX MOV U8 HTE_NEXT_ADDED[RBX],RCX MOV U8 HT_LAST_ADDED[RDI],RCX MOV U8 HTE_NEXT_ADDED[RCX],RDI POPFD POP RDI POP RSI POP RBP RET // ************************************ _HASH_REPLACE:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RCX,U8 SF_ARG1[RBP] OR RCX,RCX JZ I4 @@100 MOV RSI,U8 HTE_STR[RCX] XOR RBX,RBX MOV EBX,U4 HTE_TYPE[RCX] AND EBX,~(HTT_PRIVATE|HTT_PUBLIC|HTT_EXPORT|HTT_IMPORT|HTT_LITERAL| HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)&0xFFFFFFFF MOV RDI,U8 SF_ARG2[RBP] CALL HASH_STR PUSHFD CLI CALL HASH_SINGLE_TABLE_FIND MOV RCX,U8 SF_ARG1[RBP] JZ @@11 //Z set by find //Remque/Insque MOV RBX,U8 HTE_NEXT_ADDED[RAX] MOV U8 HTE_NEXT_ADDED[RCX],RBX MOV U8 HTE_LAST_ADDED[RBX],RCX MOV RBX,U8 HTE_LAST_ADDED[RAX] MOV U8 HTE_LAST_ADDED[RCX],RBX MOV U8 HTE_NEXT_ADDED[RBX],RCX MOV RBX,U8 HTE_NEXT[RAX] JMP @@10 //Insque @@11: MOV RBX,U8 HT_LAST_ADDED[RDI] MOV U8 HTE_LAST_ADDED[RCX],RBX MOV U8 HTE_NEXT_ADDED[RBX],RCX MOV U8 HT_LAST_ADDED[RDI],RCX MOV U8 HTE_NEXT_ADDED[RCX],RDI MOV RBX,RAX @@10: MOV U8 HTE_NEXT[RCX],RBX MOV U8 [RDX],RCX POPFD OR RAX,RAX JZ @@100 PUSH_C_REGS PUSH RAX CALL _HASH_DEL ADD RSP,8 POP_C_REGS @@100: POP RDI POP RSI POP RBP RET // ************************************ _HASH_REM_DEL:: PUSH RBP MOV RBP,RSP PUSH RSI PUSH RDI MOV RCX,U8 SF_ARG1[RBP] OR RCX,RCX JZ @@102 MOV RSI,U8 HTE_STR[RCX] XOR RBX,RBX MOV EBX,U4 HTE_TYPE[RCX] AND EBX,~(HTT_PRIVATE|HTT_PUBLIC|HTT_EXPORT|HTT_IMPORT|HTT_LITERAL| HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)&0xFFFFFFFF MOV RDI,U8 SF_ARG2[RBP] CALL HASH_STR PUSHFD CLI CALL HASH_SINGLE_TABLE_FIND JZ @@101 CMP RAX,U8 SF_ARG1[RBP] JNE @@101 MOV RBX,U8 HTE_NEXT[RAX] MOV U8 [RDX],RBX //Remque MOV RBX,U8 HTE_NEXT_ADDED[RAX] MOV RDX,U8 HTE_LAST_ADDED[RAX] MOV U8 HTE_NEXT_ADDED[RDX],RBX MOV U8 HTE_LAST_ADDED[RBX],RDX POPFD PUSH_C_REGS PUSH RAX CALL _HASH_DEL ADD RSP,8 POP_C_REGS @@100: POP RDI POP RSI POP RBP MOV RAX,1 RET @@101: POPFD @@102: POP RDI POP RSI POP RBP XOR RAX,RAX RET } LTextern _HASH_STR U8 HashStr(U1 *st); LTextern _HASH_FIND SysHashEntry * HashFind(U1 *st,SysHashTable *table,U8 mask); LTextern _HASH_SINGLE_TABLE_FIND SysHashEntry * HashSingleTableFind(U1 *st,SysHashTable *table,U8 mask); LTextern _HASH_BUCKET_FIND SysHashEntry ** HashBucketFind(U1 *st,SysHashTable *table); LTextern _HASH_ADD U0 HashAdd(SysHashEntry *temph,SysHashTable *table); LTextern _HASH_REPLACE U0 HashReplace(SysHashEntry *temph,SysHashTable *table); LTextern _HASH_REM_DEL BoolI8 HashRemDel(SysHashEntry *temph,SysHashTable *table); SysHashTable *HashTableNew(U8 size,TaskStruct *mem_task=NULL) { SysHashTable *tempht; tempht=CAlloc(sizeof(SysHashTable),mem_task); tempht->body=CAlloc(size<<3,mem_task); tempht->mask=size-1; tempht->next_added=tempht->last_added=tempht; return tempht; } asm {_HASH_DEL::} U0 HashDel(SrcSymHashEntry *temph) { if (!temph) return; if (!(temph->h.type&HTT_DICT_WORD)) Free(temph->h.str); if (temph->h.type & HTT_SRC_SYM) { Free(temph->src_link); Free(temph->index); Free(temph->import_name); LinkedListDel(temph->list); if (temph->h.type & (HTT_FUNCTION | HTT_EXPORT_SYS_SYMBOL)) { Free(temph->debug); Free(temph->indent); } if (temph->h.type & (HTT_FUNCTION | HTT_CLASS)) //Assumes code not on heap, so doesn't Free. //MemberListDel() is an import to the OSMain module MemberListDel(temph); else if (temph->h.type&HTT_DEFINE_STR) Free(temph><(DefineStrHashEntry *)->data); else if (temph->h.type & HTT_GLBL_VAR) { if (!(temph><(GlblVarStruct *)->flags&GVAF_ALIAS)) Free(temph><(GlblVarStruct *)->data_address); LinkedListDel(temph><(GlblVarStruct *)->dim.next); if (temph><(GlblVarStruct *)->fun_ptr) HashDel(temph><(GlblVarStruct *)->fun_ptr-temph><(GlblVarStruct *)->fun_ptr->ptr_cnt); } else if (temph->h.type & HTT_TYPEDEF) { LinkedListDel(temph><(GlblVarStruct *)->dim.next); if (temph><(GlblVarStruct *)->fun_ptr) HashDel(temph><(GlblVarStruct *)->fun_ptr-temph><(GlblVarStruct *)->fun_ptr->ptr_cnt); } } else if (temph->h.type & HTT_FILE) Free(temph><(GenericHashEntry *)->user_data0); Free(temph); } U0 HashTableDel(SysHashTable *tempht) { SrcSymHashEntry *temph,*temph1; if (!tempht) return; temph=tempht->next_added; while (temph!=tempht) { temph1=temph->h.next_added; HashDel(temph); temph=temph1; } Free(tempht->body); Free(tempht); } GenericHashEntry *HashGenericAdd(U1 *name,I8 type,I8 u0=0,I8 u1=0,I8 u2=0,TaskStruct *task=NULL) { GenericHashEntry *result; if (!task) task=Fs; result=CAlloc(sizeof(GenericHashEntry),task); result->h.type=type; result->user_data0=u0; result->user_data1=u1; result->user_data2=u2; result->h.str=StrNew(name,task); HashAdd(result,task->hash_table); return result; } I8 NamedFramePtr(U1 *name,TaskStruct *task=NULL) { GenericHashEntry *temph; if (!task) task=Fs; if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR)) return temph->user_data0; else return 0; } GenericHashEntry *NamedFramePtrAdd(U1 *name,I8 u0,TaskStruct *task=NULL) { return HashGenericAdd(name,HTT_NAMED_FRAME_PTR,u0,0,0,task); } I8 NamedFramePtrSet(U1 *name,I8 u0,TaskStruct *task=NULL) { GenericHashEntry *temph; if (!task) task=Fs; if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR)) return LXchgU8(&temph->user_data0,u0); else return 0; } I8 NamedFramePtrDel(U1 *name,TaskStruct *task=NULL) { I8 result=0; GenericHashEntry *temph; if (!task) task=Fs; if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR)) { result=temph->user_data0; HashRemDel(temph,task->hash_table); } return result; } U0 LoadOneImport(U1 **_ptr,U1 *code,I8 flags) { U1 *ptr=*_ptr,*ptr2; U1 *sptr; I8 i,etype; ExportSysSymHashEntry *tempess=NULL; ImportSysSymHashEntry *tempiss; BoolI1 first=TRUE; ClassStruct *tempc; GlblVarStruct *tempg; while ((etype=*ptr++)!=EIE_END) { i=*ptr><(U4 *)++; sptr=ptr; ptr+=StrLen(sptr)+1; if (*sptr) { if (!first) { *_ptr=sptr-5; return; } else { first=FALSE; if (!(tempess=HashFind(sptr,Fs->hash_table,HTT_ALL-HTT_IMPORT_SYS_SYMBOL))) { if (!(flags & LDF_SILENT)) coutln Define("ST_UNRESOLVED_REFERENCE"),sptr; tempiss=CAlloc(sizeof(ImportSysSymHashEntry)); tempiss->s.h.str=StrNew(sptr); tempiss->s.h.type=HTT_IMPORT_SYS_SYMBOL; tempiss->module_header_entry=sptr-5; tempiss->module_base=code; HashAdd(tempiss,Fs->hash_table); } } } if (tempess) { ptr2=code+i; if (tempess->s.h.type & HTT_FUNCTION) { tempc=tempess; if (etype & 1) i=tempc->executable_address; else i=tempc->executable_address-code; } else if (tempess->s.h.type & HTT_GLBL_VAR) { tempg=tempess; if (etype & 1) i=tempg->data_address; else i=tempg->data_address-code; } else { if (etype & 1) i=tempess->val; else i=tempess->val><(U1 *)-code; } if (etype<=EIE_LIT_U1) *ptr2><(U1 *)+=i; else if (etype<=EIE_LIT_U2) *ptr2><(U2 *)+=i; else if (etype<=EIE_LIT_U4) *ptr2><(U4 *)+=i; else if (etype<=EIE_LIT_U8) *ptr2><(U8 *)+=i; } } *_ptr=ptr-1; } U0 SysSymImportsResolve(U1 *sptr,I8 flags) { ImportSysSymHashEntry *tempiss; U1 *ptr; while (tempiss=HashSingleTableFind(sptr,Fs->hash_table,HTT_IMPORT_SYS_SYMBOL)) { ptr=tempiss->module_header_entry; LoadOneImport(&ptr,tempiss->module_base,flags); tempiss->s.h.type=HTT_INVALID; } } U0 LoadPass1(U1 **_ptr,U1 *code,I8 flags) { U1 *ptr=*_ptr,*ptr2,*ptr3; U1 *sptr; I8 i,j,cnt,etype; ExportSysSymHashEntry *tempess=NULL; while ((etype=*ptr++)!=EIE_END) { i=*ptr><(U4 *)++; sptr=ptr; ptr+=StrLen(sptr)+1; switch (etype) { case EIE_REL_EXPORT: case EIE_LIT_EXPORT: tempess=CAlloc(sizeof(ExportSysSymHashEntry)); tempess->s.h.str=StrNew(sptr); tempess->s.h.type=HTT_EXPORT_SYS_SYMBOL; if (etype==EIE_LIT_EXPORT) tempess->val=i; else tempess->val=i+code; HashAdd(tempess,Fs->hash_table); SysSymImportsResolve(sptr,flags); break; case EIE_REL_U1...EIE_LIT_U8: ptr=sptr-5; LoadOneImport(&ptr,code,flags); break; case EIE_ABSOLUTE_ADDRESS: if (flags & LDF_NO_ABSOLUTES) ptr+=i*sizeof(U4); else { cnt=i; for (j=0;j<cnt;j++) { ptr2=code+*ptr><(U4 *)++; *ptr2><(U4 *)+=code; } } break; case EIE_HEAP_GLBL: ptr3=MAlloc(*ptr><(U8 *)++); if (*sptr) { tempess=CAlloc(sizeof(ExportSysSymHashEntry)); tempess->s.h.str=StrNew(sptr); tempess->s.h.type=HTT_EXPORT_SYS_SYMBOL; tempess->val=ptr3; HashAdd(tempess,Fs->hash_table); } cnt=i; for (j=0;j<cnt;j++) { ptr2=code+*ptr><(U4 *)++; *ptr2><(U8 *)+=ptr3; } break; } } *_ptr=ptr; } U0 LoadOSMainHeader() { U1 *ptr; HashGenericAdd("/LT/OSMain/OS",HTT_MODULE|HTT_PUBLIC,sys_boot_base); ptr=sys_boot_header_base; LoadPass1(&ptr,sys_boot_base,LDF_NO_ABSOLUTES|LDF_SILENT); } U0 *Load(U1 *filename,U8 flags=0) { U1 *fbuf; U1 *code,*ptr,etype; U1 *sptr,*absname; U8 size,module_alignment; BinFileHeaderStruct *bfh,*bfh2; I8 i; fbuf=DefaultExtension(filename,"BIZ"); if (!(bfh2=FileRead(fbuf,&size))) { Free(fbuf); return NULL; } module_alignment=*(bfh2><(U1 *)+bfh2->header_offset+1)><(U4 *); if (!module_alignment || Bsf(module_alignment)!=Bsr(module_alignment)) throw(EXCEPT_BIN_MODULE); #assert sizeof(BinFileHeaderStruct)==16 if (Fs->code_heap!=Fs->data_heap) { if (module_alignment<16) module_alignment=16; bfh=MAllocAligned(size,module_alignment,Fs->code_heap,module_alignment-sizeof(BinFileHeaderStruct)); MemCpy(bfh,bfh2,size); Free(bfh2); } else { if (module_alignment>8) { bfh=MAllocAligned(size,module_alignment,NULL,module_alignment-sizeof(BinFileHeaderStruct)); MemCpy(bfh,bfh2,size); Free(bfh2); } else bfh=bfh2; } code=bfh><(U1 *)+sizeof(BinFileHeaderStruct); if (ArcXSum(bfh,bfh->file_size)!=LT_XSUM) throw(EXCEPT_ARC_XSUM); absname=FileNameAbs(fbuf); Free(fbuf); fbuf=StrNew(absname); StrLastRem(fbuf,"."); if (fbuf[1]==':' && StrLen(fbuf)>2) HashGenericAdd(fbuf+2,HTT_MODULE|HTT_PUBLIC,code); Free(fbuf); ptr=bfh><(U1 *)+bfh->header_offset; LoadPass1(&ptr,code,flags); if (!(flags&LDF_JUST_LOAD)) { ptr=bfh><(U1 *)+bfh->header_offset; while ((etype=*ptr++)!=EIE_END) { //PASS 2 i=*ptr><(U4 *)++; sptr=ptr; ptr+=StrLen(sptr)+1; switch (etype) { case EIE_MAIN: Call(i+code); break; case EIE_ABSOLUTE_ADDRESS: ptr+=sizeof(U4)*i; break; case EIE_HEAP_GLBL: ptr+=8+sizeof(U4)*i; break; } } } Free(absname); return bfh; }