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;
}
Historical capture: 2010-02-12. Home | Power on LoseThos | Sources and changes