Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/Compiler/Assembler.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

Project: Compiler.SPZ
U0 AsmUnresolvedAdd(AsmCtrlStruct *a,U8 *exp,I64 type,U64 ip,U64 rel_ip,
                    LexUndefEntry *undef_hash,I64 line_num,BoolI8 U8_avail,BoolI8 glbl)
{
  AsmUnresolvedRef *tempu=MAlloc(sizeof(AsmUnresolvedRef));
  tempu->exp=exp;
  tempu->type=type;
  tempu->ip=ip;
  tempu->rel_ip=rel_ip;
  tempu->undef_hash=undef_hash;
  tempu->literal=FALSE;
  tempu->line_num=line_num;
  tempu->U8_avail=U8_avail;
  tempu->str=NULL;
  if (glbl) {
    tempu->next=a->glbl_unresolved;
    a->glbl_unresolved=tempu;
    if (undef_hash->hash->type & HTT_IMPORT) {
      tempu->str=StrNew(undef_hash->hash->str);
      if (undef_hash->hash->type & HTT_LITERAL)
        tempu->literal=TRUE;
    }
  } else {
    tempu->next=a->local_unresolved;
    a->local_unresolved=tempu;
    a->has_locals=TRUE;
  }
}

U0 AsmLineList(LexStruct *lx)
{
  AsmCtrlStruct *a=lx->a;
  LexFileStruct *tempf=lx->cur_lfn;
  LtfEntry *cl=tempf->line_start,*cl3;
  if (a->list && a->last_lfn==tempf && cl) {
    if (cl3=a->last_line_listed) {
      if (tempf->flags& LFSF_IS_LTF) {
        while (cl3->y<cl->y) {
          Spaces(24-a->display_col);
          a->display_col=0;
          "%08X ",a->last_ip;
          cl3=LexPutLine(lx,cl3);
        }
      } else {
        while (*cl3><(U8 *) && cl3!=cl) {
          Spaces(24-a->display_col);
          a->display_col=0;
          "%08X ",a->last_ip;
          cl3=LexPutLine(lx,cl3);
        }
      }
      a->last_line_listed=cl3;
    } else
      a->last_line_listed=cl;
  } else {
    a->last_line_listed=NULL;
    a->last_lfn=tempf;
  }
  a->last_ip=a->ip;
}

U0 AsmStoreCodeU8(LexStruct *lx,U8 b)
{
  AsmCtrlStruct *a=lx->a;
  I64 i=a->ip>>ASM_CODE_BLK_BITS;
  AsmCodeBlk *tempc=a->code;
  while (i--)
    if (!(tempc=tempc->next)) {
      i=a->ip>>ASM_CODE_BLK_BITS+1;
      tempc=&a->code;
      while (i--) {
        if (!tempc->next)
          tempc->next=CAlloc(sizeof(AsmCodeBlk));
        tempc=tempc->next;
      }
      break;
    }
  tempc->body[a->ip++ & (ASM_CODE_BLK_SIZE-1)]=b;
  if (a->list) {
    if (a->display_col>=24) {
      NewLine;
      a->display_col=0;
    }
    "%02X ",b;
    a->display_col+=3;
  }
  if (a->ip>a->num_code_U8s)
    a->num_code_U8s=a->ip;
}

U0 AsmStoreCodeU32(LexStruct *lx,U32 d)
{
  AsmCtrlStruct *a=lx->a;
  I64 i=a->ip>>ASM_CODE_BLK_BITS,
     j=(a->ip+sizeof(U32))>>ASM_CODE_BLK_BITS;
  U32 *_d;
  AsmCodeBlk *tempc=a->code;
  if (i!=j) {
    for (i=0;i<sizeof(U32);i++)
      AsmStoreCodeU8(lx,d.u8[i]);
    return;
  }
  tempc=a->code;
  while (i--)
    if (!(tempc=tempc->next)) {
      i=a->ip>>ASM_CODE_BLK_BITS+1;
      tempc=&a->code;
      while (i--) {
        if (!tempc->next)
          tempc->next=CAlloc(sizeof(AsmCodeBlk));
        tempc=tempc->next;
      }
      break;
    }
  _d=tempc->body+ a->ip&(ASM_CODE_BLK_SIZE-1);
  *_d=d;
  a->ip+=sizeof(U32);
  if (a->list) {
    if (a->display_col>=24) {
      NewLine;
      a->display_col=0;
    }
    "%08X ",d;
    a->display_col+=9;
  }
  if (a->ip>a->num_code_U8s)
    a->num_code_U8s=a->ip;
}

U0 AsmStoreCodeU64(LexStruct *lx,U64 d)
{
  AsmCtrlStruct *a=lx->a;
  I64 i=a->ip>>ASM_CODE_BLK_BITS,
     j=(a->ip+sizeof(U64))>>ASM_CODE_BLK_BITS;
  U64 *qq;
  AsmCodeBlk *tempc=a->code;
  if (i!=j) {
    for (i=0;i<sizeof(U64);i++)
      AsmStoreCodeU8(lx,d.u8[i]);
    return;
  }
  tempc=a->code;
  while (i--)
    if (!(tempc=tempc->next)) {
      i=a->ip>>ASM_CODE_BLK_BITS+1;
      tempc=&a->code;
      while (i--) {
        if (!tempc->next)
          tempc->next=CAlloc(sizeof(AsmCodeBlk));
        tempc=tempc->next;
      }
      break;
    }
  qq=tempc->body+ a->ip&(ASM_CODE_BLK_SIZE-1);
  *qq=d;
  a->ip+=sizeof(U64);
  if (a->list) {
    if (a->display_col>=24) {
      NewLine;
      a->display_col=0;
    }
    "%016X ",d;
    a->display_col+=17;
  }
  if (a->ip>a->num_code_U8s)
    a->num_code_U8s=a->ip;
}

U0 AsmStoreCodeU8At(LexStruct *lx,U8 b,I64 ip)
{
  AsmCtrlStruct *a=lx->a;
  I64 i=ip>>ASM_CODE_BLK_BITS+1;
  AsmCodeBlk *tempc=&a->code;
  while (i--) {
    if (!tempc->next) {
      tempc->next=CAlloc(sizeof(AsmCodeBlk));
      tempc->next->next=NULL;
    }
    tempc=tempc->next;
  }
  tempc->body[ip & (ASM_CODE_BLK_SIZE-1)]=b;
  if (ip+1>a->num_code_U8s)
    a->num_code_U8s=ip+1;
}

U0 AsmReserveCodeTo(LexStruct *lx,I64 ip)
{
  AsmCtrlStruct *a=lx->a;
  I64 i=ip>>ASM_CODE_BLK_BITS+1;
  AsmCodeBlk *tempc=&a->code;
  while (i--) {
    if (!tempc->next) {
      tempc->next=CAlloc(sizeof(AsmCodeBlk));
      tempc->next->next=NULL;
    }
    tempc=tempc->next;
  }
  if (ip>a->num_code_U8s)
    a->num_code_U8s=ip;
}


I64 AsmExpressionEval(LexStruct *lx)
{
  U8 *exp;
  I64 result=0;
  lx->undef_hash_entry=NULL;
  lx->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
  lx->abs_cnts=0;
  if (!GetExpression(lx,&exp))
    LexSkipEol(lx);
  else {
    if (lx->abs_cnts.externs)
      PrsExcept(lx,"ST_EXTERNS_NOT_ALLOWED");
    if (!(lx->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
      result=Call(exp);
      ExpressionDel(exp);
    } else
      PrsExcept(lx,"ST_UNDEFINED_SYM");
  }
  return result;
}

U0 AsmLocalsResolve(LexStruct *lx)
{
  AsmCtrlStruct *a=lx->a;
  AsmUnresolvedRef *tempu=a->local_unresolved,*tempu1;
  I64 result=0;
  LexUndefEntry *templu;
  BoolI8 undefined;
  U8 *label=NULL;

  if (!a->has_locals)
    return;
  while (tempu) {
    undefined=FALSE;
    tempu1=tempu->next;
    templu=tempu->undef_hash;
    while (templu) {
      if (templu->hash->type & (HTT_UNRESOLVED_LOCAL | HTT_UNRESOLVED_GLBL)) {
        PrintFErr("%S%S%04d ","ST_UNDEFINED_SYM","ST_LINE",tempu->line_num);
        if (a->last_label)
          "%s ",a->last_label;
        "%s\n",templu->hash->str;
        lx->error_cnt++;
        FlushMsgs;
        throw(EXCEPT_COMPILER,21);
      }
      label=templu->hash->str;
      templu=templu->next;
    }
    if (!undefined) {
      result=Call(tempu->exp);
      if (!(tempu->type & 1)) {
        result-=tempu->rel_ip;
        if (tempu->type==EIE_REL_U8 && !(MIN_I8<=result<=MAX_I8) ||
            tempu->type==EIE_REL_U16 && !(MIN_I16<=result<=MAX_I16) ) {
          PrintFErr("%S%S%04d ","ST_BRANCH_OUT_OF_RANGE","ST_LINE",tempu->line_num);
          if (a->last_label)
            "%s ",a->last_label;
          if (label) "" label;
          NewLine;
          lx->error_cnt++;
          FlushMsgs;
          throw(EXCEPT_COMPILER,22);
        }
        if (tempu->U8_avail && tempu->type>EIE_LIT_U8 && -124<=result<=123) {
          PrintFWarn("%S%S%04d ","ST_COULD_USE_U8_DISP","ST_LINE",tempu->line_num);
          if (a->last_label)
            "%s ",a->last_label;
          if (label) "" label;
          NewLine;
        }
      }
      AsmStoreCodeU8At(lx,result.u8[0],tempu->ip);
      if (tempu->type>=EIE_REL_U16) {
        AsmStoreCodeU8At(lx,result.u8[1],tempu->ip+1);
        if (tempu->type>=EIE_REL_U32) {
          AsmStoreCodeU8At(lx,result.u8[2],tempu->ip+2);
          AsmStoreCodeU8At(lx,result.u8[3],tempu->ip+3);
        }
      }
    }
    ExpressionDel(tempu->exp);
    LinkedListDel(tempu->undef_hash);
    Free(tempu);
    tempu=tempu1;
  }
  HashTableDel(lx->local_hash_table);
  lx->local_hash_table=lx->hash_table_list->next=
    HashTableNew(16);
  lx->local_hash_table->next=lx->glbl_hash_table;
  a->local_unresolved=NULL;
  a->has_locals=FALSE;
}

U0 AsmGlblsResolve(LexStruct *lx,ExeStruct *ex)
{
  AsmCtrlStruct *a=lx->a;
  ClassStruct *tempc;
  AsmUnresolvedRef *tempu=a->glbl_unresolved,*tempu1;
  I64 j,result=0;
  ExeImportExportStruct *tempe,*tempe1;
  LexUndefEntry *templu;
  ExportSysSymHashEntry *tempess;
  U8 *label;
  BoolI8 undefined;
  ExternUsage *tempeu,*tempeu8;

  while (tempu) {
    label=NULL;
    undefined=FALSE;
    tempu1=tempu->next;
    templu=tempu->undef_hash;
    while (templu) {
      if (templu->hash->type & (HTT_UNRESOLVED_LOCAL | HTT_UNRESOLVED_GLBL)) {
        tempess=templu->hash;
        if (tempess->type & HTT_EXPORT_SYS_SYM &&
            tempess->type & HTT_UNRESOLVED_GLBL &&
            !(tempess->type & HTT_IMPORT) &&
            (tempc=HashFind(tempess->str,lx->hash_table_list,HTT_FUN)) &&
            !Bt(tempc->flags,Cf_EXTERN)) {
          tempess->val=tempc->executable_addr;
          tempess->type&=~HTT_UNRESOLVED_GLBL;
          label=templu->hash->str;
        } else {
          if (!(tempess->type & HTT_IMPORT)) {
            PrintFErr("%S%S%04d %s\n",
              "ST_UNDEFINED_SYM","ST_LINE",tempu->line_num,tempess->str);
            lx->error_cnt++;
            FlushMsgs;
            throw(EXCEPT_COMPILER,23);
          }
          undefined=TRUE;
        }
      } else
        label=templu->hash->str;
      templu=templu->next;
    }
    result=Call(tempu->exp);
    if (!(tempu->type & 1))
      result-=tempu->rel_ip;
    if (undefined) {
      templu=tempu->undef_hash;
      if (templu->hash->type & HTT_IMPORT) {
        tempe=CAlloc(sizeof(ExeImportExportStruct));
        tempe->next=templu->hash->list;
        templu->hash->list=tempe;
        tempe->ip=tempu->ip;
        tempe->type=tempu->type;
      }
    } else {
      if (!(tempu->type & 1))  { //Rel?
        if (tempu->type==EIE_REL_U8 && !(MIN_I8<=result<=MAX_I8) ||
            tempu->type==EIE_REL_U16 && !(MIN_I16<=result<=MAX_I16)) {
          PrintFErr("%S%S%04d ","ST_BRANCH_OUT_OF_RANGE","ST_LINE",tempu->line_num);
          if (label) "" label;
          NewLine;
          lx->error_cnt++;
          FlushMsgs;
          throw(EXCEPT_COMPILER,24);
        }
        if (tempu->U8_avail && tempu->type>EIE_LIT_U8 && -124<=result<=123) {
          PrintFWarn("%S%S%04d ","ST_COULD_USE_U8_DISP","ST_LINE",tempu->line_num);
          if (a->last_label)
            "%s ",a->last_label;
          if (label) "" label;
          NewLine;
        }
      }
    }
    AsmStoreCodeU8At(lx,result.u8[0],tempu->ip);
    if (tempu->type>=EIE_REL_U16) {
      AsmStoreCodeU8At(lx,result.u8[1],tempu->ip+1);
      if (tempu->type>=EIE_REL_U32) {
        AsmStoreCodeU8At(lx,result.u8[2],tempu->ip+2);
        AsmStoreCodeU8At(lx,result.u8[3],tempu->ip+3);
        if (tempu->type>=EIE_REL_U64) {
          AsmStoreCodeU8At(lx,result.u8[2],tempu->ip+4);
          AsmStoreCodeU8At(lx,result.u8[3],tempu->ip+5);
          AsmStoreCodeU8At(lx,result.u8[2],tempu->ip+6);
          AsmStoreCodeU8At(lx,result.u8[3],tempu->ip+7);
        }
      }
    }
    ExpressionDel(tempu->exp);
    LinkedListDel(tempu->undef_hash);
    Free(tempu);
    tempu=tempu1;
  }

  tempess=lx->glbl_hash_table->next_added;
  while (tempess!=lx->glbl_hash_table) {
    if (tempess->type & HTT_IMPORT && tempess->use_cnt) {
      if (tempe=tempess->list) {
        if (tempess->import_name)
          tempe->str=StrNew(tempess->import_name);
        else
          tempe->str=StrNew(tempess->str);
        do {
          tempe1=tempe->next;
          InsQue(tempe,ex->last_ie);
        } while (tempe=tempe1);
        tempess->list=NULL;
      }
    } else if (tempess->type & HTT_EXPORT) {
      if (tempess->type & HTT_UNRESOLVED_GLBL) {
        PrintFErr("%S%s\n","ST_UNDEFINED_SYM",tempess->str);
        lx->error_cnt++;
        throw(EXCEPT_COMPILER,25);
      }
      tempe=CAlloc(sizeof(ExeImportExportStruct));
      tempe->type=EIE_REL_EXPORT;
      if (tempess->type & HTT_FUN) {
        tempc=tempess;
        tempe->ip=tempc->executable_addr;
        tempeu=tempc->ext_list;
        while (tempeu) {
          tempeu8=tempeu->next;
          j=tempc->executable_addr-(tempeu->ip+4);
          AsmStoreCodeU8At(lx,j.u8[0],tempeu->ip);
          AsmStoreCodeU8At(lx,j.u8[1],tempeu->ip+1);
          AsmStoreCodeU8At(lx,j.u8[2],tempeu->ip+2);
          AsmStoreCodeU8At(lx,j.u8[3],tempeu->ip+3);
          Free(tempeu);
          tempeu=tempeu8;
        }
      } else if (tempess->type & HTT_GLBL_VAR)
        tempe->ip=tempess><(GlblVarStruct *)->data_addr_ip;
      else
        tempe->ip=tempess->val;
      if (tempess->type & HTT_LITERAL)
        tempe->type++;
      tempe->str=StrNew(tempess->str);
      InsQue(tempe,ex->last_ie);
    }
    tempess=tempess->next_added;
  }
}

BoolI64 PrsAsmImm(LexStruct *lx,AsmArgStruct *arg,U64 ip)
{
  if (arg->imm_or_off_present)
    PrsExcept(lx,"ST_ALREADY_ONE_IMMEDIATE");
  arg->imm_or_off_present=TRUE;
  arg->num.undef_local=NULL;
  arg->num.undef_glbl=NULL;
  lx->instruction_ptr=ip;
  lx->undef_hash_entry=NULL;
  lx->abs_cnts=0;
  lx->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
  if (!GetExpression(lx,&arg->num.exp))
    LexSkipEol(lx);
  else {
    if (lx->abs_cnts.externs)
      PrsExcept(lx,"ST_EXTERNS_NOT_ALLOWED");
    if (!(lx->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
      arg->num.i=Call(arg->num.exp);
      arg->num.undef_glbl=lx->undef_hash_entry;
      lx->undef_hash_entry=NULL;
      ExpressionDel(arg->num.exp);
      arg->num.exp=NULL;
    } else {
      if (lx->flags & LF_UNRESOLVED_GLBL) {
        arg->num.undef_glbl=lx->undef_hash_entry;
        lx->undef_hash_entry=NULL;
        lx->a->has_locals=TRUE;
      } else if (lx->flags & LF_UNRESOLVED_LOCAL) {
        arg->num.undef_local=lx->undef_hash_entry;
        lx->undef_hash_entry=NULL;
      }
    }
  }
  return TRUE;
}

U0 PrsAsmArg(LexStruct *lx,AsmArgStruct *arg,U64 ip)
{
  MemSet(arg,0,sizeof(AsmArgStruct));
  arg->seg=CREG_NONE;
  arg->reg1=CREG_NONE;
  arg->reg2=CREG_NONE;
  arg->fstk=CREG_NONE;
  arg->scale=1;
  while (TRUE) {
    if (lx->token==TK_IDENT) {
      if (lx->hash_entry) {
        if (lx->hash_entry->type==HTT_R8) {
          arg->size=1;
          arg->reg1=lx->hash_entry->user_data0;
          Lex(lx);
          return;
        } else if (lx->hash_entry->type==HTT_R16) {
          arg->size=2;
          arg->reg1=lx->hash_entry->user_data0;
          Lex(lx);
          return;
        } else if (lx->hash_entry->type==HTT_R32) {
          arg->size=4;
          arg->reg1=lx->hash_entry->user_data0;
          Lex(lx);
          return;
        } else if (lx->hash_entry->type==HTT_R64) {
          arg->size=8;
          arg->reg1=lx->hash_entry->user_data0;
          Lex(lx);
          return;
        } else if (lx->hash_entry->type==HTT_SEG) {
          arg->seg=lx->hash_entry->user_data0;
          if (Lex(lx)!=':') {
            arg->just_seg=TRUE;
            return;
          } else
            Lex(lx); //skip ":"
        } else if (lx->hash_entry->type==HTT_FSTK) {
          arg->size=8;
          arg->fstk=lx->hash_entry->user_data0;
          Lex(lx);
          return;
        } else if (lx->hash_entry->type==HTT_ASM_KEYWORD) {
          switch (lx->hash_entry->user_data0) {
            case AKW_I8:
            case AKW_U8:
              arg->size=1;
              break;
            case AKW_I16:
            case AKW_U16:
              arg->size=2;
              break;
            case AKW_I32:
            case AKW_U32:
              arg->size=4;
              break;
            case AKW_I64:
            case AKW_U64:
              arg->size=8;
              break;
            default:
              PrsExcept(lx,"ST_SYNTAX_ERROR");
          }
          Lex(lx); //skip keyword
        } else {
          PrsAsmImm(lx,arg,ip);
          arg->num.abs_cnts=lx->abs_cnts;
          if (lx->token!='[')
            return;
        }
      } else {
        PrsAsmImm(lx,arg,ip);
        arg->num.abs_cnts=lx->abs_cnts;
        if (lx->token!='[')
          return;
      }
    } else if (lx->token=='[') {
      arg->indirect=TRUE;
      Lex(lx); // skip [
      while (lx->token && lx->token!=']') {
        if (lx->token==TK_IDENT) {
          if (lx->hash_entry) {
            if (lx->hash_entry->type==HTT_R16 ||
                lx->hash_entry->type==HTT_R32 ||
                lx->hash_entry->type==HTT_R64) {
              if (arg->reg1==CREG_NONE) {
                if (lx->hash_entry->user_data0&7==CREG_RSP) {
                  arg->reg1=4;
                  arg->reg2=lx->hash_entry->user_data0;
                } else
                  arg->reg1=lx->hash_entry->user_data0;
              } else
                arg->reg2=lx->hash_entry->user_data0;
              Lex(lx);
            } else {
              PrsAsmImm(lx,arg,ip);
              arg->num.abs_cnts=lx->abs_cnts;
            }
          } else {
            PrsAsmImm(lx,arg,ip);
            arg->num.abs_cnts=lx->abs_cnts;
          }
        } else if (lx->token=='*') {
          Lex(lx);
          if (lx->token!=TK_INTEGER&&lx->token!=TK_U8)
            PrsExcept(lx,"ST_EXPECTING_SCALE_FACTOR");
          arg->scale=lx->cur_i;
          Lex(lx); //skip scale
          if (arg->reg2!=CREG_NONE)
            SwapU64(&arg->reg1,&arg->reg2);
        } else if (lx->token=='+') {
          Lex(lx); //skip '+'
        } else {
          PrsAsmImm(lx,arg,ip);
          arg->num.abs_cnts=lx->abs_cnts;
        }
      }
      if (lx->token!=']')
        PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
      else {
        Lex(lx); //skip ]
        return;
      }
    } else {
      PrsAsmImm(lx,arg,ip);
      arg->num.abs_cnts=lx->abs_cnts;
      if (lx->token!='[')
        return;
    }
  }
}


U0 AsmMakeArgMask(LexStruct *lx,AsmArgStruct *arg,U64 *mask)
{
  AsmCtrlStruct *a=lx->a;
  if (arg->just_seg) {
    switch (arg->seg) {
      case 0: *mask=1<<ARGT_ES|1<<ARGT_SREG; break;
      case 1: *mask=1<<ARGT_CS|1<<ARGT_SREG; break;
      case 2: *mask=1<<ARGT_SS|1<<ARGT_SREG; break;
      case 3: *mask=1<<ARGT_DS|1<<ARGT_SREG; break;
      case 4: *mask=1<<ARGT_FS|1<<ARGT_SREG; break;
      case 5: *mask=1<<ARGT_GS|1<<ARGT_SREG; break;
    }
    return;
  }
  if (arg->fstk!=CREG_NONE) {
    if (arg->fstk)
      *mask=1<<ARGT_STI;
    else
      *mask=1<<ARGT_ST0|1<<ARGT_STI;
    return;
  }
  switch (arg->size) {
    case 0: *mask=0x3FF0FFFFFE; break;
    case 1: *mask=0x1110111112; break;
    case 2: *mask=0x2220222224; break;
    case 4: *mask=0x0440444448; break;
    case 8: *mask=0x0880888880; break;
  }
  if (a->seg_size==64)
    *mask&=  0xFF0FFFFFFF;

  if (arg->reg1!=CREG_NONE && arg->imm_or_off_present && !arg->num.i) {
    if (!arg->num.undef_glbl && !arg->num.undef_local)
      arg->imm_or_off_present=FALSE;  //Zero displacement
  }

  if (arg->reg2!=CREG_NONE || arg->scale!=1) {
    *mask&=  0x0000FF0000;
    return;
  }

  if (arg->indirect) {
    if (arg->imm_or_off_present)
      *mask&=0x00FFFF0000;
    else
      *mask&=0x000FFF0000;
  } else {
    if (arg->imm_or_off_present)
      *mask&=0x000F00F0FE;
    else
      *mask&=0x3F0FFF0F00;
  }
  if (arg->seg!=CREG_NONE)
    *mask&=  0x00FFFF0000;
  if (arg->reg1==CREG_NONE) {
    if (arg->indirect)
      *mask&=0x00FFFF0000;
    else if (MIN_I8<=arg->num.i<=MAX_I8)
      *mask&=0x000000F0FE;
    else if (MIN_I8<=arg->num.i<=MAX_U8)
      *mask&=0x000000E0FE;
    else if (MIN_I16<=arg->num.i<=MAX_I16)
      *mask&=0x000000E0EE;
    else if (MIN_I16<=arg->num.i<=MAX_U16)
      *mask&=0x000000C0EE;
    else if (MIN_I32<=arg->num.i<=MAX_I32)
      *mask&=0x000000C0CE;
    else if (MIN_I32<=arg->num.i<=MAX_U32)
      *mask&=0x00000080CE;
    else
      *mask&=0x000000808E;
  } else {
    *mask&=  0x3F00FF0F00;
    if (!arg->indirect) //M8-M64
      *mask&=  0xFFFF0FFFFF;
  }
  if (arg->reg1)
    *mask&=  0x30FFFFFFFF;
  if (arg->reg1!=1)
    *mask&=  0x2FFFFFFFFF;
  if (arg->reg1!=2)
    *mask&=  0x1FFFFFFFFF;
}

BoolI64 AsmStoreNum(LexStruct *lx,AsmNum2 *num2,I64 cnt,BoolI8 is_question,BoolI8 U8_avail)
{
  AsmCtrlStruct *a=lx->a;
  I64 i;
  ExeAbsAddrStruct *tempa;

  if (!num2->lit)
    num2->num.i-=num2->rel;
  for (i=0;i<cnt;i++) {
    if (num2->U8_cnt==1) {
      if (num2->num.undef_local)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U8+num2->lit,a->ip,num2->rel,
          num2->num.undef_local,LexLineNum(lx),U8_avail,FALSE);
      else if (num2->num.undef_glbl)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U8+num2->lit,a->ip,num2->rel,
          num2->num.undef_glbl,LexLineNum(lx),U8_avail,TRUE);
      else {
        if (!num2->lit && !(MIN_I8<=num2->num.i<=MAX_I8)) {
//        LexPop(lx);
          PrsExcept(lx,"ST_BRANCH_OUT_OF_RANGE");
        }
      }
      if (num2->lit) {
        if (num2->num.abs_cnts.abs_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_ADD_U8;
        }
      } else {
        if (num2->num.abs_cnts.c_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_SUB_U8;
        }
      }
      if (is_question)
        a->ip++;
      else
        AsmStoreCodeU8(lx,num2->num.i.u8[0]);

    } else if (num2->U8_cnt==2) {
      if (num2->num.undef_local)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U16+num2->lit,a->ip,num2->rel,
          num2->num.undef_local,LexLineNum(lx),U8_avail,FALSE);
      else if (num2->num.undef_glbl)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U16+num2->lit,a->ip,num2->rel,
          num2->num.undef_glbl,LexLineNum(lx),U8_avail,TRUE);
      else {
        if (!num2->lit && !(MIN_I16<=num2->num.i<=MAX_I16)) {
//        LexPop(lx);
          PrsExcept(lx,"ST_BRANCH_OUT_OF_RANGE");
        }
      }
      if (num2->lit) {
        if (num2->num.abs_cnts.abs_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_ADD_U16;
        }
      } else {
        if (num2->num.abs_cnts.c_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_SUB_U16;
        }
      }
      if (is_question)
        a->ip+=2;
      else {
        AsmStoreCodeU8(lx,num2->num.i.u8[0]);
        AsmStoreCodeU8(lx,num2->num.i.u8[1]);
      }
      if (U8_avail && !num2->num.undef_local && !num2->num.undef_glbl &&
          !num2->lit && -124<=num2->num.i<=123) {
//      LexPop(lx);
        PutAsmWarn(lx,"ST_COULD_USE_U8_DISP");
        return FALSE;
      }
    } else if (num2->U8_cnt==4) {
      if (num2->num.undef_local)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U32+num2->lit,a->ip,num2->rel,
          num2->num.undef_local,LexLineNum(lx),U8_avail,FALSE);
      else if (num2->num.undef_glbl)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U32+num2->lit,a->ip,num2->rel,
          num2->num.undef_glbl,LexLineNum(lx),U8_avail,TRUE);
      if (num2->lit) {
        if (num2->num.abs_cnts.abs_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_ADD_U32;
        }
      } else {
        if (num2->num.abs_cnts.c_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_SUB_U32;
        }
      }
      if (is_question)
        a->ip+=4;
      else
        AsmStoreCodeU32(lx,num2->num.i.u32[0]);
      if (U8_avail && !num2->num.undef_local && !num2->num.undef_glbl &&
          !num2->lit && -124<=num2->num.i<=123) {
//      LexPop(lx);
        PutAsmWarn(lx,"ST_COULD_USE_U8_DISP");
        return FALSE;
      }
    } else if (num2->U8_cnt==8) {
//TODO
      if (num2->num.undef_local)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U32+num2->lit,a->ip,num2->rel,
          num2->num.undef_local,LexLineNum(lx),U8_avail,FALSE);
      else if (num2->num.undef_glbl)
        AsmUnresolvedAdd(a,num2->num.exp,EIE_REL_U32+num2->lit,a->ip,num2->rel,
          num2->num.undef_glbl,LexLineNum(lx),U8_avail,TRUE);
      if (num2->lit) {
        if (num2->num.abs_cnts.abs_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_ADD_U64;
        }
      } else {
        if (num2->num.abs_cnts.c_addres & 1) {
          tempa=CAlloc(sizeof(ExeAbsAddrStruct));
          tempa->next=a->abss;
          a->abss=tempa;
          tempa->ip=a->ip;
          tempa->type=EAA_SUB_U64;
        }
      }
      if (is_question)
        a->ip+=8;
      else
        AsmStoreCodeU64(lx,num2->num.i);
      if (U8_avail && !num2->num.undef_local && !num2->num.undef_glbl &&
          !num2->lit && -124<=num2->num.i<=123) {
//      LexPop(lx);
        PutAsmWarn(lx,"ST_COULD_USE_U8_DISP");
        return FALSE;
      }
    }
  }
  return TRUE;
}

U8 asm_seg_prefixes[6]={0x26,0x2E,0x36,0x3E,0x64,0x65};

BoolI64 AsmCodeInstruction(LexStruct *lx,
                          OpcodeHashEntry *tempo,I64 argcnt)
{
  AsmCtrlStruct *a=lx->a;
  I64 i,j,a1,a2,om,seg;
  U64 arg1mask,arg2mask;
  AsmArgStruct *tempa1,*tempa2;
  BoolI8 ModrM_complete,U8_avail=FALSE,found_second_possible=FALSE;
  InstructionEntry *tempi;

  AsmIns cur,best;
  best.U8_cnt=255;

  if (argcnt>0)
    AsmMakeArgMask(lx,&a->arg1,&arg1mask);
  else
    arg1mask=1;
  if (argcnt>1)
    AsmMakeArgMask(lx,&a->arg2,&arg2mask);
  else
    arg2mask=1;
  for (i=0;i<tempo->instruction_entry_cnt;i++) {
    tempi=&tempo->ins[i];
    if (tempi->arg1==ARGT_REL8 || tempi->arg2==ARGT_REL8)
      U8_avail=TRUE;
    if (Bt(&arg1mask,tempi->arg1) && Bt(&arg2mask,tempi->arg2)) {
      MemSet(&cur,0,sizeof(AsmIns));
      cur.tempi=tempi;
      ModrM_complete=FALSE;
      cur.is_dft=ToBool(tempi->flags & IEF_DFT);
      if (a->seg_size==64) {
        if (tempi->flags & IEF_48_REX)
          cur.REX=0x48;
        else if (!(tempi->flags & IEF_NO_REX))
          cur.REX=0x40;
      }
      cur.disp.lit=1;
      cur.imm.lit=1;
      om=tempi->opcode_modifier;
      a1=tempi->arg1;
      a2=tempi->arg2;
      tempa1=&a->arg1;
      tempa2=&a->arg2;
      cur.last_opcode_U8=tempi->opcode[tempi->opcode_cnt-1];

      if (tempi->slash_val<8) {
        cur.ModrM|=tempi->slash_val<<3;
        cur.has_ModrM=TRUE;
      }

      if (a->seg_size==16 && tempi->flags & IEF_OP_SIZE32 ||
          a->seg_size!=16 && tempi->flags & IEF_OP_SIZE16)
        cur.has_operand_prefix=TRUE;

      if (om==OM_IB)      cur.imm.U8_cnt=1;
      else if (om==OM_IW) cur.imm.U8_cnt=2;
      else if (om==OM_ID) cur.imm.U8_cnt=4;

      if (om==OM_CB) {
        cur.imm.U8_cnt=1;
        cur.imm.lit=0;
      } else if (om==OM_CW) {
        cur.imm.U8_cnt=2;
        cur.imm.lit=0;
      } else if (om==OM_CD) {
        cur.imm.U8_cnt=4;
        cur.imm.lit=0;
      }

      if (argcnt==1) {
        if (best.U8_cnt!=255 && !found_second_possible && !best.is_dft) {
          found_second_possible=TRUE;
          if (!a->arg1.size)
            PrintFWarn("%S%s,%04d\n","ST_NO_SIZE_SPECIFIED",
                   lx->cur_lfn->name,lx->cur_lfn->line_num-1);
        }
        if (tempi->flags & IEF_PLUS_OPCODE) {
          if (om==OM_I) {
            if (tempa1->fstk!=CREG_NONE)
              cur.last_opcode_U8+=tempa1->fstk;
          } else {
            cur.last_opcode_U8|=tempa1->reg1&7;
            if (tempa1->reg1&15>7)
              cur.REX|=1;
            if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
              cur.has_REX=TRUE;
          }
        }
        if (a1==ARGT_R64 || a1==ARGT_RM64 || a1==ARGT_M64)
          cur.REX|=8;
        if (ARGT_RM8<=a1<=ARGT_RM64 || ARGT_M8<=a1<=ARGT_M64) {
          if (a->seg_size==16)
            cur.has_addr_prefix=TRUE;

          cur.has_ModrM=TRUE;
          if (tempa1->imm_or_off_present && tempa1->indirect && tempa1->reg1==CREG_NONE) {
            cur.ModrM=cur.ModrM+5;
            MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
            cur.disp.U8_cnt=4;
            if (a->seg_size==64)
              cur.disp.lit=0;
          } else {
            if (tempa1->reg2==CREG_NONE && tempa1->scale==1) {
              cur.ModrM|=tempa1->reg1&7;
              if (tempa1->reg1&15>7)
                cur.REX|=1;
              if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                cur.has_REX=TRUE;
            } else {
              cur.ModrM|=4;
              cur.has_SIB=TRUE;
              if (tempa1->scale==1)
                cur.SIB=0;
              else if (tempa1->scale==2)
                cur.SIB=0x40;
              else if (tempa1->scale==4)
                cur.SIB=0x80;
              else if (tempa1->scale==8)
                cur.SIB=0xC0;
              if (tempa1->reg2==CREG_NONE) {
                ModrM_complete=TRUE;
                cur.SIB|=(tempa1->reg1&7)<<3+CREG_RBP;
                if (tempa1->reg1&15>7)
                  cur.REX|=2;
                if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
                cur.disp.U8_cnt=4;
              } else {
                cur.SIB|=(tempa1->reg1&7)<<3+tempa1->reg2&7;
                if (tempa1->reg1&15>7)
                  cur.REX|=2;
                if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                if (tempa1->reg2&15>7)
                  cur.REX|=1;
                if (tempa1->reg2>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                if (tempa1->reg2&7==CREG_RBP && !tempa1->imm_or_off_present && tempa1->indirect) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                  ModrM_complete=TRUE;
                }
              }
            }
            if (!ModrM_complete) {
              if (tempa1->imm_or_off_present) {
                MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
                if (!cur.disp.num.exp && MIN_I8<=cur.disp.num.i<=MAX_I8) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                } else if (a->seg_size==16) {
                  cur.ModrM|=0x80;
                  cur.disp.U8_cnt=2;
                } else {
                  cur.ModrM|=0x80;
                  cur.disp.U8_cnt=4;
                }
              } else if (!tempa1->indirect) {
                cur.has_addr_prefix=FALSE;
                cur.ModrM|=0xC0;
              } else {
                if (tempa1->reg1&7==CREG_RBP) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                }
              }
            }
          }
        } else if (ARGT_REL8<=a1<=ARGT_REL32 ||
                   ARGT_IMM8<=a1<=ARGT_IMM64 ||
                   ARGT_UIMM8<=a1<=ARGT_UIMM64) {
          if (a1==ARGT_IMM64 || a2==ARGT_UIMM64)
            cur.REX|=8;
          MemCpy(&cur.imm.num,&tempa1->num,sizeof(AsmNum));
        }
      } else if (argcnt==2) {
        if (best.U8_cnt!=255 && !found_second_possible && !best.is_dft) {
          found_second_possible=TRUE;
          if (!a->arg1.size && !a->arg2.size)
            PrintFWarn("%S%s,%04d\n","ST_NO_SIZE_SPECIFIED",
              lx->cur_lfn->name,lx->cur_lfn->line_num-1);
        }
        if (tempi->flags & IEF_PLUS_OPCODE) {
          if (OM_RB<=om<=OM_RD) {
            cur.last_opcode_U8|=tempa1->reg1&7;
            if (tempa1->reg1&15>7)
              cur.REX|=1;
            if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
              cur.has_REX=TRUE;
          } else if (om==OM_I) {
            if (tempa1->fstk!=CREG_NONE)
              cur.last_opcode_U8|=tempa1->fstk;
            if (tempa2->fstk!=CREG_NONE)
              cur.last_opcode_U8|=tempa2->fstk;
          }
          else if (tempi->slash_val==SV_REGISTER) {
            if (ARGT_AL<=a1<=ARGT_EAX) {
              cur.last_opcode_U8|=tempa2->reg1&7;
              if (tempa2->reg1&15>7)
                cur.REX|=1;
              if (tempa2->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                cur.has_REX=TRUE;
            } else if (ARGT_AL<=a2<=ARGT_EAX) {
              cur.last_opcode_U8|=tempa1->reg1&7;
              if (tempa1->reg1&15>7)
                cur.REX|=1;
              if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                cur.has_REX=TRUE;
            }
          }
        }
        if (a1==ARGT_RM64 || a2==ARGT_RM64 ||
            a1==ARGT_M64 || a2==ARGT_M64 ||
            a1==ARGT_R64 || a2==ARGT_R64)
          cur.REX|=8;
        if (ARGT_RM8<=a1<=ARGT_RM64 || ARGT_RM8<=a2<=ARGT_RM64 ||
            ARGT_M8 <=a1<=ARGT_M64  || ARGT_M8 <=a2<=ARGT_M64) {
          if (a->seg_size==16)
            cur.has_addr_prefix=TRUE;
          cur.has_ModrM=TRUE;
          if (ARGT_RM8<=a2<=ARGT_RM64 || ARGT_M8<=a2<=ARGT_M64) {
            tempa1=&a->arg2;
            tempa2=&a->arg1;
          }
          if (tempi->slash_val==SV_REGISTER) {
            if (tempa2->just_seg)
              cur.ModrM|=tempa2->seg<<3;
            else {
              if (tempa2->reg1==CREG_NONE) {
                cur.ModrM|=(tempa1->reg1&7)<<3;
                if (tempa1->reg1&15>7)
                  cur.REX|=4;
                if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
              } else {
                cur.ModrM|=(tempa2->reg1&7)<<3;
                if (tempa2->reg1&15>7)
                  cur.REX|=4;
                if (tempa2->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
              }
            }
          }
          if (tempa1->reg2==CREG_NONE && tempa1->scale==1) {
            if (tempa1->reg1!=CREG_NONE) {
              cur.ModrM|=tempa1->reg1&7;
              if (tempa1->reg1&15>7)
                cur.REX|=1;
              if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                cur.has_REX=TRUE;
            }
          } else {
            cur.ModrM|=4;
            cur.has_SIB=TRUE;
            if (tempa1->scale==1)
              cur.SIB=0;
            else if (tempa1->scale==2)
              cur.SIB=0x40;
            else if (tempa1->scale==4)
              cur.SIB=0x80;
            else if (tempa1->scale==8)
              cur.SIB=0xC0;
              if (tempa1->reg2==CREG_NONE) {
                ModrM_complete=TRUE;
                cur.SIB|=(tempa1->reg1&7)<<3+5;
                if (tempa1->reg1&15>7)
                  cur.REX|=2;
                if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
                cur.disp.U8_cnt=4;
              } else {
                cur.SIB|=(tempa1->reg1&7)<<3+tempa1->reg2&7;
                if (tempa1->reg1&15>7)
                  cur.REX|=2;
                if (tempa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                if (tempa1->reg2&15>7)
                  cur.REX|=1;
                if (tempa1->reg2>=20) //RBPu8,RSPu8,RSIu8,RDIu8?
                  cur.has_REX=TRUE;
                if (tempa1->reg2&7==CREG_RBP && !tempa1->imm_or_off_present && tempa1->indirect) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                  ModrM_complete=TRUE;
                }
              }
          }
          if (!ModrM_complete) {
            if (tempa1->imm_or_off_present && tempa1->indirect && tempa1->reg1==CREG_NONE) {
              cur.ModrM=cur.ModrM&0xF8+5;
              MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
              cur.disp.U8_cnt=4;
              if (a->seg_size==64)
                cur.disp.lit=0;
            } else {
              if (tempa1->imm_or_off_present) {
                MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
                if (!cur.disp.num.exp && MIN_I8<=cur.disp.num.i<=MAX_I8) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                } else if (a->seg_size==16) {
                  cur.ModrM|=0x80;
                  cur.disp.U8_cnt=2;
                } else {
                  cur.ModrM|=0x80;
                  cur.disp.U8_cnt=4;
                }
              } else if (!tempa1->indirect) {
                cur.has_addr_prefix=FALSE;
                cur.ModrM|=0xC0;
              } else {
                if (tempa1->reg1&7==CREG_RBP) {
                  cur.ModrM|=0x40;
                  cur.disp.U8_cnt=1;
                }
              }
            }
          }
        } else if (ARGT_MOFFS8<=a1<=ARGT_MOFFS64) {
          MemCpy(&cur.disp.num,&tempa1->num,sizeof(AsmNum));
          if (a->seg_size==16)
            cur.disp.U8_cnt=2;
          else
            cur.disp.U8_cnt=4;
          cur.has_addr_prefix=FALSE;
        } else if (ARGT_MOFFS8<=a2<=ARGT_MOFFS64) {
          MemCpy(&cur.disp.num,&tempa2->num,sizeof(AsmNum));
          if (a->seg_size==16)
            cur.disp.U8_cnt=2;
          else
            cur.disp.U8_cnt=4;
          cur.has_addr_prefix=FALSE;
        } else if (ARGT_IMM8<=a1<=ARGT_IMM64 ||
                   ARGT_UIMM8<=a1<=ARGT_UIMM64) {
          MemCpy(&cur.imm.num,&tempa1->num,sizeof(AsmNum));
          if (a1==ARGT_IMM8 || a1==ARGT_UIMM8) cur.imm.U8_cnt=1;
          else if (a1==ARGT_IMM16 || a1==ARGT_UIMM16) cur.imm.U8_cnt=2;
          else if (a1==ARGT_IMM32 || a1==ARGT_UIMM32) cur.imm.U8_cnt=4;
          else {
            cur.imm.U8_cnt=8;
            cur.REX|=8;
          }
        }
        if (ARGT_IMM8<=a2<=ARGT_IMM64 ||
            ARGT_UIMM8<=a2<=ARGT_UIMM64) {
          MemCpy(&cur.imm.num,&tempa2->num,sizeof(AsmNum));
          if (a2==ARGT_IMM8 || a2==ARGT_UIMM8) cur.imm.U8_cnt=1;
          else if (a2==ARGT_IMM16 || a2==ARGT_UIMM16) cur.imm.U8_cnt=2;
          else if (a2==ARGT_IMM32 || a2==ARGT_UIMM32) cur.imm.U8_cnt=4;
          else {
            cur.imm.U8_cnt=8;
            cur.REX|=8;
          }
        }
      }
      cur.U8_cnt=tempi->opcode_cnt+cur.disp.U8_cnt+cur.imm.U8_cnt;
      if (cur.has_ModrM) cur.U8_cnt++;
      if (cur.has_SIB) cur.U8_cnt++;
      if (a->seg_size==64 && cur.REX&0x40==0x40 &&
          (cur.REX!=0x40 || tempi->flags&IEF_40_REX || cur.has_REX) &&
          (cur.REX&7 || !(tempi->flags&IEF_REX_ONLY_R8_R15 ||
                      tempi->flags&IEF_REX_XOR_LIKE && tempa1->reg1==tempa2->reg1 && cur.ModrM&0xC0==0xC0)))
          cur.U8_cnt++;
      if (cur.U8_cnt<best.U8_cnt &&
         !(tempi->flags & IEF_DONT_SWITCH_MODES &&
          (cur.has_addr_prefix || cur.has_operand_prefix)))
        MemCpy(&best,&cur,sizeof(AsmIns));
    }
  }
  if (best.U8_cnt<255) {
    tempi=best.tempi;
    seg=CREG_NONE;
    if (argcnt>1 && a->arg2.seg!=CREG_NONE && !a->arg2.just_seg)
      seg=a->arg2.seg;
    else if (argcnt>0 && a->arg1.seg!=CREG_NONE && !a->arg1.just_seg)
      seg=a->arg1.seg;
    if (seg!=CREG_NONE)
      AsmStoreCodeU8(lx,asm_seg_prefixes[seg]);
    if (best.has_operand_prefix)
      AsmStoreCodeU8(lx,OC_OP_SIZE_PREFIX); //Operand size override
    if (best.has_addr_prefix  || a->seg_size==16 && cur.has_SIB)
      AsmStoreCodeU8(lx,OC_ADDR_SIZE_PREFIX); //Operand size override
    if (a->seg_size==64 && best.REX&0x40==0x40 &&
        (best.REX!=0x40 || tempi->flags&IEF_40_REX || best.has_REX) &&
        (best.REX&7||!(tempi->flags&IEF_REX_ONLY_R8_R15 ||
                    tempi->flags&IEF_REX_XOR_LIKE && tempa1->reg1==tempa2->reg1 && best.ModrM&0xC0==0xC0)))
        AsmStoreCodeU8(lx,best.REX);
    for (j=0;j<tempi->opcode_cnt-1;j++)
      AsmStoreCodeU8(lx,tempi->opcode[j]);
    AsmStoreCodeU8(lx,best.last_opcode_U8);

    if (best.has_ModrM)
      AsmStoreCodeU8(lx,best.ModrM);
    if (best.has_SIB)
      AsmStoreCodeU8(lx,best.SIB);

    if (best.disp.U8_cnt) {
      best.disp.rel=a->ip+best.disp.U8_cnt+best.imm.U8_cnt;
      if (!AsmStoreNum(lx,&best.disp,1,FALSE,U8_avail))
        return FALSE;
    }

    if (best.imm.U8_cnt) {
      best.imm.rel=a->ip+best.imm.U8_cnt;
      if (!AsmStoreNum(lx,&best.imm,1,FALSE,U8_avail))
        return FALSE;
    }
    if (tempi->flags&IEF_ENDING_ZERO) //ENTER instruction
      AsmStoreCodeU8(lx,0);
    return TRUE;
  }
//  LexPop(lx);
  PrsExcept(lx,"ST_INVALID_INSTRUCTION");
}


U0 DefineU8s(LexStruct *lx,I64 U8_cnt)
{
  AsmCtrlStruct *a=lx->a;
  BoolI8 is_question,is_dup;
  I64 i,dup_val;
  U8 *ptr;
  AsmNum2 num2;
  num2.U8_cnt=U8_cnt;

  while (lx->token && lx->token!=';') {
    lx->instruction_ptr=a->ip;
    num2.num.undef_local=NULL;
    num2.num.undef_glbl=NULL;
    if (lx->token==TK_STR) {
      ptr=lx->ident;
      i=lx->ident_len-1;
      while (i--)
        AsmStoreCodeU8(lx,*ptr++);
      Lex(lx);  //Skip Str
    } else {
      is_question=FALSE;
      is_dup=FALSE;
      lx->abs_cnts=0;
      if (lx->token=='?') {
        is_question=TRUE;
        Lex(lx);
      } else {
        lx->undef_hash_entry=NULL;
        lx->flags=lx->flags & ~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
        if (!GetExpression(lx,&num2.num.exp))
          LexSkipEol(lx);
        else {
          if (lx->abs_cnts.externs)
            PrsExcept(lx,"ST_EXTERNS_NOT_ALLOWED");
          if (lx->flags & (LF_UNRESOLVED_LOCAL | LF_UNRESOLVED_GLBL)) {
            if (lx->flags & LF_UNRESOLVED_LOCAL) {
              num2.num.undef_local=lx->undef_hash_entry;
              lx->undef_hash_entry=NULL;
              a->has_locals=TRUE;
            } else if (lx->flags & LF_UNRESOLVED_GLBL) {
              num2.num.undef_glbl=lx->undef_hash_entry;
              lx->undef_hash_entry=NULL;
            }
          } else {
            i=Call(num2.num.exp);
            ExpressionDel(num2.num.exp);
          }
        }
      }
      if (lx->token==TK_IDENT && lx->hash_entry) {
        if (lx->hash_entry->type & HTT_ASM_KEYWORD && lx->hash_entry->user_data0==AKW_DUP) {
          if (is_question)
            PrsExcept(lx,"ST_QUESTION_NOT_ALLOWED");
          is_dup=TRUE;
          if (Lex(lx)!='(')
            PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN");
          if (Lex(lx)=='?') {
            is_question=TRUE;
            Lex(lx);  //SKIP "?"
          } else
            dup_val=AsmExpressionEval(lx);
          if (lx->token!=')')
            PrsExcept(lx,"ST_EXPECTING_RIGHT_PAREN");
          Lex(lx); //SKIP ')'
        }
      }
      num2.rel=0;
      num2.lit=1;
      num2.num.abs_cnts=lx->abs_cnts;
      if (is_dup) {
        if (num2.num.undef_local || num2.num.undef_glbl)
          PrsExcept(lx,"ST_UNDEFINED_DUP_CNT");
        num2.num.i=dup_val;
        AsmStoreNum(lx,&num2,i,is_question,FALSE);
      } else {
        num2.num.i=i;
        AsmStoreNum(lx,&num2,1,is_question,FALSE);
      }
    }
    if (lx->token==',')
      Lex(lx);
  }
  if (lx->token!=';')
    PrsExcept(lx,"ST_MISSING_SEMICOLON");
  else
    Lex(lx);
}

U0 PrsAsmBlk(LexStruct *lx)
{
  AsmCtrlStruct *a=lx->a;
  I64 i,j,k;
  OpcodeHashEntry *tempo;
  ExportSysSymHashEntry *tempess;
  U64 argcnt,saved_ip;
  BoolI8 is_literal;
  U64 old_hash_mask=lx->hash_mask;
  U64 old_flags=lx->flags & LF_ASM_EXPRESSIONS;
  U8 *next_last_label;

  a->seg_size=64;
  lx->flags|=LF_ASM_EXPRESSIONS;
  lx->hash_mask=lx->hash_mask&~(HTT_PUBLIC|HTT_FILE|HTT_INTERNAL_TYPE|
      HTT_MODULE|HTT_PRIVATE|HTT_EXPORT|HTT_IMPORT)|HTT_ASM_KEYWORD;
  if (lx->token!='{')
    PrsExcept(lx,"ST_MISSING_RIGHT_BRACE");
  else
    Lex(lx);
  while (lx->token && lx->token!='}') {
    AsmLineList(lx);
    if (lx->token==TK_IDENT && lx->hash_entry) {
      if (lx->hash_entry->type&HTT_ASM_KEYWORD) {
        i=lx->hash_entry->user_data0;
        Lex(lx); //skip keyword
        switch (i) {
          case AKW_IMPORT:
          case AKW_EXPORT:
            while (lx->token && lx->token!=';') {
              if (lx->token=='#') {
                is_literal=TRUE;
                Lex(lx);
              } else
                is_literal=FALSE;
              if (lx->token!=TK_IDENT)
                PrsExcept(lx,"ST_EXPECTING_IDENTIFIER");
              else {
                if (i==AKW_IMPORT)
                  tempess=NULL;
                else if (tempess=lx->hash_entry) {
                  if (tempess=HashFind(lx->ident,lx->glbl_hash_table,HTT_EXPORT_SYS_SYM))
                    tempess->type=HTT_EXPORT_SYS_SYM|HTT_UNRESOLVED_GLBL;
                }
                if (!tempess) {
                  tempess=CAlloc(sizeof(ExportSysSymHashEntry));
                  tempess->str=lx->ident;
                  lx->ident=0;
                  tempess->type=HTT_EXPORT_SYS_SYM|HTT_UNRESOLVED_GLBL;
                  HashAdd(tempess,lx->glbl_hash_table);
                }
                if (i==AKW_IMPORT)
                  tempess->type|=HTT_IMPORT;
                else if (i==AKW_EXPORT)
                  tempess->type|=HTT_EXPORT;
                if (is_literal)
                  tempess->type|=HTT_LITERAL;
                if (Lex(lx)==',')
                  Lex(lx); //skip ','
              }
            }
            if (lx->token!=';')
              PrsExcept(lx,"ST_MISSING_SEMICOLON");
            else
              Lex(lx); //skip ';';
            break;
          case AKW_ALIGN:
            if (lx->local_var_list)
              PrsExcept(lx,"ST_NO_FUN_ASM_ALIGN");
            i=AsmExpressionEval(lx);
            if (Bsf(i)!=Bsr(i))
              PrsExcept(lx,"ST_ALIGN_MUST_BE_POWER_OF_TWO");
            if (!(lx->flags&LF_STATIC_COMPILE) && i>8)
              PrsExcept(lx,"ST_ALIGN_TOO_LARGE");
            if (i>a->max_align) a->max_align=i;
            i=CeilU64(a->ip,i);
            if (lx->token==',')
              Lex(lx);
            if (lx->token=='?') {
              Lex(lx);
              a->ip=i;
            } else {
              k=AsmExpressionEval(lx);
              for (j=a->ip;j<i;j++)
                AsmStoreCodeU8(lx,k);
            }
            break;
          case AKW_END:
            break; //TODO
          case AKW_DU8:
            DefineU8s(lx,1);
            break;
          case AKW_DU16:
            DefineU8s(lx,2);
            break;
          case AKW_DU32:
            DefineU8s(lx,4);
            break;
          case AKW_DU64:
            DefineU8s(lx,8);
            break;
          case AKW_LIST:
            a->list=TRUE;
            break;
          case AKW_NOLIST:
            a->list=FALSE;
            break;
          case AKW_STRUC:
            a->flags|=ACSF_IN_STRUCT;
            saved_ip=a->ip;
            a->ip=AsmExpressionEval(lx);
            break;
          case AKW_ENDS:
            a->ip=saved_ip;
            a->flags&=~ACSF_IN_STRUCT;
            break;
          case AKW_USE16:
            a->seg_size=16;
            break;
          case AKW_USE32:
            a->seg_size=32;
            break;
          case AKW_USE64:
            a->seg_size=64;
            break;
          default:
            PrsExcept(lx,"ST_SYNTAX_ERROR");
        }
      } else if (lx->hash_entry->type & HTT_OPCODE) {
        tempo=lx->hash_entry;
        Lex(lx); //skip opcode
        argcnt=0;
        if (tempo->ins[0].arg1) {
          argcnt++;
          PrsAsmArg(lx,&a->arg1,a->ip);
          if (tempo->ins[0].arg2) {
            argcnt++;
            if (lx->token!=',')
              PrsExcept(lx,"ST_EXPECTING_COMMA");
            else {
              Lex(lx); //skip ','
              PrsAsmArg(lx,&a->arg2,a->ip);
            }
          }
        }
        AsmCodeInstruction(lx,tempo,argcnt);
      } else if (lx->hash_entry->type & HTT_EXPORT_SYS_SYM) {
        if (a->flags & ACSF_IN_STRUCT)
          lx->hash_entry->type|=HTT_LITERAL;
        else
          lx->hash_entry->type&=~HTT_LITERAL;
        if (lx->hash_entry->type & HTT_UNRESOLVED_LOCAL) {
          lx->hash_entry->type&=~HTT_UNRESOLVED_LOCAL;
          lx->hash_entry><(ExportSysSymHashEntry *)->val=a->ip;
          if (Lex(lx)!=':')
            PrsExcept(lx,"ST_EXPECTING_COLON");
          Lex(lx);
        } else if (lx->hash_entry->type & HTT_UNRESOLVED_GLBL) {
          if (lx->hash_entry->type & HTT_IMPORT)
            PrsExcept(lx,"ST_ATTEMPT_DEFINE_IMPORT");
          lx->hash_entry->type&=~HTT_UNRESOLVED_GLBL;
          lx->hash_entry><(ExportSysSymHashEntry *)->val=a->ip;
          next_last_label=lx->hash_entry->str;
          Lex(lx); //Skip ident
          if (lx->token!=':' && lx->token!=TK_DBL_COLON)
            PrsExcept(lx,"ST_EXPECTING_COLON");
          if (lx->token==TK_DBL_COLON) {
            lx->hash_entry->type|=HTT_EXPORT;
            AsmLocalsResolve(lx);
            a->last_label=next_last_label;
          }
          if (Lex(lx)=='#') {
            Lex(lx);
            lx->hash_entry->type|=HTT_LITERAL | HTT_EXPORT;
          }
        } else
          PrsExcept(lx,"ST_REDEFINITION");
      } else
        PrsExcept(lx,"ST_SYNTAX_ERROR");
    } else {
      if (lx->token==TK_IDENT) {
        tempess=CAlloc(sizeof(ExportSysSymHashEntry));
        tempess->str=lx->ident;
        lx->ident=0;
        tempess->type=HTT_EXPORT_SYS_SYM;
        if (a->flags & ACSF_IN_STRUCT)
          tempess->type|=HTT_LITERAL;
        tempess->val=a->ip;
        Lex(lx);  //Skip ident
        if (lx->token!=':' && lx->token!=TK_DBL_COLON)
          PrsExcept(lx,"ST_EXPECTING_COLON");
        else {
          if (*tempess->str=='@' && tempess->str[1]=='@') {
            if (lx->token==TK_DBL_COLON)
              PrsExcept(lx,"ST_NO_LOCAL_GLBL_EXPORT");
            HashAdd(tempess,lx->local_hash_table);
            a->has_locals=TRUE;
          } else
            HashAdd(tempess,lx->glbl_hash_table);
          if (lx->token==TK_DBL_COLON) {
            tempess->type|=HTT_EXPORT;
            AsmLocalsResolve(lx);
            a->last_label=tempess->str;
            Lex(lx);
          } else {
            if (Lex(lx)=='#') {
              tempess->type|=HTT_EXPORT | HTT_LITERAL;
              AsmLocalsResolve(lx);
              a->last_label=tempess->str;
              Lex(lx);
            }
          }
        }
      } else if (lx->token==';')
        Lex(lx);
      else
        PrsExcept(lx,"ST_SYNTAX_ERROR");
    }
  }
  AsmLocalsResolve(lx);
  AsmReserveCodeTo(lx,a->ip);
  lx->flags&=lx->flags&~LF_ASM_EXPRESSIONS|old_flags;
  lx->hash_mask=old_hash_mask;
}

Historical capture: 2012-03-02. Home | Power on LoseThos | Sources and changes