Files
TempleOS-Rijn/LT/Compiler/AsmMain.CPZ
T
2018-09-08 21:45:20 +02:00

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 "}"
}