Files
TempleOS-Rijn/LT/COMPILE/ASM.CPZ
T
2018-09-08 21:45:17 +02:00

1411 lines
37 KiB
Plaintext

ClassStruct *CmpClassNew()
{
ClassStruct *result=MAllocZ(sizeof(ClassStruct)<<2),
*tempc=result;
tempc->last_in_member_list=&tempc->member_list;
tempc->type=HTT_CLASS;
tempc->sub_type=IT_I4;
tempc->pointer_cnt=0;
tempc+=sizeof(ClassStruct);
tempc->type=HTT_CLASS;
tempc->sub_type=IT_I4;
tempc->size=4;
tempc->pointer_cnt=1;
tempc+=sizeof(ClassStruct);
tempc->type=HTT_CLASS;
tempc->sub_type=IT_I4;
tempc->size=4;
tempc->pointer_cnt=2;
tempc+=sizeof(ClassStruct);
tempc->type=HTT_CLASS;
tempc->sub_type=IT_I4;
tempc->size=4;
tempc->pointer_cnt=3;
return result;
}
void LoadAsmHash(BoolU4 first)
{
U8 i,type;
U4 *dd;
LexStruct *l;
I8 size,size1;
SysHashEntry *temph,**temph1;
ClassStruct *tempc;
OpcodeHashEntry *tempo,*tempo1;
InstructionEntry *tempi;
asm_hash=NewHashTable(2048);
size1=offset(OpcodeHashEntry.ins)+sizeof(InstructionEntry)<<5;
tempo=MAlloc(size1);
l=LexNew(ReadTextFile("ASM.TXZ"),0,NewString("ASM.TXZ"));
l->hash_table_list=NULL;
Lex(l);
while (l->token) {
if (l->token!=TK_IDENT)
PutAsmError(l,"ST_EXPECTING_IDENTIFIER");
else {
i=MatchListEntry(l->ident,"OPCODE\0KEYWORD\0R8\0R16\0R32\0SEG\0\0",MLE_IGNORE_CASE);
Lex(l); //skip keyword
if (!i) { //OPCODE
MemSet(tempo,0,size1);
tempo->type=HTT_OPCODE;
tempo->instruction_entry_cnt=0;
tempo->string=l->ident;
l->ident=0;
Lex(l); //Skip OPCODE
while (l->token && l->token!=';') {
tempi=&tempo->ins[tempo->instruction_entry_cnt];
tempi->ins_entry_num=tempo->instruction_entry_cnt++;
tempi->opcode_cnt=0;
while (l->token==TK_INTEGER) {
tempi->opcode[tempi->opcode_cnt++]=l->cur_i;
Lex(l);
}
if (l->token=='+') {
tempi->plus_opcode=1;
Lex(l);
} else
tempi->plus_opcode=0;
if (l->token=='/') {
if (Lex(l)==TK_INTEGER) {
tempi->slash_value=l->cur_i;
Lex(l);
} else if (l->token==TK_IDENT) {
tempi->slash_value=8;
Lex(l);
}
} else
tempi->slash_value=9;
if (l->token=='*') {
tempi->operand_size16=1;
Lex(l);
} else
tempi->operand_size16=0;
if (l->token=='%') {
tempi->operand_size32=1;
Lex(l);
} else
tempi->operand_size32=0;
if (l->token=='!') {
tempi->dont_switch_modes=1;
Lex(l);
} else
tempi->dont_switch_modes=0;
if (l->token=='&') {
tempi->default=1;
Lex(l);
} else
tempi->default=0;
if (l->token!=TK_IDENT)
PutAsmError(l,"ST_EXPECTING_IDENTIFIER");
else {
tempi->opcode_modifier=MatchSysTextEntry(l->ident,
"ST_OPCODE_MODIFIERS",MLE_IGNORE_CASE);
tempi->arg1=0;
tempi->arg2=0;
if (Lex(l)==TK_IDENT) {
tempi->arg1=MatchSysTextEntry(l->ident,
"ST_ARGUMENT_TYPES",MLE_IGNORE_CASE);
if (Lex(l)==TK_IDENT) {
tempi->arg2=MatchSysTextEntry(l->ident,
"ST_ARGUMENT_TYPES",MLE_IGNORE_CASE);
Lex(l);
}
}
}
}
if (l->token==';') {
Lex(l); //Skip ';'
size=offset(OpcodeHashEntry.ins)+
sizeof(InstructionEntry)*tempo->instruction_entry_cnt;
tempo1=MAlloc(size);
MemCpy(tempo1,tempo,size);
temph1=FindHashBucket(tempo1->string,asm_hash);
tempo1->use_cnt=0;
SetSourceFileInfo(l,tempo1);
tempo1->next=*temph1;
*temph1=tempo1;
} else
PutAsmError(l,"ST_MISSING_SEMICOLON");
} else if (i>=1 && i<=5) { //KEYWORD,R8,R16,R32,SEG
if (l->token!=TK_IDENT)
PutAsmError(l,"ST_EXPECTING_IDENTIFIER");
else {
temph=MAllocZ(sizeof(SysHashEntry));
temph->string=l->ident;
l->ident=NULL;
temph->use_cnt=0;
SetSourceFileInfo(l,temph);
Lex(l); //skip keyword name
if (l->token!=TK_INTEGER)
PutAsmError(l,"ST_EXPECTING_INTEGER");
else {
temph->user0=l->cur_i;
if (Lex(l)!=';')
PutAsmError(l,"ST_MISSING_SEMICOLON");
else {
Lex(l); //skip ';'
temph1=FindHashBucket(temph->string,asm_hash);
temph->next=*temph1;
*temph1=temph;
}
}
switch (i) {
case 1:
temph->type=HTT_KEYWORD;
if (first) {
temph=MAllocIdentical(temph);
temph1=FindHashBucket(temph->string,adam_tss->hash_table);
temph->next=*temph1;
*temph1=temph;
}
break;
case 2: temph->type=HTT_R8; break;
case 3: temph->type=HTT_R16; break;
case 4: temph->type=HTT_R32; break;
case 5: temph->type=HTT_SEG; break;
}
}
} else
PutAsmError(l,"Unknown Statement");
}
}
Free(tempo);
LexDel(l);
dd=internal_types_table;
while (*dd!=HTT_INVALID) {
tempc=CmpClassNew;
tempc->type=*dd; dd+=4;
tempc->use_cnt=0;
tempc->source_link=NULL;
tempc->sub_type=*dd; dd+=4;
tempc->size=*dd; dd+=4;
tempc->string=ANewString(dd);
dd+=StrLen(tempc->string)+1;
temph1=FindHashBucket(tempc->string,asm_hash);
tempc->next=*temph1;
*temph1=tempc;
sys_internal_types[tempc->sub_type]=tempc;
if (first) {
tempc=MAllocIdentical(tempc);
temph1=FindHashBucket(tempc->string,adam_tss->hash_table);
tempc->next=*temph1;
*temph1=tempc;
}
}
}
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->string=NULL;
if (glbl) {
tempu->next=a->glbl_unresolved;
a->glbl_unresolved=tempu;
if (undef_hash->hash->type & HTT_IMPORT) {
tempu->string=NewString(undef_hash->hash->string);
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 *l)
{
I8 i;
AsmCtrlStruct *a=l->a;
LexFileStruct *tempf=l->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(l,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;
}
exe {NoRegVar(ON);}
void AsmStoreCodeU1(LexStruct *l,U1 b)
{
AsmCtrlStruct *a=l->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(l);
}
}
if (a->ip>a->num_code_U1s)
a->num_code_U1s=a->ip;
}
exe {NoRegVar(OFF);}
void AsmStoreCodeU1At(LexStruct *l,U1 b,I8 ip)
{
AsmCtrlStruct *a=l->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 *l)
{
U1 *exp;
I8 result=0;
l->undef_hash_entry=NULL;
l->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
l->absolute_address_cnt=0;
if (!GetExpression(l,&exp))
LexSkipEol(l);
else {
if (!(l->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
result=Run(exp);
DelExpression(exp);
} else
PutAsmError(l,"ST_UNDEFINED_SYMBOL");
}
return result;
}
void ResolveLocals(LexStruct *l)
{
AsmCtrlStruct *a=l->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)) {
cout SysText("ST_ERROR"),SysText("ST_UNDEFINED_SYMBOL"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
if (a->last_label) cout a->last_label," ";
coutln templu->hash->string;
l->error_cnt++;
undefined=TRUE;
} else
label=templu->hash->string;
templu=templu->next;
}
if (!undefined) {
result=Run(tempu->exp);
if (!(tempu->type & 1)) {
result-=tempu->rel_ip;
if (tempu->type==EIE_REL_U1 && (result<-128 || result>127) ||
tempu->type==EIE_REL_U2 && (result<-0x8000 || result>0x7FFF) ) {
cout SysText("ST_ERROR"),SysText("ST_BRANCH_OUT_OF_RANGE"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
if (a->last_label)
PrintF("%s ",a->last_label);
if (label) cout label;
CrLf;
l->error_cnt++;
}
if (tempu->U1_avail && tempu->type>EIE_LIT_U1 && (result>=-124 && result<=123)) {
cout SysText("ST_WARNING"),SysText("ST_COULD_USE_U1_DISP"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
if (a->last_label)
PrintF("%s ",a->last_label);
if (label) cout label;
CrLf;
}
}
AsmStoreCodeU1At(l,result.u1[0],tempu->ip);
if (tempu->type>=EIE_REL_U2)
AsmStoreCodeU1At(l,result.u1[1],tempu->ip+1);
if (tempu->type>=EIE_REL_U4) {
AsmStoreCodeU1At(l,result.u1[2],tempu->ip+2);
AsmStoreCodeU1At(l,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;
l->hash_table_list=a->local_hash;
l->local_hash_table=a->local_hash;
a->local_unresolved=NULL;
a->has_locals=FALSE;
}
void ResolveGlbls(LexStruct *l,ExeStruct *e)
{
AsmCtrlStruct *a=l->a;
ClassStruct *tempc;
GlblVarStruct *tempg;
AsmUnresolvedRef *tempu=a->glbl_unresolved,*tempu1;
I8 result=0;
ExeImportExportStruct *tempe,*tempe1;
LexUndefEntry *templu;
I8 i;
SysHashEntry *temph;
I1 *label;
BoolU4 undefined;
l;//Ref so no warning
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)) {
cout SysText("ST_ERROR"),SysText("ST_UNDEFINED_SYMBOL"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
cout templu->hash->string,"\r\n";
l->error_cnt++;
}
undefined=TRUE;
} else
label=templu->hash->string;
templu=templu->next;
}
if (undefined) {
templu=tempu->undef_hash;
if (templu->hash->type & HTT_IMPORT) {
tempe=MAllocZ(sizeof(ExeImportExportStruct));
tempe->next=templu->hash->user1;
tempe->string=NULL;
templu->hash->user1=tempe;
tempe->ip=tempu->ip;
tempe->type=tempu->type;
}
} else {
result=Run(tempu->exp);
if (!(tempu->type & 1)) {
result=result-tempu->rel_ip;
if ((tempu->type==EIE_REL_U1 && (result<-128 || result>127)) ||
tempu->type==EIE_REL_U2 && (result<-0x8000 || result>0x7FFF)) {
cout SysText("ST_ERROR"),SysText("ST_BRANCH_OUT_OF_RANGE"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
if (label) cout label;
CrLf;
l->error_cnt++;
}
if (tempu->U1_avail && tempu->type>EIE_LIT_U1 && (result>=-124 && result<=123)) {
cout SysText("ST_WARNING"),SysText("ST_COULD_USE_U1_DISP"),SysText("ST_LINE");
PrintF("%04d ",tempu->line_num);
if (a->last_label)
PrintF("%s ",a->last_label);
if (label) cout label;
CrLf;
}
}
AsmStoreCodeU1At(l,result.u1[0],tempu->ip);
if (tempu->type>=EIE_REL_U2)
AsmStoreCodeU1At(l,result.u1[1],tempu->ip+1);
if (tempu->type>=EIE_REL_U4) {
AsmStoreCodeU1At(l,result.u1[2],tempu->ip+2);
AsmStoreCodeU1At(l,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->string=(tempc->import_name) ?
NewString(tempc->import_name):NewString(tempc->string);
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->string=NewString(tempg->import_name);
else
tempe->string=NewString(tempg->string);
tempe->ip=tempg->data_address;
tempe1->next=tempe;
tempe1=tempe;
} else {
tempe=temph->user1;
if (tempe) {
tempe1->next=tempe;
tempe->string=NewString(temph->string);
while (tempe1->next)
tempe1=tempe1->next;
}
}
} else if (temph->type & HTT_EXPORT) {
if (temph->type & HTT_UNRESOLVED_GLBL) {
coutln SysText("ST_ERROR"),SysText("ST_UNDEFINED_SYMBOL"),temph->string;
l->error_cnt++;
} else {
tempe=MAlloc(sizeof(ExeImportExportStruct));
tempe->type=EIE_REL_EXPORT;
if (temph->type & HTT_FUNCTION) {
tempc=temph;
tempe->ip=tempc->executable_address;
} else if (temph->type & HTT_GLBL_VAR) {
tempg=temph;
tempe->ip=tempg->data_address;
} else
tempe->ip=temph->user0;
if (temph->type & HTT_LITERAL)
tempe->type++;
*tempe1=tempe;
tempe->next=NULL;
tempe1=tempe;
tempe->string=NewString(temph->string);
}
}
temph=temph->next;
}
}
}
BoolU4 ParseAsmImm(LexStruct *l,AsmCtrlStruct *aa,AsmArgStruct *a,U8 ip)
{
if (a->imm_or_off_present) {
PutAsmError(l,"ST_ALREADY_ONE_IMMEDIATE");
return FALSE;
} else {
a->imm_or_off_present=TRUE;
a->undef_local=NULL;
a->undef_glbl=NULL;
l->instruction_pointer=ip;
l->undef_hash_entry=NULL;
l->absolute_address_cnt=0;
l->flags&=~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
if (!GetExpression(l,&a->exp))
LexSkipEol(l);
else {
if (!(l->flags & (LF_UNRESOLVED_LOCAL|LF_UNRESOLVED_GLBL))) {
a->imm=Run(a->exp);
a->undef_glbl=l->undef_hash_entry;
l->undef_hash_entry=NULL;
DelExpression(a->exp);
a->exp=NULL;
} else {
if (l->flags & LF_UNRESOLVED_GLBL) {
a->undef_glbl=l->undef_hash_entry;
l->undef_hash_entry=NULL;
aa->has_locals=TRUE;
} else if (l->flags & LF_UNRESOLVED_LOCAL) {
a->undef_local=l->undef_hash_entry;
l->undef_hash_entry=NULL;
}
}
}
}
return TRUE;
}
void ParseAsmArg(LexStruct *l,AsmCtrlStruct *aa,AsmArgStruct *a,U8 ip)
{
I8 i,temp;
a->size=0;
a->absolute_address_cnt=0;
a->seg=8;
a->reg1=8;
a->reg2=8;
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 (l->token==TK_IDENT) {
if (l->hash_entry) {
if (l->hash_entry->type==HTT_R8) {
a->size=1;
a->reg1=l->hash_entry->user0;
Lex(l);
return;
} else if (l->hash_entry->type==HTT_R16) {
a->size=2;
a->reg1=l->hash_entry->user0;
Lex(l);
return;
} else if (l->hash_entry->type==HTT_R32) {
a->size=4;
a->reg1=l->hash_entry->user0;
Lex(l);
return;
} else if (l->hash_entry->type==HTT_SEG) {
a->seg=l->hash_entry->user0;
if (Lex(l)!=':') {
a->just_seg=TRUE;
return;
} else
Lex(l); //skip ":"
} else if (l->hash_entry->type==HTT_KEYWORD) {
i=l->hash_entry->user0;
if (i==AKW_U1) {
Lex(l); //skip keyword
a->size=1;
} else if (i==AKW_U2) {
Lex(l); //skip keyword
a->size=2;
} else if (i==AKW_U4) {
Lex(l); //skip keyword
a->size=4;
} else {
PutAsmError(l,"ST_SYNTAX_ERROR");
return;
}
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
if (l->token!='[')
return;
}
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
if (l->token!='[')
return;
}
} else if (l->token=='[') {
a->indirect=TRUE;
Lex(l); // skip [
while (l->token && l->token!=']') {
if (l->token==TK_IDENT) {
if (l->hash_entry) {
if (l->hash_entry->type==HTT_R16 || l->hash_entry->type==HTT_R32) {
if (a->reg1==8)
a->reg1=l->hash_entry->user0;
else
a->reg2=l->hash_entry->user0;
Lex(l);
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
}
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
}
} else if (l->token=='*') {
if (Lex(l)!=TK_INTEGER)
PutAsmError(l,"ST_EXPECTING_SCALE_FACTOR");
else {
a->scale=l->cur_i;
Lex(l); //skip scale
if (a->reg2!=8) {
temp=a->reg1;
a->reg1=a->reg2;
a->reg2=temp;
}
}
} else if (l->token=='+') {
Lex(l); //skip '+'
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
}
}
if (l->token==']') {
Lex(l); //skip ]
return;
} else
PutAsmError(l,"ST_MISSING_RIGHT_BRACKET");
} else {
ParseAsmImm(l,aa,a,ip);
a->absolute_address_cnt=l->absolute_address_cnt;
if (l->token!='[')
return;
}
}
}
void AsmMakeArgMask(AsmArgStruct *a,U8 *mask)
{
if (a->just_seg) {
mask->u4[0]=0;
if (!a->seg)
mask->u4[1]=0x24;
else if (a->seg==1)
mask->u4[1]=0x60;
else if (a->seg==2)
mask->u4[1]=0x21;
else if (a->seg==3)
mask->u4[1]=0x22;
else if (a->seg==4)
mask->u4[1]=0x28;
else
mask->u4[1]=0x30;
return;
}
mask->u4[1]=0;
if (!a->size)
mask->u4[0]=0xFF07FFFE;
else if (a->size==1)
mask->u4[0]=0x19012492;
else if (a->size==2)
mask->u4[0]=0xA2024924;
else if (a->size==4)
mask->u4[0]=0x44049248;
if (a->reg1!=8 && 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!=8 || a->scale!=1) {
mask->u4[0]&=0x0000E000;
return;
}
if (a->indirect) {
if (a->imm_or_off_present) {
mask->u4[0]&=0x07FFE000;
} else
mask->u4[0]&=0x00FFE000;
} else {
if (a->imm_or_off_present)
mask->u4[0]&=0x00F81C7E;
else
mask->u4[0]&=0xF8F8E380;
}
if (a->seg!=8)
mask->u4[0]&=0x07FFE000;
if (a->reg1==8) {
if (a->indirect)
mask->u4[0]&=0x07FFE000;
else if (a->imm>=-128 && a->imm<=127)
mask->u4[0]&=0x00001C7E;
else if (a->imm>=-128 && a->imm<=255)
mask->u4[0]&=0x0000187E;
else if (a->imm>=-0x8000 && a->imm<=0x7FFF)
mask->u4[0]&=0x0000186E;
else if (a->imm>=-0x8000 && a->imm<=0xFFFF)
mask->u4[0]&=0x0000106E;
else
mask->u4[0]&=0x0000104E;
} else
mask->u4[0]&=0xF807E380;
if (a->reg1!=0)
mask->u4[0]&=0x8FFFFFFF;
if (a->reg1!=1)
mask->u4[0]&=0xF7FFFFFF;
if (a->reg1!=2)
mask->u4[0]&=0x7FFFFFFF;
// coutln "MASK:",mask->u4[0];
}
BoolU4 AsmStoreNum(LexStruct *l,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,j;
ExeAbsoluteAddressStruct *tempa;
if (!num_lit)
num=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(l),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(l),U1_avail,TRUE);
else {
if (!num_lit && (num<-128 || num>127)) {
LexPop(l);
PutAsmError(l,"ST_BRANCH_OUT_OF_RANGE");
a->ip++;
return FALSE;
}
}
if (is_question)
a->ip++;
else
AsmStoreCodeU1(l,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(l),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(l),U1_avail,TRUE);
else {
if (!num_lit && (num <-0x8000 || num>0x7FFF)) {
LexPop(l);
PutAsmError(l,"ST_BRANCH_OUT_OF_RANGE");
a->ip+=2;
return FALSE;
}
}
if (is_question)
a->ip+=2;
else {
AsmStoreCodeU1(l,num.u1[0]);
AsmStoreCodeU1(l,num.u1[1]);
}
if (U1_avail && !num_local_hash && !num_glbl_hash &&
!num_lit && num>=-124 && num<=123) {
LexPop(l);
PutAsmWarning(l,"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(l),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(l),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+=4;
else
for (j=0;j<num_U1s;j++)
AsmStoreCodeU1(l,num.u1[j]);
if (U1_avail && !num_local_hash && !num_glbl_hash &&
!num_lit && num>=-124 && num<=123) {
LexPop(l);
PutAsmWarning(l,"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(l),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(l),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+=8;
else
for (j=0;j<num_U1s;j++)
AsmStoreCodeU1(l,num.u1[j]);
if (U1_avail && !num_local_hash && !num_glbl_hash &&
!num_lit && num>=-124 && num<=123) {
LexPop(l);
PutAsmWarning(l,"ST_COULD_USE_U1_DISP");
return FALSE;
}
}
}
return TRUE;
}
BoolU4 AsmCodeInstruction(LexStruct *l,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;
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;
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;
if (tempi->default)
is_default=TRUE;
else
is_default=FALSE;
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->use16 && tempi->operand_size32) ||
(!a->use16 && tempi->operand_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) {
cout SysText("ST_WARNING"),SysText("ST_NO_SIZE_SPECIFIED");
PrintF("%s,%04d\r\n",l->cur_lfn->name,l->cur_lfn->line_num-1);
}
}
if (tempi->plus_opcode)
last_opcode_U1=last_opcode_U1+tempa1->reg1;
if (a1>=ARGT_RM8 && a1<=ARGT_RM32) {
if (a->use16)
has_address_prefix=TRUE;
has_ModrM=TRUE;
if (tempa1->imm_or_off_present && tempa1->indirect && tempa1->reg1==8) {
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;
} else {
if (tempa1->reg2==8 && tempa1->scale==1)
ModrM+=tempa1->reg1;
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==8) {
ModrM_complete=TRUE;
SIB=SIB+(tempa1->reg1<<3)+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;
} else {
SIB=SIB+(tempa1->reg1<<3)+tempa1->reg2;
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 && disp>=-128 && disp<=127) {
ModrM+=0x40;
disp_U1s=1;
} else if (a->use16) {
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_IMM32 ||
a1>=ARGT_UIMM8 && a1<=ARGT_UIMM32) {
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==0 && a->arg2.size==0) {
cout SysText("ST_WARNING"),SysText("ST_NO_SIZE_SPECIFIED");
PrintF("%s,%04d\r\n",l->cur_lfn->name,l->cur_lfn->line_num-1);
}
}
if (tempi->plus_opcode) {
if (om>=OM_RB && om<=OM_RD)
last_opcode_U1+=tempa1->reg1;
else if (tempi->slash_value==8) {
if (a1>=ARGT_AL && a1<=ARGT_EAX)
last_opcode_U1+=tempa2->reg1;
else if (a2>=ARGT_AL && a2<=ARGT_EAX)
last_opcode_U1+=tempa1->reg1;
}
}
if (a1>=ARGT_RM8 && a1<=ARGT_RM32 ||a2>=ARGT_RM8 && a2<=ARGT_RM32) {
if (a->use16)
has_address_prefix=TRUE;
has_ModrM=TRUE;
if (a2>=ARGT_RM8 && a2<=ARGT_RM32) {
tempa1=&a->arg2;
tempa2=&a->arg1;
}
if (tempi->slash_value==8) {
if (tempa2->just_seg)
ModrM+=(tempa2->seg<<3);
else {
if (tempa2->reg1==8)
ModrM+=(tempa1->reg1<<3);
else
ModrM+=(tempa2->reg1<<3);
}
}
if (tempa1->reg2==8 && tempa1->scale==1) {
if (tempa1->reg1!=8)
ModrM+=tempa1->reg1;
} 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==8) {
ModrM_complete=TRUE;
SIB+=(tempa1->reg1<<3)+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;
} else {
SIB+=(tempa1->reg1<<3)+tempa1->reg2;
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==8) {
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;
} 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 && disp>=-128 && disp<=127) {
ModrM+=0x40;
disp_U1s=1;
} else if (a->use16) {
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_MOFFS32) {
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->use16)
disp_U1s=2;
else
disp_U1s=4;
has_address_prefix=FALSE;
} else if (a2>=ARGT_MOFFS8 && a2<=ARGT_MOFFS32) {
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->use16)
disp_U1s=2;
else
disp_U1s=4;
has_address_prefix=FALSE;
} else if (a1>=ARGT_IMM8 && a1<=ARGT_IMM32 ||
a1>=ARGT_UIMM8 && a1<=ARGT_UIMM32) {
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 imm_U1s=4;
}
if (a2>=ARGT_IMM8 && a2<=ARGT_IMM32 ||
a2>=ARGT_UIMM8 && a2<=ARGT_UIMM32) {
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 imm_U1s=4;
}
}
U1_cnt=tempi->opcode_cnt+disp_U1s+imm_U1s;
if (has_ModrM) U1_cnt++;
if (has_SIB) U1_cnt++;
if (U1_cnt<best_U1_cnt &&
!(tempi->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;
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(l,0x66); //Operand size override
if (bhas_address_prefix || a->use16 && has_SIB)
AsmStoreCodeU1(l,0x67); //Operand size override
seg=8;
if (argcnt>1 && a->arg2.seg!=8 && !a->arg2.just_seg)
seg=a->arg2.seg;
else if (argcnt>0 && a->arg1.seg!=8 && !a->arg1.just_seg)
seg=a->arg1.seg;
if (seg!=8) {
if (seg==0)
AsmStoreCodeU1(l,0x26); //ES:
else if (seg==1)
AsmStoreCodeU1(l,0x2E); //CS:
else if (seg==2)
AsmStoreCodeU1(l,0x36); //SS:
else if (seg==3)
AsmStoreCodeU1(l,0x3E); //DS:
else if (seg==4)
AsmStoreCodeU1(l,0x64); //FS:
else
AsmStoreCodeU1(l,0x65); //GS:
}
for (j=0;j<btempi->opcode_cnt-1;j++)
AsmStoreCodeU1(l,btempi->opcode[j]);
AsmStoreCodeU1(l,blast_opcode_U1);
if (bhas_ModrM)
AsmStoreCodeU1(l,bModrM);
if (bhas_SIB)
AsmStoreCodeU1(l,bSIB);
if (bdisp_U1s) {
bdisp_ip_rel=a->ip+bdisp_U1s+bimm_U1s;
if (!AsmStoreNum(l,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(l,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(l);
PutAsmError(l,"ST_INVALID_INSTRUCTION");
return FALSE;
}
void DefineU1s(LexStruct *l,AsmCtrlStruct *a,I8 num_U1s)
{
BoolU4 is_question,is_dup;
I8 i,dup_value;
U1 *exp;
I1 *ptr;
LexUndefEntry *undef_locals,*undef_glbls;
while (l->token && l->token!=';') {
undef_locals=NULL;
undef_glbls=NULL;
if (l->token==TK_STRING) {
ptr=l->ident;
i=l->ident_len-1;
while (i--)
AsmStoreCodeU1(l,*ptr++);
Lex(l); //SKip STRING
} else {
is_question=FALSE;
is_dup=FALSE;
l->absolute_address_cnt=0;
if (l->token=='?') {
is_question=TRUE;
Lex(l);
} else {
l->undef_hash_entry=NULL;
l->flags=l->flags & ~(LF_UNRESOLVED_LOCAL+LF_UNRESOLVED_GLBL);
if (!GetExpression(l,&exp))
LexSkipEol(l);
else {
if (l->flags & (LF_UNRESOLVED_LOCAL | LF_UNRESOLVED_GLBL)) {
if (l->flags & LF_UNRESOLVED_LOCAL) {
undef_locals=l->undef_hash_entry;
l->undef_hash_entry=NULL;
a->has_locals=TRUE;
} else if (l->flags & LF_UNRESOLVED_GLBL) {
undef_glbls=l->undef_hash_entry;
l->undef_hash_entry=NULL;
}
} else {
i=Run(exp);
DelExpression(exp);
}
}
}
if (l->token==TK_IDENT && l->hash_entry) {
if (l->hash_entry->type & HTT_KEYWORD && l->hash_entry->user0==AKW_DUP) {
if (is_question)
PutAsmError(l,"ST_QUESTION_NOT_ALLOWED");
else {
is_dup=TRUE;
if (Lex(l)!='(')
PutAsmError(l,"ST_EXPECTING_LEFT_PAREN");
else {
if (Lex(l)=='?') {
is_question=TRUE;
Lex(l); //SKIP "?"
} else
dup_value=AsmEvalExpression(l);
if (l->token!=')')
PutAsmError(l,"ST_EXPECTING_RIGHT_PAREN");
else
Lex(l); //SKIP ')'
}
}
}
}
if (is_dup) {
if (undef_locals || undef_glbls)
PutAsmError(l,"ST_UNDEFINED_DUP_CNT");
else
AsmStoreNum(l,a,dup_value,is_question,num_U1s,i,0,1,exp,undef_locals,undef_glbls,FALSE,l->absolute_address_cnt);
} else
AsmStoreNum(l,a,i,is_question,num_U1s,1,0,1,exp,undef_locals,undef_glbls,FALSE,l->absolute_address_cnt);
}
if (l->token==',')
Lex(l);
}
if (l->token==';')
Lex(l);
else
PutAsmError(l,"ST_MISSING_SEMICOLON");
}