1656 lines
43 KiB
Plaintext
1656 lines
43 KiB
Plaintext
ClassStruct *CmpClassNew()
|
|
{
|
|
ClassStruct *result=MAllocZ(sizeof(ClassStruct)*5),
|
|
*tempc=result;
|
|
tempc->last_in_member_list=&tempc->member_list;
|
|
tempc->type=HTT_CLASS;
|
|
tempc->sub_type=IT_PTR;
|
|
tempc->ptr_cnt=0;
|
|
|
|
tempc+=sizeof(ClassStruct);
|
|
tempc->type=HTT_CLASS;
|
|
tempc->sub_type=IT_PTR;
|
|
tempc->size=sizeof(void *);
|
|
tempc->ptr_cnt=1;
|
|
|
|
tempc+=sizeof(ClassStruct);
|
|
tempc->type=HTT_CLASS;
|
|
tempc->sub_type=IT_PTR;
|
|
tempc->size=sizeof(void *);
|
|
tempc->ptr_cnt=2;
|
|
|
|
tempc+=sizeof(ClassStruct);
|
|
tempc->type=HTT_CLASS;
|
|
tempc->sub_type=IT_PTR;
|
|
tempc->size=sizeof(void *);
|
|
tempc->ptr_cnt=3;
|
|
|
|
tempc+=sizeof(ClassStruct);
|
|
tempc->type=HTT_CLASS;
|
|
tempc->sub_type=IT_PTR;
|
|
tempc->size=sizeof(void *);
|
|
tempc->ptr_cnt=4;
|
|
|
|
return result;
|
|
}
|
|
|
|
void AddUnresolved(AsmCtrlStruct *a,U1 *exp,I8 type,U8 ip,U8 rel_ip,
|
|
LexUndefEntry *undef_hash,I8 line_num,BoolU4 U1_avail,BoolU4 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->U1_avail=U1_avail;
|
|
tempu->str=NULL;
|
|
if (glbl) {
|
|
tempu->next=a->glbl_unresolved;
|
|
a->glbl_unresolved=tempu;
|
|
if (undef_hash->hash->type & HTT_IMPORT) {
|
|
tempu->str=NewStr(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;
|
|
}
|
|
}
|
|
|
|
void AsmListLine(LexStruct *lx)
|
|
{
|
|
I8 i;
|
|
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) {
|
|
while (cl3->y<cl->y) {
|
|
for (i=a->display_col;i<8;i++)
|
|
cout " ";
|
|
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;
|
|
}
|
|
|
|
void AsmStoreCodeU1(LexStruct *lx,U1 b)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
I8 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)
|
|
*tempc=MAllocZ(sizeof(AsmCodeBlk));
|
|
tempc=tempc->next;
|
|
}
|
|
break;
|
|
}
|
|
tempc->body[a->ip++ & (ASM_CODE_BLK_SIZE-1)]=b;
|
|
if (a->list) {
|
|
PrintF("%02X ",b);
|
|
a->display_col++;
|
|
if (a->display_col>8) {
|
|
a->display_col=0;
|
|
AsmListLine(lx);
|
|
}
|
|
}
|
|
if (a->ip>a->num_code_U1s)
|
|
a->num_code_U1s=a->ip;
|
|
}
|
|
|
|
void AsmStoreCodeU4(LexStruct *lx,U4 d)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
I8 i=a->ip>>ASM_CODE_BLK_BITS,
|
|
j=(a->ip+sizeof(U4))>>ASM_CODE_BLK_BITS;
|
|
U4 *dd;
|
|
AsmCodeBlk *tempc=a->code;
|
|
if (i!=j) {
|
|
for (i=0;i<sizeof(U4);i++)
|
|
AsmStoreCodeU1(lx,d.u1[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)
|
|
*tempc=MAllocZ(sizeof(AsmCodeBlk));
|
|
tempc=tempc->next;
|
|
}
|
|
break;
|
|
}
|
|
dd=tempc->body+(a->ip&(ASM_CODE_BLK_SIZE-1));
|
|
*dd=d;
|
|
a->ip+=sizeof(U4);
|
|
if (a->list) {
|
|
PrintF("%08X ",d);
|
|
a->display_col+=sizeof(U4);
|
|
if (a->display_col>8) {
|
|
a->display_col=0;
|
|
AsmListLine(lx);
|
|
}
|
|
}
|
|
if (a->ip>a->num_code_U1s)
|
|
a->num_code_U1s=a->ip;
|
|
}
|
|
|
|
void AsmStoreCodeU8(LexStruct *lx,U8 d)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
I8 i=a->ip>>ASM_CODE_BLK_BITS,
|
|
j=(a->ip+sizeof(U8))>>ASM_CODE_BLK_BITS;
|
|
U8 *dd;
|
|
AsmCodeBlk *tempc=a->code;
|
|
if (i!=j) {
|
|
for (i=0;i<sizeof(U8);i++)
|
|
AsmStoreCodeU1(lx,d.u1[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)
|
|
*tempc=MAllocZ(sizeof(AsmCodeBlk));
|
|
tempc=tempc->next;
|
|
}
|
|
break;
|
|
}
|
|
dd=tempc->body+(a->ip&(ASM_CODE_BLK_SIZE-1));
|
|
*dd=d;
|
|
a->ip+=sizeof(U8);
|
|
if (a->list) {
|
|
PrintF("%016X ",d);
|
|
a->display_col+=sizeof(U8);
|
|
if (a->display_col>8) {
|
|
a->display_col=0;
|
|
AsmListLine(lx);
|
|
}
|
|
}
|
|
if (a->ip>a->num_code_U1s)
|
|
a->num_code_U1s=a->ip;
|
|
}
|
|
|
|
void AsmStoreCodeU1At(LexStruct *lx,U1 b,I8 ip)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
I8 i=ip>>ASM_CODE_BLK_BITS+1;
|
|
AsmCodeBlk *tempc=&a->code;
|
|
while (i--) {
|
|
if (!*tempc) {
|
|
*tempc=MAlloc(sizeof(AsmCodeBlk));
|
|
**tempc=NULL;
|
|
}
|
|
tempc=tempc->next;
|
|
}
|
|
tempc->body[ip & (ASM_CODE_BLK_SIZE-1)]=b;
|
|
if (ip+1>a->num_code_U1s)
|
|
a->num_code_U1s=ip+1;
|
|
}
|
|
|
|
|
|
I8 AsmEvalExpression(LexStruct *lx)
|
|
{
|
|
U1 *exp;
|
|
I8 result=0;
|
|
lx->undef_hash_entry=NULL;
|
|
lx->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
|
|
lx->absolute_address_cnt=0;
|
|
if (!GetExpression(lx,&exp))
|
|
LexSkipEol(lx);
|
|
else {
|
|
if (!(lx->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
|
|
result=Call(exp);
|
|
DelExpression(exp);
|
|
} else
|
|
PutAsmError(lx,"ST_UNDEFINED_SYMBOL");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ResolveLocals(LexStruct *lx)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
AsmUnresolvedRef *tempu=a->local_unresolved,*tempu1;
|
|
I8 result=0;
|
|
LexUndefEntry *templu;
|
|
BoolU4 undefined;
|
|
I1 *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_SYMBOL","ST_LINE",tempu->line_num);
|
|
if (a->last_label) cout a->last_label," ";
|
|
coutln templu->hash->str;
|
|
lx->error_cnt++;
|
|
undefined=TRUE;
|
|
} else
|
|
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_U1 && (result<MIN_I1 || result>MAX_I1) ||
|
|
tempu->type==EIE_REL_U2 && (result<MIN_I2 || result>MAX_I2) ) {
|
|
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++;
|
|
}
|
|
if (tempu->U1_avail && tempu->type>EIE_LIT_U1 && (result>=-124 && result<=123)) {
|
|
PrintFWarn("%S%S%04d ","ST_COULD_USE_U1_DISP","ST_LINE",tempu->line_num);
|
|
if (a->last_label)
|
|
PrintF("%s ",a->last_label);
|
|
if (label) cout label;
|
|
CrLf;
|
|
}
|
|
}
|
|
AsmStoreCodeU1At(lx,result.u1[0],tempu->ip);
|
|
if (tempu->type>=EIE_REL_U2)
|
|
AsmStoreCodeU1At(lx,result.u1[1],tempu->ip+1);
|
|
if (tempu->type>=EIE_REL_U4) {
|
|
AsmStoreCodeU1At(lx,result.u1[2],tempu->ip+2);
|
|
AsmStoreCodeU1At(lx,result.u1[3],tempu->ip+3);
|
|
}
|
|
}
|
|
DelExpression(tempu->exp);
|
|
DelLinkedList(tempu->undef_hash);
|
|
Free(tempu);
|
|
tempu=tempu1;
|
|
}
|
|
DelHashTable(a->local_hash);
|
|
a->local_hash=NewHashTable(16);
|
|
a->local_hash->next=a->glbl_hash;
|
|
lx->hash_table_list=a->local_hash;
|
|
lx->local_hash_table=a->local_hash;
|
|
a->local_unresolved=NULL;
|
|
a->has_locals=FALSE;
|
|
}
|
|
|
|
void ResolveGlbls(LexStruct *lx,ExeStruct *e)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
ClassStruct *tempc;
|
|
GlblVarStruct *tempg;
|
|
AsmUnresolvedRef *tempu=a->glbl_unresolved,*tempu1;
|
|
I8 result=0;
|
|
ExeImportExportStruct *tempe,*tempe1;
|
|
LexUndefEntry *templu;
|
|
I8 i,j;
|
|
SysHashEntry *temph;
|
|
I1 *label;
|
|
BoolU4 undefined;
|
|
ExternUsage *tempeu,*tempeu1;
|
|
|
|
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)) {
|
|
if (!(templu->hash->type & HTT_IMPORT)) {
|
|
PrintFErr("%S%S%04d ","ST_UNDEFINED_SYMBOL","ST_LINE",tempu->line_num);
|
|
cout templu->hash->str,"\r\n";
|
|
lx->error_cnt++;
|
|
}
|
|
undefined=TRUE;
|
|
} else
|
|
label=templu->hash->str;
|
|
templu=templu->next;
|
|
}
|
|
if (undefined) {
|
|
templu=tempu->undef_hash;
|
|
if (templu->hash->type & HTT_IMPORT) {
|
|
tempe=MAllocZ(sizeof(ExeImportExportStruct));
|
|
tempe->next=templu->hash->user_data1;
|
|
tempe->str=NULL;
|
|
templu->hash->user_data1=tempe;
|
|
tempe->ip=tempu->ip;
|
|
tempe->type=tempu->type;
|
|
}
|
|
} else {
|
|
result=Call(tempu->exp);
|
|
if (!(tempu->type & 1)) {
|
|
result-=tempu->rel_ip;
|
|
if ((tempu->type==EIE_REL_U1 && (result<MIN_I1 || result>MAX_I1)) ||
|
|
tempu->type==EIE_REL_U2 && (result<MIN_I2 || result>MAX_I2)) {
|
|
PrintFErr("%S%S%04d ","ST_BRANCH_OUT_OF_RANGE","ST_LINE",tempu->line_num);
|
|
if (label) cout label;
|
|
CrLf;
|
|
lx->error_cnt++;
|
|
}
|
|
if (tempu->U1_avail && tempu->type>EIE_LIT_U1 && (result>=-124 && result<=123)) {
|
|
PrintFWarn("%S%S%04d ","ST_COULD_USE_U1_DISP","ST_LINE",tempu->line_num);
|
|
if (a->last_label)
|
|
PrintF("%s ",a->last_label);
|
|
if (label) cout label;
|
|
CrLf;
|
|
}
|
|
}
|
|
AsmStoreCodeU1At(lx,result.u1[0],tempu->ip);
|
|
if (tempu->type>=EIE_REL_U2)
|
|
AsmStoreCodeU1At(lx,result.u1[1],tempu->ip+1);
|
|
if (tempu->type>=EIE_REL_U4) {
|
|
AsmStoreCodeU1At(lx,result.u1[2],tempu->ip+2);
|
|
AsmStoreCodeU1At(lx,result.u1[3],tempu->ip+3);
|
|
}
|
|
}
|
|
DelExpression(tempu->exp);
|
|
DelLinkedList(tempu->undef_hash);
|
|
Free(tempu);
|
|
tempu=tempu1;
|
|
}
|
|
|
|
tempe1=&e->ie;
|
|
while (tempe1->next)
|
|
tempe1=tempe1->next;
|
|
|
|
for (i=0;i<=a->glbl_hash->mask;i++) {
|
|
temph=a->glbl_hash->body[i];
|
|
while (temph) {
|
|
if (temph->type & HTT_IMPORT && temph->use_cnt) {
|
|
if (temph->type & HTT_FUNCTION) {
|
|
tempe=MAllocZ(sizeof(ExeImportExportStruct));
|
|
tempe->type=EIE_LIT_U4;
|
|
tempc=temph;
|
|
tempe->str=(tempc->import_name) ?
|
|
NewStr(tempc->import_name):NewStr(tempc->str);
|
|
tempe->ip=tempc->executable_address;
|
|
tempe1->next=tempe;
|
|
tempe1=tempe;
|
|
} else if (temph->type & HTT_GLBL_VAR) {
|
|
tempe=MAllocZ(sizeof(ExeImportExportStruct));
|
|
tempe->type=EIE_LIT_U4;
|
|
tempg=temph;
|
|
if (tempg->import_name)
|
|
tempe->str=NewStr(tempg->import_name);
|
|
else
|
|
tempe->str=NewStr(tempg->str);
|
|
tempe->ip=tempg->data_address;
|
|
tempe1->next=tempe;
|
|
tempe1=tempe;
|
|
} else {
|
|
tempe=temph->user_data1;
|
|
if (tempe) {
|
|
tempe1->next=tempe;
|
|
tempe->str=NewStr(temph->str);
|
|
while (tempe1->next)
|
|
tempe1=tempe1->next;
|
|
}
|
|
}
|
|
} else if (temph->type & HTT_EXPORT) {
|
|
if (temph->type & HTT_UNRESOLVED_GLBL) {
|
|
PrintFErr("%S%s\r\n","ST_UNDEFINED_SYMBOL",temph->str);
|
|
lx->error_cnt++;
|
|
} else {
|
|
tempe=MAlloc(sizeof(ExeImportExportStruct));
|
|
tempe->type=EIE_REL_EXPORT;
|
|
if (temph->type & HTT_FUNCTION) {
|
|
tempc=temph;
|
|
tempe->ip=tempc->executable_address;
|
|
tempeu=tempc->ext_list;
|
|
while (tempeu) {
|
|
tempeu1=tempeu->next;
|
|
j=tempc->executable_address-(tempeu->ip+4);
|
|
AsmStoreCodeU1At(lx,j.u1[0],tempeu->ip);
|
|
AsmStoreCodeU1At(lx,j.u1[1],tempeu->ip+1);
|
|
AsmStoreCodeU1At(lx,j.u1[2],tempeu->ip+2);
|
|
AsmStoreCodeU1At(lx,j.u1[3],tempeu->ip+3);
|
|
Free(tempeu);
|
|
tempeu=tempeu1;
|
|
}
|
|
} else if (temph->type & HTT_GLBL_VAR) {
|
|
tempg=temph;
|
|
tempe->ip=tempg->data_address;
|
|
} else
|
|
tempe->ip=temph->user_data0;
|
|
if (temph->type & HTT_LITERAL)
|
|
tempe->type++;
|
|
*tempe1=tempe;
|
|
tempe->next=NULL;
|
|
tempe1=tempe;
|
|
tempe->str=NewStr(temph->str);
|
|
}
|
|
}
|
|
temph=temph->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
BoolU8 ParseAsmImm(LexStruct *lx,AsmCtrlStruct *aa,AsmArgStruct *a,U8 ip)
|
|
{
|
|
if (a->imm_or_off_present) {
|
|
PutAsmError(lx,"ST_ALREADY_ONE_IMMEDIATE");
|
|
return FALSE;
|
|
} else {
|
|
a->imm_or_off_present=TRUE;
|
|
a->undef_local=NULL;
|
|
a->undef_glbl=NULL;
|
|
lx->instruction_pointer=ip;
|
|
lx->undef_hash_entry=NULL;
|
|
lx->absolute_address_cnt=0;
|
|
lx->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
|
|
if (!GetExpression(lx,&a->exp))
|
|
LexSkipEol(lx);
|
|
else {
|
|
if (!(lx->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
|
|
a->imm=Call(a->exp);
|
|
a->undef_glbl=lx->undef_hash_entry;
|
|
lx->undef_hash_entry=NULL;
|
|
DelExpression(a->exp);
|
|
a->exp=NULL;
|
|
} else {
|
|
if (lx->flags & LF_UNRESOLVED_GLBL) {
|
|
a->undef_glbl=lx->undef_hash_entry;
|
|
lx->undef_hash_entry=NULL;
|
|
aa->has_locals=TRUE;
|
|
} else if (lx->flags & LF_UNRESOLVED_LOCAL) {
|
|
a->undef_local=lx->undef_hash_entry;
|
|
lx->undef_hash_entry=NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void ParseAsmArg(LexStruct *lx,AsmCtrlStruct *aa,AsmArgStruct *a,U8 ip)
|
|
{
|
|
I8 i,temp;
|
|
a->size=0;
|
|
a->absolute_address_cnt=0;
|
|
a->seg=16;
|
|
a->reg1=16;
|
|
a->reg2=16;
|
|
a->imm=0;
|
|
a->scale=1;
|
|
a->indirect=FALSE;
|
|
a->imm_or_off_present=FALSE;
|
|
a->undef_local=NULL;
|
|
a->undef_glbl=NULL;
|
|
a->just_seg=FALSE;
|
|
a->exp=NULL;
|
|
while (TRUE) {
|
|
if (lx->token==TK_IDENT) {
|
|
if (lx->hash_entry) {
|
|
if (lx->hash_entry->type==HTT_R8) {
|
|
a->size=1;
|
|
a->reg1=lx->hash_entry->user_data0;
|
|
Lex(lx);
|
|
return;
|
|
} else if (lx->hash_entry->type==HTT_R16) {
|
|
a->size=2;
|
|
a->reg1=lx->hash_entry->user_data0;
|
|
Lex(lx);
|
|
return;
|
|
} else if (lx->hash_entry->type==HTT_R32) {
|
|
a->size=4;
|
|
a->reg1=lx->hash_entry->user_data0;
|
|
Lex(lx);
|
|
return;
|
|
} else if (lx->hash_entry->type==HTT_R64) {
|
|
a->size=8;
|
|
a->reg1=lx->hash_entry->user_data0;
|
|
Lex(lx);
|
|
return;
|
|
} else if (lx->hash_entry->type==HTT_SEG) {
|
|
a->seg=lx->hash_entry->user_data0;
|
|
if (Lex(lx)!=':') {
|
|
a->just_seg=TRUE;
|
|
return;
|
|
} else
|
|
Lex(lx); //skip ":"
|
|
} else if (lx->hash_entry->type==HTT_KEYWORD) {
|
|
i=lx->hash_entry->user_data0;
|
|
if (i==AKW_U1) {
|
|
Lex(lx); //skip keyword
|
|
a->size=1;
|
|
} else if (i==AKW_U2) {
|
|
Lex(lx); //skip keyword
|
|
a->size=2;
|
|
} else if (i==AKW_U4) {
|
|
Lex(lx); //skip keyword
|
|
a->size=4;
|
|
} else if (i==AKW_U8) {
|
|
Lex(lx); //skip keyword
|
|
a->size=8;
|
|
} else {
|
|
PutAsmError(lx,"ST_SYNTAX_ERROR");
|
|
return;
|
|
}
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
if (lx->token!='[')
|
|
return;
|
|
}
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
if (lx->token!='[')
|
|
return;
|
|
}
|
|
} else if (lx->token=='[') {
|
|
a->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 (a->reg1==16)
|
|
a->reg1=lx->hash_entry->user_data0;
|
|
else
|
|
a->reg2=lx->hash_entry->user_data0;
|
|
Lex(lx);
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
}
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
}
|
|
} else if (lx->token=='*') {
|
|
if (Lex(lx)!=TK_INTEGER)
|
|
PutAsmError(lx,"ST_EXPECTING_SCALE_FACTOR");
|
|
else {
|
|
a->scale=lx->cur_i;
|
|
Lex(lx); //skip scale
|
|
if (a->reg2!=16) {
|
|
temp=a->reg1;
|
|
a->reg1=a->reg2;
|
|
a->reg2=temp;
|
|
}
|
|
}
|
|
} else if (lx->token=='+') {
|
|
Lex(lx); //skip '+'
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
}
|
|
}
|
|
if (lx->token==']') {
|
|
Lex(lx); //skip ]
|
|
return;
|
|
} else
|
|
PutAsmError(lx,"ST_MISSING_RIGHT_BRACKET");
|
|
} else {
|
|
ParseAsmImm(lx,aa,a,ip);
|
|
a->absolute_address_cnt=lx->absolute_address_cnt;
|
|
if (lx->token!='[')
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void AsmMakeArgMask(AsmArgStruct *a,U8 *mask)
|
|
{
|
|
if (a->just_seg) {
|
|
switch (a->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;
|
|
}
|
|
switch (a->size) {
|
|
case 0: *mask=0x3FF07FFFFE; break;
|
|
case 1: *mask=0x1110111112; break;
|
|
case 2: *mask=0x2220222224; break;
|
|
case 4: *mask=0x0440444448; break;
|
|
case 8: *mask=0x0880088880; break;
|
|
}
|
|
|
|
if (a->reg1!=16 && a->imm_or_off_present && !a->imm) {
|
|
if (!a->undef_glbl && !a->undef_local)
|
|
a->imm_or_off_present=FALSE; //Zero displacement
|
|
}
|
|
|
|
if (a->reg2!=16 || a->scale!=1) {
|
|
*mask&= 0x00000F0000;
|
|
return;
|
|
}
|
|
|
|
if (a->indirect) {
|
|
if (a->imm_or_off_present)
|
|
*mask&=0x00FFFF0000;
|
|
else
|
|
*mask&=0x000FFF0000;
|
|
} else {
|
|
if (a->imm_or_off_present)
|
|
*mask&=0x000F80F0FE;
|
|
else
|
|
*mask&=0x3F0F8F0F00;
|
|
}
|
|
if (a->seg!=16)
|
|
*mask&= 0x00FFFF0000;
|
|
if (a->reg1==16) {
|
|
if (a->indirect)
|
|
*mask&=0x00FFFF0000;
|
|
else if (MIN_I1<=a->imm<=MAX_I1)
|
|
*mask&=0x000000F0FE;
|
|
else if (MIN_I1<=a->imm<=MAX_U1)
|
|
*mask&=0x000000E0FE;
|
|
else if (MIN_I2<=a->imm<=MAX_I2)
|
|
*mask&=0x000000E0EE;
|
|
else if (MIN_I2<=a->imm<=MAX_U2)
|
|
*mask&=0x000000C0EE;
|
|
else if (MIN_I4<=a->imm<=MAX_I4)
|
|
*mask&=0x000000C0CE;
|
|
else if (MIN_I4<=a->imm<=MAX_U4)
|
|
*mask&=0x00000080CE;
|
|
else
|
|
*mask&=0x000000808E;
|
|
} else
|
|
*mask&= 0x3F007F0F00;
|
|
if (a->reg1!=0)
|
|
*mask&= 0x30FFFFFFFF;
|
|
if (a->reg1!=1)
|
|
*mask&= 0x2FFFFFFFFF;
|
|
if (a->reg1!=2)
|
|
*mask&= 0x1FFFFFFFFF;
|
|
}
|
|
|
|
BoolU8 AsmStoreNum(LexStruct *lx,AsmCtrlStruct *a,I8 num,BoolU4 is_question,I8 num_U1s,I8 cnt,
|
|
I8 num_ip_rel,I8 num_lit,
|
|
U1 *num_exp,LexUndefEntry *num_local_hash,LexUndefEntry *num_glbl_hash,
|
|
BoolU4 U1_avail,U8 abs_add_cnt)
|
|
{
|
|
I8 i;
|
|
ExeAbsoluteAddressStruct *tempa;
|
|
if (!num_lit)
|
|
num-=num_ip_rel;
|
|
for (i=0;i<cnt;i++) {
|
|
if (num_U1s==1) {
|
|
if (num_local_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U1+num_lit,a->ip,num_ip_rel,
|
|
num_local_hash,LexLineNum(lx),U1_avail,FALSE);
|
|
else if (num_glbl_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U1+num_lit,a->ip,num_ip_rel,
|
|
num_glbl_hash,LexLineNum(lx),U1_avail,TRUE);
|
|
else {
|
|
if (!num_lit && (num<MIN_I1 || num>MAX_I1)) {
|
|
// LexPop(lx);
|
|
PutAsmError(lx,"ST_BRANCH_OUT_OF_RANGE");
|
|
a->ip++;
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (is_question)
|
|
a->ip++;
|
|
else
|
|
AsmStoreCodeU1(lx,num.u1[0]);
|
|
|
|
} else if (num_U1s==2) {
|
|
if (num_local_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U2+num_lit,a->ip,num_ip_rel,
|
|
num_local_hash,LexLineNum(lx),U1_avail,FALSE);
|
|
else if (num_glbl_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U2+num_lit,a->ip,num_ip_rel,
|
|
num_glbl_hash,LexLineNum(lx),U1_avail,TRUE);
|
|
else {
|
|
if (!num_lit && (num <MIN_I2 || num>MAX_I2)) {
|
|
// LexPop(lx);
|
|
PutAsmError(lx,"ST_BRANCH_OUT_OF_RANGE");
|
|
a->ip+=2;
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (is_question)
|
|
a->ip+=2;
|
|
else {
|
|
AsmStoreCodeU1(lx,num.u1[0]);
|
|
AsmStoreCodeU1(lx,num.u1[1]);
|
|
}
|
|
if (U1_avail && !num_local_hash && !num_glbl_hash &&
|
|
!num_lit && num>=-124 && num<=123) {
|
|
// LexPop(lx);
|
|
PutAsmWarning(lx,"ST_COULD_USE_U1_DISP");
|
|
return FALSE;
|
|
}
|
|
} else if (num_U1s==4) {
|
|
if (num_local_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U4+num_lit,a->ip,num_ip_rel,
|
|
num_local_hash,LexLineNum(lx),U1_avail,FALSE);
|
|
else if (num_glbl_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U4+num_lit,a->ip,num_ip_rel,
|
|
num_glbl_hash,LexLineNum(lx),U1_avail,TRUE);
|
|
if (num_lit && abs_add_cnt & 1) {
|
|
tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct));
|
|
tempa->next=a->absolutes;
|
|
a->absolutes=tempa;
|
|
tempa->ip=a->ip;
|
|
}
|
|
if (is_question)
|
|
a->ip+=sizeof(U4);
|
|
else
|
|
AsmStoreCodeU4(lx,num.u4[0]);
|
|
if (U1_avail && !num_local_hash && !num_glbl_hash &&
|
|
!num_lit && num>=-124 && num<=123) {
|
|
// LexPop(lx);
|
|
PutAsmWarning(lx,"ST_COULD_USE_U1_DISP");
|
|
return FALSE;
|
|
}
|
|
} else if (num_U1s==8) {
|
|
//dbgo
|
|
if (num_local_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U4+num_lit,a->ip,num_ip_rel,
|
|
num_local_hash,LexLineNum(lx),U1_avail,FALSE);
|
|
else if (num_glbl_hash)
|
|
AddUnresolved(a,num_exp,EIE_REL_U4+num_lit,a->ip,num_ip_rel,
|
|
num_glbl_hash,LexLineNum(lx),U1_avail,TRUE);
|
|
if (num_lit && abs_add_cnt & 1) {
|
|
tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct));
|
|
tempa->next=a->absolutes;
|
|
a->absolutes=tempa;
|
|
tempa->ip=a->ip;
|
|
}
|
|
if (is_question)
|
|
a->ip+=sizeof(U8);
|
|
else
|
|
AsmStoreCodeU8(lx,num);
|
|
if (U1_avail && !num_local_hash && !num_glbl_hash &&
|
|
!num_lit && num>=-124 && num<=123) {
|
|
// LexPop(lx);
|
|
PutAsmWarning(lx,"ST_COULD_USE_U1_DISP");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BoolU8 AsmCodeInstruction(LexStruct *lx,AsmCtrlStruct *a,
|
|
OpcodeHashEntry *tempo,I8 argcnt)
|
|
{
|
|
I8 i,j,a1,a2,om,seg;
|
|
U8 arg1mask,arg2mask;
|
|
AsmArgStruct *tempa1,*tempa2;
|
|
BoolU4 ModrM_complete,U1_avail=FALSE,found_second_possible=FALSE;
|
|
|
|
I8 U1_cnt;
|
|
U1 last_opcode_U1;
|
|
InstructionEntry *tempi;
|
|
BoolU4 has_ModrM;
|
|
U1 ModrM;
|
|
BoolU4 has_SIB;
|
|
U1 SIB,REX;
|
|
BoolU4 has_address_prefix;
|
|
BoolU4 has_operand_prefix;
|
|
BoolU4 is_default;
|
|
I8 disp,disp_U1s,disp_ip_rel,disp_lit,disp_abs_cnt;
|
|
I8 imm, imm_U1s, imm_ip_rel, imm_lit,imm_abs_cnt;
|
|
U1 *disp_exp,*imm_exp;
|
|
LexUndefEntry *disp_local_hash,*disp_glbl_hash;
|
|
LexUndefEntry *imm_local_hash,*imm_glbl_hash;
|
|
|
|
I8 best_U1_cnt=255;
|
|
U1 blast_opcode_U1;
|
|
InstructionEntry *btempi;
|
|
BoolU4 bhas_ModrM;
|
|
U1 bModrM;
|
|
BoolU4 bhas_SIB;
|
|
U1 bSIB,bREX;
|
|
BoolU4 bhas_address_prefix;
|
|
BoolU4 bhas_operand_prefix;
|
|
BoolU4 bis_default;
|
|
I8 bdisp,bdisp_U1s,bdisp_ip_rel,bdisp_lit,bdisp_abs_cnt;
|
|
I8 bimm, bimm_U1s, bimm_ip_rel, bimm_lit,bimm_abs_cnt;
|
|
U1 *bdisp_exp,*bimm_exp;
|
|
LexUndefEntry *bdisp_local_hash,*bdisp_glbl_hash;
|
|
LexUndefEntry *bimm_local_hash,*bimm_glbl_hash;
|
|
|
|
|
|
if (argcnt>0)
|
|
AsmMakeArgMask(&a->arg1,&arg1mask);
|
|
else
|
|
arg1mask=1;
|
|
if (argcnt>1)
|
|
AsmMakeArgMask(&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)
|
|
U1_avail=TRUE;
|
|
if (Bt(&arg1mask,tempi->arg1) && Bt(&arg2mask,tempi->arg2)) {
|
|
ModrM_complete=FALSE;
|
|
last_opcode_U1=0;
|
|
has_ModrM=FALSE;
|
|
ModrM=0;
|
|
has_SIB=FALSE;
|
|
SIB=0;
|
|
has_address_prefix=FALSE;
|
|
has_operand_prefix=FALSE;
|
|
is_default=(tempi->flags & IEF_DEFAULT) ? TRUE:FALSE;
|
|
if (a->seg_size==64) {
|
|
REX=0x40;
|
|
if (tempi->flags & IEF_48_REX)
|
|
REX=0x48;
|
|
else if (tempi->flags & IEF_NO_REX)
|
|
REX=0x00;
|
|
} else
|
|
REX=0x00;
|
|
disp=0; disp_U1s=0; disp_ip_rel=0; disp_lit=1;
|
|
imm=0; imm_U1s=0; imm_ip_rel=0; imm_lit=1;
|
|
disp_exp=NULL; imm_exp=NULL;
|
|
disp_local_hash=NULL; disp_glbl_hash=NULL;
|
|
disp_abs_cnt=0;
|
|
imm_local_hash=NULL; imm_glbl_hash=NULL;
|
|
imm_abs_cnt=0;
|
|
om=tempi->opcode_modifier;
|
|
a1=tempi->arg1;
|
|
a2=tempi->arg2;
|
|
tempa1=&a->arg1;
|
|
tempa2=&a->arg2;
|
|
last_opcode_U1=tempi->opcode[tempi->opcode_cnt-1];
|
|
|
|
if (tempi->slash_value<8) {
|
|
ModrM+=tempi->slash_value<<3;
|
|
has_ModrM=TRUE;
|
|
}
|
|
|
|
if ((a->seg_size==16 && tempi->flags & IEF_OP_SIZE32) ||
|
|
(a->seg_size!=16 && tempi->flags & IEF_OP_SIZE16))
|
|
has_operand_prefix=TRUE;
|
|
|
|
if (om==OM_IB) imm_U1s=1;
|
|
else if (om==OM_IW) imm_U1s=2;
|
|
else if (om==OM_ID) imm_U1s=4;
|
|
|
|
if (om==OM_CB) {
|
|
imm_U1s=1;
|
|
imm_lit=0;
|
|
} else if (om==OM_CW) {
|
|
imm_U1s=2;
|
|
imm_lit=0;
|
|
} else if (om==OM_CD) {
|
|
imm_U1s=4;
|
|
imm_lit=0;
|
|
}
|
|
|
|
if (argcnt==1) {
|
|
if (best_U1_cnt!=255 && !found_second_possible && !bis_default) {
|
|
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) {
|
|
last_opcode_U1=last_opcode_U1+tempa1->reg1&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=1;
|
|
}
|
|
if (a1==ARGT_R64 || a1==ARGT_RM64)
|
|
REX|=8;
|
|
if (a1>=ARGT_RM8 && a1<=ARGT_RM64) {
|
|
if (a->seg_size==16)
|
|
has_address_prefix=TRUE;
|
|
|
|
has_ModrM=TRUE;
|
|
if (tempa1->imm_or_off_present && tempa1->indirect && tempa1->reg1==16) {
|
|
ModrM=ModrM+5;
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_U1s=4;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (a->seg_size==64)
|
|
disp_lit=0;
|
|
} else {
|
|
if (tempa1->reg2==16 && tempa1->scale==1) {
|
|
ModrM+=tempa1->reg1&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=1;
|
|
} else {
|
|
ModrM+=4;
|
|
has_SIB=TRUE;
|
|
if (tempa1->scale==1)
|
|
SIB=0;
|
|
else if (tempa1->scale==2)
|
|
SIB=0x40;
|
|
else if (tempa1->scale==4)
|
|
SIB=0x80;
|
|
else if (tempa1->scale==8)
|
|
SIB=0xC0;
|
|
if (tempa1->reg2==16) {
|
|
ModrM_complete=TRUE;
|
|
SIB+=((tempa1->reg1&7)<<3)+5;
|
|
if (tempa1->reg1>7)
|
|
REX|=2;
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_U1s=4;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
} else {
|
|
SIB+=((tempa1->reg1&7)<<3)+tempa1->reg2&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=2;
|
|
if (tempa1->reg2>7)
|
|
REX|=1;
|
|
if (tempa1->reg2==5 && !tempa1->imm_or_off_present && tempa1->indirect) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
ModrM_complete=TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (!ModrM_complete) {
|
|
if (tempa1->imm_or_off_present) {
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (!disp_exp && MIN_I1<=disp<=MAX_I1) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
} else if (a->seg_size==16) {
|
|
ModrM+=0x80;
|
|
disp_U1s=2;
|
|
} else {
|
|
ModrM+=0x80;
|
|
disp_U1s=4;
|
|
}
|
|
} else if (!tempa1->indirect) {
|
|
has_address_prefix=FALSE;
|
|
ModrM+=0xC0;
|
|
} else {
|
|
if (tempa1->reg1==5) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (a1>=ARGT_REL8 && a1<=ARGT_REL32 ||
|
|
a1>=ARGT_IMM8 && a1<=ARGT_IMM64 ||
|
|
a1>=ARGT_UIMM8 && a1<=ARGT_UIMM64) {
|
|
if (a1==ARGT_IMM64 || a2==ARGT_UIMM64)
|
|
REX|=8;
|
|
imm=tempa1->imm;
|
|
imm_exp=tempa1->exp;
|
|
imm_local_hash=tempa1->undef_local;
|
|
imm_glbl_hash=tempa1->undef_glbl;
|
|
imm_abs_cnt=tempa1->absolute_address_cnt;
|
|
}
|
|
} else if (argcnt==2) {
|
|
if (best_U1_cnt!=255 && !found_second_possible && !bis_default) {
|
|
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>=OM_RB && om<=OM_RD) {
|
|
last_opcode_U1+=tempa1->reg1&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=1;
|
|
} else if (tempi->slash_value==SV_REGISTER) {
|
|
if (a1>=ARGT_AL && a1<=ARGT_EAX) {
|
|
last_opcode_U1+=tempa2->reg1&7;
|
|
if (tempa2->reg1>7)
|
|
REX|=1;
|
|
} else if (a2>=ARGT_AL && a2<=ARGT_EAX) {
|
|
last_opcode_U1+=tempa1->reg1&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=1;
|
|
}
|
|
}
|
|
}
|
|
if (a1==ARGT_RM64 || a2==ARGT_RM64 ||
|
|
a1==ARGT_R64 || a2==ARGT_R64)
|
|
REX|=8;
|
|
if (a1>=ARGT_RM8 && a1<=ARGT_RM64 ||a2>=ARGT_RM8 && a2<=ARGT_RM64) {
|
|
if (a->seg_size==16)
|
|
has_address_prefix=TRUE;
|
|
has_ModrM=TRUE;
|
|
if (a2>=ARGT_RM8 && a2<=ARGT_RM64) {
|
|
tempa1=&a->arg2;
|
|
tempa2=&a->arg1;
|
|
}
|
|
if (tempi->slash_value==SV_REGISTER) {
|
|
if (tempa2->just_seg)
|
|
ModrM+=(tempa2->seg<<3);
|
|
else {
|
|
if (tempa2->reg1==16) {
|
|
ModrM+=((tempa1->reg1&7)<<3);
|
|
if (tempa1->reg1>7)
|
|
REX|=4;
|
|
} else {
|
|
ModrM+=((tempa2->reg1&7)<<3);
|
|
if (tempa2->reg1>7)
|
|
REX|=4;
|
|
}
|
|
}
|
|
}
|
|
if (tempa1->reg2==16 && tempa1->scale==1) {
|
|
if (tempa1->reg1!=16) {
|
|
ModrM+=tempa1->reg1&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=1;
|
|
}
|
|
} else {
|
|
ModrM+=4;
|
|
has_SIB=TRUE;
|
|
if (tempa1->scale==1)
|
|
SIB=0;
|
|
else if (tempa1->scale==2)
|
|
SIB=0x40;
|
|
else if (tempa1->scale==4)
|
|
SIB=0x80;
|
|
else if (tempa1->scale==8)
|
|
SIB=0xC0;
|
|
if (tempa1->reg2==16) {
|
|
ModrM_complete=TRUE;
|
|
SIB+=((tempa1->reg1&7)<<3)+5;
|
|
if (tempa1->reg1>7)
|
|
REX|=2;
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_U1s=4;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
} else {
|
|
SIB+=((tempa1->reg1&7)<<3)+tempa1->reg2&7;
|
|
if (tempa1->reg1>7)
|
|
REX|=2;
|
|
if (tempa1->reg2>7)
|
|
REX|=1;
|
|
if (tempa1->reg2==5 && !tempa1->imm_or_off_present && tempa1->indirect) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
ModrM_complete=TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (!ModrM_complete) {
|
|
if (tempa1->imm_or_off_present && tempa1->indirect && tempa1->reg1==16) {
|
|
ModrM=(ModrM & 0xF8)+5;
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_U1s=4;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (a->seg_size==64)
|
|
disp_lit=0;
|
|
} else {
|
|
if (tempa1->imm_or_off_present) {
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (!disp_exp && MIN_I1<=disp<=MAX_I1) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
} else if (a->seg_size==16) {
|
|
ModrM+=0x80;
|
|
disp_U1s=2;
|
|
} else {
|
|
ModrM+=0x80;
|
|
disp_U1s=4;
|
|
}
|
|
} else if (!tempa1->indirect) {
|
|
has_address_prefix=FALSE;
|
|
ModrM+=0xC0;
|
|
} else {
|
|
if (tempa1->reg1==5) {
|
|
ModrM+=0x40;
|
|
disp_U1s=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (a1>=ARGT_MOFFS8 && a1<=ARGT_MOFFS64) {
|
|
disp=tempa1->imm;
|
|
disp_exp=tempa1->exp;
|
|
disp_local_hash=tempa1->undef_local;
|
|
disp_glbl_hash=tempa1->undef_glbl;
|
|
disp_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (a->seg_size==16)
|
|
disp_U1s=2;
|
|
else
|
|
disp_U1s=4;
|
|
has_address_prefix=FALSE;
|
|
} else if (a2>=ARGT_MOFFS8 && a2<=ARGT_MOFFS64) {
|
|
disp=tempa2->imm;
|
|
disp_exp=tempa2->exp;
|
|
disp_local_hash=tempa2->undef_local;
|
|
disp_glbl_hash=tempa2->undef_glbl;
|
|
disp_abs_cnt=tempa2->absolute_address_cnt;
|
|
if (a->seg_size==16)
|
|
disp_U1s=2;
|
|
else
|
|
disp_U1s=4;
|
|
has_address_prefix=FALSE;
|
|
} else if (a1>=ARGT_IMM8 && a1<=ARGT_IMM64 ||
|
|
a1>=ARGT_UIMM8 && a1<=ARGT_UIMM64) {
|
|
imm=tempa1->imm;
|
|
imm_exp=tempa1->exp;
|
|
imm_local_hash=tempa1->undef_local;
|
|
imm_glbl_hash=tempa1->undef_glbl;
|
|
imm_abs_cnt=tempa1->absolute_address_cnt;
|
|
if (a1==ARGT_IMM8 || a1==ARGT_UIMM8) imm_U1s=1;
|
|
else if (a1==ARGT_IMM16 || a1==ARGT_UIMM16) imm_U1s=2;
|
|
else if (a1==ARGT_IMM32 || a1==ARGT_UIMM32) imm_U1s=4;
|
|
else {
|
|
imm_U1s=8;
|
|
REX|=8;
|
|
}
|
|
}
|
|
if (a2>=ARGT_IMM8 && a2<=ARGT_IMM64 ||
|
|
a2>=ARGT_UIMM8 && a2<=ARGT_UIMM64) {
|
|
imm=tempa2->imm;
|
|
imm_exp=tempa2->exp;
|
|
imm_local_hash=tempa2->undef_local;
|
|
imm_glbl_hash=tempa2->undef_glbl;
|
|
imm_abs_cnt=tempa2->absolute_address_cnt;
|
|
if (a2==ARGT_IMM8 || a2==ARGT_UIMM8) imm_U1s=1;
|
|
else if (a2==ARGT_IMM16 || a2==ARGT_UIMM16) imm_U1s=2;
|
|
else if (a2==ARGT_IMM32 || a2==ARGT_UIMM32) imm_U1s=4;
|
|
else {
|
|
imm_U1s=8;
|
|
REX|=8;
|
|
}
|
|
}
|
|
}
|
|
U1_cnt=tempi->opcode_cnt+disp_U1s+imm_U1s;
|
|
if (has_ModrM) U1_cnt++;
|
|
if (has_SIB) U1_cnt++;
|
|
if (a->seg_size==64)
|
|
if (REX&0x40==0x40 &&
|
|
(REX!=0x40 || (tempi->flags&IEF_40_REX)))
|
|
U1_cnt++;
|
|
|
|
if (U1_cnt<best_U1_cnt &&
|
|
!(tempi->flags & IEF_DONT_SWITCH_MODES &&
|
|
(has_address_prefix || has_operand_prefix))) {
|
|
best_U1_cnt=U1_cnt;
|
|
blast_opcode_U1=last_opcode_U1;
|
|
btempi=tempi;
|
|
bhas_ModrM=has_ModrM;
|
|
bModrM=ModrM;
|
|
bhas_SIB=has_SIB;
|
|
bSIB=SIB;
|
|
bREX=REX;
|
|
bhas_address_prefix=has_address_prefix;
|
|
bhas_operand_prefix=has_operand_prefix;
|
|
bis_default=is_default;
|
|
bdisp=disp;
|
|
bdisp_U1s=disp_U1s;
|
|
bdisp_ip_rel=disp_ip_rel;
|
|
bdisp_lit=disp_lit;
|
|
bdisp_abs_cnt=disp_abs_cnt;
|
|
bimm=imm;
|
|
bimm_U1s=imm_U1s;
|
|
bimm_ip_rel=imm_ip_rel;
|
|
bimm_lit=imm_lit;
|
|
bimm_abs_cnt=imm_abs_cnt;
|
|
bdisp_exp=disp_exp;
|
|
bimm_exp=imm_exp;
|
|
bdisp_local_hash=disp_local_hash;
|
|
bdisp_glbl_hash=disp_glbl_hash;
|
|
bimm_local_hash=imm_local_hash;
|
|
bimm_glbl_hash=imm_glbl_hash;
|
|
}
|
|
}
|
|
}
|
|
if (best_U1_cnt<255) {
|
|
if (bhas_operand_prefix)
|
|
AsmStoreCodeU1(lx,0x66); //Operand size override
|
|
if (bhas_address_prefix || a->seg_size==16 && has_SIB)
|
|
AsmStoreCodeU1(lx,0x67); //Operand size override
|
|
|
|
seg=16;
|
|
if (argcnt>1 && a->arg2.seg!=16 && !a->arg2.just_seg)
|
|
seg=a->arg2.seg;
|
|
else if (argcnt>0 && a->arg1.seg!=16 && !a->arg1.just_seg)
|
|
seg=a->arg1.seg;
|
|
if (seg!=16) {
|
|
if (seg==0)
|
|
AsmStoreCodeU1(lx,0x26); //ES:
|
|
else if (seg==1)
|
|
AsmStoreCodeU1(lx,0x2E); //CS:
|
|
else if (seg==2)
|
|
AsmStoreCodeU1(lx,0x36); //SS:
|
|
else if (seg==3)
|
|
AsmStoreCodeU1(lx,0x3E); //DS:
|
|
else if (seg==4)
|
|
AsmStoreCodeU1(lx,0x64); //FS:
|
|
else
|
|
AsmStoreCodeU1(lx,0x65); //GS:
|
|
}
|
|
if (a->seg_size==64)
|
|
if (bREX&0x40==0x40 &&
|
|
(bREX!=0x40 || (btempi->flags&IEF_40_REX)))
|
|
AsmStoreCodeU1(lx,bREX);
|
|
for (j=0;j<btempi->opcode_cnt-1;j++)
|
|
AsmStoreCodeU1(lx,btempi->opcode[j]);
|
|
AsmStoreCodeU1(lx,blast_opcode_U1);
|
|
|
|
if (bhas_ModrM)
|
|
AsmStoreCodeU1(lx,bModrM);
|
|
if (bhas_SIB)
|
|
AsmStoreCodeU1(lx,bSIB);
|
|
|
|
if (bdisp_U1s) {
|
|
bdisp_ip_rel=a->ip+bdisp_U1s+bimm_U1s;
|
|
if (!AsmStoreNum(lx,a,bdisp,FALSE,bdisp_U1s,1,bdisp_ip_rel,bdisp_lit,
|
|
bdisp_exp,bdisp_local_hash,bdisp_glbl_hash,U1_avail,bdisp_abs_cnt))
|
|
return FALSE;
|
|
}
|
|
|
|
if (bimm_U1s) {
|
|
bimm_ip_rel=a->ip+bimm_U1s;
|
|
if (!AsmStoreNum(lx,a,bimm,FALSE,bimm_U1s,1,bimm_ip_rel,bimm_lit,
|
|
bimm_exp,bimm_local_hash,bimm_glbl_hash,U1_avail,bimm_abs_cnt))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
// LexPop(lx);
|
|
PutAsmError(lx,"ST_INVALID_INSTRUCTION");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void DefineU1s(LexStruct *lx,AsmCtrlStruct *a,I8 num_U1s)
|
|
{
|
|
BoolU4 is_question,is_dup;
|
|
I8 i,dup_value;
|
|
void *exp;
|
|
I1 *ptr;
|
|
LexUndefEntry *undef_locals,*undef_glbls;
|
|
|
|
while (lx->token && lx->token!=';') {
|
|
undef_locals=NULL;
|
|
undef_glbls=NULL;
|
|
if (lx->token==TK_STR) {
|
|
ptr=lx->ident;
|
|
i=lx->ident_len-1;
|
|
while (i--)
|
|
AsmStoreCodeU1(lx,*ptr++);
|
|
Lex(lx); //SKip STR
|
|
} else {
|
|
is_question=FALSE;
|
|
is_dup=FALSE;
|
|
lx->absolute_address_cnt=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,&exp))
|
|
LexSkipEol(lx);
|
|
else {
|
|
if (lx->flags & (LF_UNRESOLVED_LOCAL | LF_UNRESOLVED_GLBL)) {
|
|
if (lx->flags & LF_UNRESOLVED_LOCAL) {
|
|
undef_locals=lx->undef_hash_entry;
|
|
lx->undef_hash_entry=NULL;
|
|
a->has_locals=TRUE;
|
|
} else if (lx->flags & LF_UNRESOLVED_GLBL) {
|
|
undef_glbls=lx->undef_hash_entry;
|
|
lx->undef_hash_entry=NULL;
|
|
}
|
|
} else {
|
|
i=Call(exp);
|
|
DelExpression(exp);
|
|
}
|
|
}
|
|
}
|
|
if (lx->token==TK_IDENT && lx->hash_entry) {
|
|
if (lx->hash_entry->type & HTT_KEYWORD && lx->hash_entry->user_data0==AKW_DUP) {
|
|
if (is_question)
|
|
PutAsmError(lx,"ST_QUESTION_NOT_ALLOWED");
|
|
else {
|
|
is_dup=TRUE;
|
|
if (Lex(lx)!='(')
|
|
PutAsmError(lx,"ST_EXPECTING_LEFT_PAREN");
|
|
else {
|
|
if (Lex(lx)=='?') {
|
|
is_question=TRUE;
|
|
Lex(lx); //SKIP "?"
|
|
} else
|
|
dup_value=AsmEvalExpression(lx);
|
|
if (lx->token!=')')
|
|
PutAsmError(lx,"ST_EXPECTING_RIGHT_PAREN");
|
|
else
|
|
Lex(lx); //SKIP ')'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (is_dup) {
|
|
if (undef_locals || undef_glbls)
|
|
PutAsmError(lx,"ST_UNDEFINED_DUP_CNT");
|
|
else
|
|
AsmStoreNum(lx,a,dup_value,is_question,num_U1s,i,0,1,exp,undef_locals,undef_glbls,FALSE,lx->absolute_address_cnt);
|
|
} else
|
|
AsmStoreNum(lx,a,i,is_question,num_U1s,1,0,1,exp,undef_locals,undef_glbls,FALSE,lx->absolute_address_cnt);
|
|
}
|
|
if (lx->token==',')
|
|
Lex(lx);
|
|
}
|
|
if (lx->token==';')
|
|
Lex(lx);
|
|
else
|
|
PutAsmError(lx,"ST_MISSING_SEMICOLON");
|
|
}
|
|
|
|
void CmpParseAsmBlk(LexStruct *lx)
|
|
{
|
|
AsmCtrlStruct *a=lx->a;
|
|
I8 i,j;
|
|
OpcodeHashEntry *tempo;
|
|
SysHashEntry *temph;
|
|
U8 argcnt,saved_ip;
|
|
BoolU4 is_literal;
|
|
U1 *file_buf,*b;
|
|
U8 file_size;
|
|
U8 old_hash_mask=lx->hash_mask;
|
|
I1 *next_last_label;
|
|
ArcCompressStruct *ac;
|
|
|
|
if (!a)
|
|
PutAsmError(lx,"ST_ASM_NOT_ALLOWED");
|
|
|
|
a->seg_size=64;
|
|
lx->flags|=LF_ASM_EXPRESSIONS;
|
|
lx->hash_mask&=~(HTT_INTERNAL_TYPE|HTT_CLASS|HTT_PUBLIC|
|
|
HTT_WORD|HTT_LOCAL_VAR|HTT_GLBL_VAR|HTT_FUNCTION|HTT_FILE|
|
|
HTT_MODULE|HTT_PRIVATE|HTT_EXPORT|HTT_IMPORT);
|
|
if (lx->token=='{')
|
|
Lex(lx);
|
|
else
|
|
PrsExcept(lx,"ST_MISSING_RIGHT_BRACE");
|
|
while (lx->token && lx->token!='}') {
|
|
AsmListLine(lx);
|
|
if (lx->token==TK_IDENT && lx->hash_entry) {
|
|
if (lx->hash_entry->type==HTT_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) {
|
|
if (temph=lx->hash_entry) {
|
|
temph=FindHashEntry(lx->ident,a->glbl_hash,HTT_ALL);
|
|
if (temph)
|
|
temph->type=HTT_SYS_SYMBOL+HTT_UNRESOLVED_GLBL;
|
|
}
|
|
if (!temph) {
|
|
temph=MAllocZ(sizeof(SysHashEntry));
|
|
temph->str=lx->ident;
|
|
lx->ident=0;
|
|
temph->type=HTT_SYS_SYMBOL+HTT_UNRESOLVED_GLBL;
|
|
temph->use_cnt=0;
|
|
temph->user_data0=0;
|
|
temph->user_data1=NULL;
|
|
SetSourceFileInfo(lx,temph);
|
|
AddSysHashEntry(temph,a->glbl_hash);
|
|
}
|
|
if (i==AKW_IMPORT)
|
|
temph->type|=HTT_IMPORT;
|
|
else if (i==AKW_EXPORT)
|
|
temph->type|=HTT_EXPORT;
|
|
if (is_literal)
|
|
temph->type|=HTT_LITERAL;
|
|
if (Lex(lx)==',')
|
|
Lex(lx); //skip ','
|
|
} else {
|
|
PutAsmError(lx,"ST_EXPECTING_IDENTIFIER");
|
|
break;
|
|
}
|
|
}
|
|
if (lx->token!=';')
|
|
PutAsmError(lx,"ST_MISSING_SEMICOLON");
|
|
else
|
|
Lex(lx); //skip ';';
|
|
break;
|
|
case AKW_ALIGN:
|
|
if (lx->token!=TK_INTEGER)
|
|
PutAsmError(lx,"ST_EXPECTING_INTEGER");
|
|
else {
|
|
i=(a->ip+lx->cur_i-1) & -lx->cur_i;
|
|
if (Lex(lx)==',')
|
|
Lex(lx);
|
|
if (lx->token==TK_INTEGER) {
|
|
for (j=a->ip;j<i;j++)
|
|
AsmStoreCodeU1(lx,lx->cur_i);
|
|
Lex(lx);
|
|
} else
|
|
a->ip=i;
|
|
}
|
|
break;
|
|
case AKW_END:
|
|
break; //TODO
|
|
case AKW_DU1:
|
|
DefineU1s(lx,a,1);
|
|
break;
|
|
case AKW_DU2:
|
|
DefineU1s(lx,a,2);
|
|
break;
|
|
case AKW_DU4:
|
|
DefineU1s(lx,a,4);
|
|
break;
|
|
case AKW_DU8:
|
|
DefineU1s(lx,a,8);
|
|
break;
|
|
case AKW_INSERT:
|
|
if (lx->token!=TK_STR)
|
|
PutAsmError(lx,"ST_EXPECTING_STR");
|
|
else {
|
|
file_buf=ReadFile(lx->ident,&file_size);
|
|
if (file_buf) {
|
|
for (i=0;i<file_size;i++)
|
|
AsmStoreCodeU1(lx,file_buf[i]);
|
|
Free(file_buf);
|
|
}
|
|
Lex(lx);
|
|
}
|
|
break;
|
|
case AKW_INSERT_COMPRESSED:
|
|
if (lx->token!=TK_STR)
|
|
PutAsmError(lx,"ST_EXPECTING_STR");
|
|
else {
|
|
file_buf=ReadFile(lx->ident,&file_size);
|
|
if (file_buf) {
|
|
ac=CompressBuf(file_buf,file_size);
|
|
b=ac;
|
|
for (i=0;i<ac->compressed_size;i++)
|
|
AsmStoreCodeU1(lx,b[i]);
|
|
Free(file_buf);
|
|
Free(ac);
|
|
}
|
|
Lex(lx);
|
|
}
|
|
break;
|
|
case AKW_LIST:
|
|
a->list=TRUE;
|
|
break;
|
|
case AKW_NOLIST:
|
|
a->list=FALSE;
|
|
break;
|
|
case AKW_ORG:
|
|
a->ip=AsmEvalExpression(lx);
|
|
break;
|
|
case AKW_STRUC:
|
|
a->flags|=ACSF_IN_STRUCT;
|
|
saved_ip=a->ip;
|
|
a->ip=AsmEvalExpression(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:
|
|
PutAsmError(lx,"ST_SYNTAX_ERROR");
|
|
break;
|
|
}
|
|
} else if (lx->hash_entry->type & HTT_OPCODE) {
|
|
tempo=lx->hash_entry;
|
|
Lex(lx); //skip opcode
|
|
argcnt=0;
|
|
if (tempo->ins[0].arg1) {
|
|
argcnt++;
|
|
ParseAsmArg(lx,a,&a->arg1,a->ip);
|
|
if (tempo->ins[0].arg2) {
|
|
argcnt++;
|
|
if (lx->token!=',')
|
|
PutAsmError(lx,"ST_EXPECTING_COMMA");
|
|
else {
|
|
Lex(lx); //skip ','
|
|
ParseAsmArg(lx,a,&a->arg2,a->ip);
|
|
}
|
|
}
|
|
}
|
|
AsmCodeInstruction(lx,a,tempo,argcnt);
|
|
} else if (lx->hash_entry->type & HTT_SYS_SYMBOL) {
|
|
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->user_data0=a->ip;
|
|
if (Lex(lx)!=':')
|
|
PutAsmError(lx,"ST_EXPECTING_COLON");
|
|
else
|
|
Lex(lx);
|
|
} else if (lx->hash_entry->type & HTT_UNRESOLVED_GLBL) {
|
|
if (lx->hash_entry->type & HTT_IMPORT)
|
|
PutAsmError(lx,"ST_ATTEMPT_DEFINE_IMPORT");
|
|
else {
|
|
lx->hash_entry->type&=~HTT_UNRESOLVED_GLBL;
|
|
lx->hash_entry->user_data0=a->ip;
|
|
next_last_label=lx->hash_entry->str;
|
|
Lex(lx); //Skip ident
|
|
if (lx->token!=':' && lx->token!=TK_DOUBLE_COLON)
|
|
PutAsmError(lx,"ST_EXPECTING_COLON");
|
|
else {
|
|
if (lx->token==TK_DOUBLE_COLON) {
|
|
lx->hash_entry->type|=HTT_EXPORT;
|
|
ResolveLocals(lx);
|
|
a->last_label=next_last_label;
|
|
}
|
|
if (Lex(lx)=='#') {
|
|
Lex(lx);
|
|
lx->hash_entry->type|=HTT_LITERAL | HTT_EXPORT;
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
PutAsmError(lx,"ST_REDEFINITION");
|
|
} else
|
|
PutAsmError(lx,"ST_SYNTAX_ERROR");
|
|
} else {
|
|
if (lx->token==TK_IDENT) {
|
|
temph=MAllocZ(sizeof(SysHashEntry));
|
|
temph->str=lx->ident;
|
|
lx->ident=0;
|
|
temph->type=HTT_SYS_SYMBOL;
|
|
if (a->flags & ACSF_IN_STRUCT)
|
|
temph->type|=HTT_LITERAL;
|
|
temph->use_cnt=0;
|
|
SetSourceFileInfo(lx,temph);
|
|
temph->user_data0=a->ip;
|
|
temph->user_data1=NULL;
|
|
Lex(lx); //Skip ident
|
|
if (lx->token==':' || lx->token==TK_DOUBLE_COLON) {
|
|
if (temph->str[0]=='@' && temph->str[1]=='@') {
|
|
AddSysHashEntry(temph,a->local_hash);
|
|
a->has_locals=TRUE;
|
|
} else
|
|
AddSysHashEntry(temph,a->glbl_hash);
|
|
if (lx->token==TK_DOUBLE_COLON) {
|
|
temph->type|=HTT_EXPORT;
|
|
ResolveLocals(lx);
|
|
a->last_label=temph->str;
|
|
Lex(lx);
|
|
} else {
|
|
if (Lex(lx)=='#') {
|
|
temph->type|=HTT_EXPORT | HTT_LITERAL;
|
|
ResolveLocals(lx);
|
|
a->last_label=temph->str;
|
|
Lex(lx);
|
|
}
|
|
}
|
|
} else {
|
|
PutAsmError(lx,"ST_EXPECTING_COLON");
|
|
Free(temph->str);
|
|
Free(temph);
|
|
}
|
|
} else
|
|
PutAsmError(lx,"ST_SYNTAX_ERROR");
|
|
}
|
|
}
|
|
ResolveLocals(lx);
|
|
lx->flags&=~LF_ASM_EXPRESSIONS;
|
|
lx->hash_mask=old_hash_mask;
|
|
Lex(lx); //Skip "}"
|
|
}
|
|
|