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->s.h.type & HTT_IMPORT) { tempu->str=StrNew(undef_hash->hash->s.h.str); if (undef_hash->hash->s.h.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; PrintF("%08X ",a->last_ip); cl3=LexPutLine(lx,cl3); } } else { while (*cl3><(U8 *) && cl3!=cl) { Spaces(24-a->display_col); a->display_col=0; PrintF("%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) { CrLf; a->display_col=0; } PrintF("%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 *dd; 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; } dd=tempc->body+ a->ip&(ASM_CODE_BLK_SIZE-1); *dd=d; a->ip+=sizeof(U32); if (a->list) { if (a->display_col>=24) { CrLf; a->display_col=0; } PrintF("%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 *dd; 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; } dd=tempc->body+ a->ip&(ASM_CODE_BLK_SIZE-1); *dd=d; a->ip+=sizeof(U64); if (a->list) { if (a->display_col>=24) { CrLf; a->display_col=0; } PrintF("%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->s.h.type & (HTT_UNRESOLVED_LOCAL | HTT_UNRESOLVED_GLBL)) { PrintFErr("%S%S%04d ","ST_UNDEFINED_SYM","ST_LINE",tempu->line_num); if (a->last_label) cout a->last_label," "; coutln templu->hash->s.h.str; lx->error_cnt++; FlushMsgs; throw(EXCEPT_COMPILER,21); } label=templu->hash->s.h.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) PrintF("%s ",a->last_label); if (label) cout label; CrLf; 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) PrintF("%s ",a->last_label); if (label) cout label; CrLf; } } 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->s.h.type & (HTT_UNRESOLVED_LOCAL | HTT_UNRESOLVED_GLBL)) { tempess=templu->hash; if (tempess->s.h.type & HTT_EXPORT_SYS_SYM && tempess->s.h.type & HTT_UNRESOLVED_GLBL && !(tempess->s.h.type & HTT_IMPORT) && (tempc=HashFind(tempess->s.h.str,lx->hash_table_list,HTT_FUN)) && !Bt(tempc->flags,Cf_EXTERN)) { tempess->val=tempc->executable_address; tempess->s.h.type&=~HTT_UNRESOLVED_GLBL; label=templu->hash->s.h.str; } else { if (!(tempess->s.h.type & HTT_IMPORT)) { PrintFErr("%S%S%04d ","ST_UNDEFINED_SYM","ST_LINE",tempu->line_num); cout tempess->s.h.str,"\r\n"; lx->error_cnt++; FlushMsgs; throw(EXCEPT_COMPILER,23); } undefined=TRUE; } } else label=templu->hash->s.h.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->s.h.type & HTT_IMPORT) { tempe=CAlloc(sizeof(ExeImportExportStruct)); tempe->next=templu->hash->s.list; templu->hash->s.list=tempe; tempe->ip=tempu->ip; tempe->type=tempu->type; } } else { if (!(tempu->type & 1)) { 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) cout label; CrLf; 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) PrintF("%s ",a->last_label); if (label) cout label; CrLf; } } } 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; } tempess=lx->glbl_hash_table->next_added; while (tempess!=lx->glbl_hash_table) { if (tempess->s.h.type & HTT_IMPORT && tempess->s.h.use_cnt) { if (tempe=tempess->s.list) { if (tempess->s.import_name) tempe->str=StrNew(tempess->s.import_name); else tempe->str=StrNew(tempess->s.h.str); do { tempe1=tempe->next; InsQue(tempe,ex->last_ie); } while (tempe=tempe1); tempess->s.list=NULL; } } else if (tempess->s.h.type & HTT_EXPORT) { if (tempess->s.h.type & HTT_UNRESOLVED_GLBL) { PrintFErr("%S%s\r\n","ST_UNDEFINED_SYM",tempess->s.h.str); lx->error_cnt++; throw(EXCEPT_COMPILER,25); } tempe=CAlloc(sizeof(ExeImportExportStruct)); tempe->type=EIE_REL_EXPORT; if (tempess->s.h.type & HTT_FUN) { tempc=tempess; tempe->ip=tempc->executable_address; tempeu=tempc->ext_list; while (tempeu) { tempeu8=tempeu->next; j=tempc->executable_address-(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->s.h.type & HTT_GLBL_VAR) tempe->ip=tempess><(GlblVarStruct *)->data_address_ip; else tempe->ip=tempess->val; if (tempess->s.h.type & HTT_LITERAL) tempe->type++; tempe->str=StrNew(tempess->s.h.str); InsQue(tempe,ex->last_ie); } tempess=tempess->s.h.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->h.type==HTT_R8) { arg->size=1; arg->reg1=lx->hash_entry->user_data0; Lex(lx); return; } else if (lx->hash_entry->h.type==HTT_R16) { arg->size=2; arg->reg1=lx->hash_entry->user_data0; Lex(lx); return; } else if (lx->hash_entry->h.type==HTT_R32) { arg->size=4; arg->reg1=lx->hash_entry->user_data0; Lex(lx); return; } else if (lx->hash_entry->h.type==HTT_R64) { arg->size=8; arg->reg1=lx->hash_entry->user_data0; Lex(lx); return; } else if (lx->hash_entry->h.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->h.type==HTT_FSTK) { arg->size=8; arg->fstk=lx->hash_entry->user_data0; Lex(lx); return; } else if (lx->hash_entry->h.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->h.type==HTT_R16 || lx->hash_entry->h.type==HTT_R32 || lx->hash_entry->h.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=='*') { if (Lex(lx)!=TK_INTEGER) 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; ExeAbsoluteAddressStruct *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.absolute_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip; tempa->type=EAA_ADD_U8; } } else { if (num2->num.abs_cnts.c_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=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.absolute_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip; tempa->type=EAA_ADD_U16; } } else { if (num2->num.abs_cnts.c_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=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.absolute_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip; tempa->type=EAA_ADD_U32; } } else { if (num2->num.abs_cnts.c_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=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.absolute_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=tempa; tempa->ip=a->ip; tempa->type=EAA_ADD_U64; } } else { if (num2->num.abs_cnts.c_addresses & 1) { tempa=CAlloc(sizeof(ExeAbsoluteAddressStruct)); tempa->next=a->absolutes; a->absolutes=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; } 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\r\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_address_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_address_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\r\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_address_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_address_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_address_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_address_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_address_prefix || cur.has_operand_prefix))) MemCpy(&best,&cur,sizeof(AsmIns)); } } if (best.U8_cnt<255) { tempi=best.tempi; if (best.has_operand_prefix) AsmStoreCodeU8(lx,0x66); //Operand size override if (best.has_address_prefix || a->seg_size==16 && cur.has_SIB) AsmStoreCodeU8(lx,0x67); //Operand size override 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) { if (seg==0) AsmStoreCodeU8(lx,0x26); //ES: else if (seg==1) AsmStoreCodeU8(lx,0x2E); //CS: else if (seg==2) AsmStoreCodeU8(lx,0x36); //SS: else if (seg==3) AsmStoreCodeU8(lx,0x3E); //DS: else if (seg==4) AsmStoreCodeU8(lx,0x64); //FS: else AsmStoreCodeU8(lx,0x65); //GS: } 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->h.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_WORD|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->h.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->s.h.type=HTT_EXPORT_SYS_SYM+HTT_UNRESOLVED_GLBL; } if (!tempess) { tempess=CAlloc(sizeof(ExportSysSymHashEntry)); tempess->s.h.str=lx->ident; lx->ident=0; tempess->s.h.type=HTT_EXPORT_SYS_SYM+HTT_UNRESOLVED_GLBL; HashAdd(tempess,lx->glbl_hash_table); } if (i==AKW_IMPORT) tempess->s.h.type|=HTT_IMPORT; else if (i==AKW_EXPORT) tempess->s.h.type|=HTT_EXPORT; if (is_literal) tempess->s.h.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->h.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->h.type & HTT_EXPORT_SYS_SYM) { if (a->flags & ACSF_IN_STRUCT) lx->hash_entry->h.type|=HTT_LITERAL; else lx->hash_entry->h.type&=~HTT_LITERAL; if (lx->hash_entry->h.type & HTT_UNRESOLVED_LOCAL) { lx->hash_entry->h.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->h.type & HTT_UNRESOLVED_GLBL) { if (lx->hash_entry->h.type & HTT_IMPORT) PrsExcept(lx,"ST_ATTEMPT_DEFINE_IMPORT"); lx->hash_entry->h.type&=~HTT_UNRESOLVED_GLBL; lx->hash_entry><(ExportSysSymHashEntry *)->val=a->ip; next_last_label=lx->hash_entry->h.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->h.type|=HTT_EXPORT; AsmLocalsResolve(lx); a->last_label=next_last_label; } if (Lex(lx)=='#') { Lex(lx); lx->hash_entry->h.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->s.h.str=lx->ident; lx->ident=0; tempess->s.h.type=HTT_EXPORT_SYS_SYM; if (a->flags & ACSF_IN_STRUCT) tempess->s.h.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->s.h.str=='@' && tempess->s.h.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->s.h.type|=HTT_EXPORT; AsmLocalsResolve(lx); a->last_label=tempess->s.h.str; Lex(lx); } else { if (Lex(lx)=='#') { tempess->s.h.type|=HTT_EXPORT | HTT_LITERAL; AsmLocalsResolve(lx); a->last_label=tempess->s.h.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; }