#define _TOKB_ #include "tok.h" char badadr[]="Bad outrm value in outaddress();"; char CXandDX[]="CX and DX"; char ECXandEDX[]="ECX and EDX"; char BXandFS[]="BX and FS"; int divexpand=FALSE; int optnumber=FALSE; ITOK itok,itok2,ptok; char *pbuf; SINFO pstr; LISTFLOAT *floatnum=NULL; //список float констант unsigned int numfloatconst=0; unsigned int maxnumfloatconst; #define STEPFLOATCONST 16 unsigned int ofsfloatlist=0; unsigned char idxregs[5]={ESI,EDI,EBX,EDX,255}; int expandvar(); int speedmul(unsigned long num, int razr); int leamul32(unsigned long num,int reg,int razr); void Float2reg32(int reg,int addop=0,int reg1=idxregs[0],int reg2=idxregs[1]); void NegReg(int razr,int reg); int RshiftReg(int razr,int reg,int sign); void do_e_axmath2(int sign,int razr,int expand); int MulReg(int reg,int razr); void DivMod(int vop,int sign,int razr,int expand); void DivNum2(unsigned long num,int razr,int sign); void DivNum(unsigned long num,int razr,int sign); void ClearDX(int razr,int sign); void doalmath2(int sign); void num2bits(ITOK *gtok,unsigned long num,int razr); void reg2bits(ITOK *gtok,int razr); void cwpointr(ITOK *wtok,char *&wbuf,SINFO *wstr,int *otok,int npointr,int ureg); int CheckAddOnly(); void optnumadd64(unsigned long long num,int r1,int r2,int vop); void CallExternProc(char *name); void getinto_reg(int gtok,ITOK *gstok,char *&gbuf,SINFO *gstr,int razr,int reg); void intinstack(int addop); extern void warningoptnum(); extern void segoperror(); extern void segbyteerror(); extern void regmathoperror(); extern void begmathoperror(); extern void negregerror(); extern void regbyteerror(); extern void begworderror(); extern void regshifterror(); extern void regmatherror(); extern void DevideZero(); extern void wordnotoper(); unsigned long long li[]={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,0x100,0x200,0x400, 0x800,0x1000,0x2000,0x4000,0x8000,0x10000,0x20000,0x40000,0x80000,0x100000, 0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0x10000000, 0x20000000,0x40000000,0x80000000,0x100000000LL,0x200000000LL,0x400000000LL ,0x800000000LL,0x1000000000LL,0x2000000000LL,0x4000000000LL,0x8000000000LL ,0x10000000000LL,0x20000000000LL,0x40000000000LL,0x80000000000LL ,0x100000000000LL,0x200000000000LL,0x400000000000LL,0x800000000000LL ,0x1000000000000LL,0x2000000000000LL,0x4000000000000LL,0x8000000000000LL ,0x10000000000000LL,0x20000000000000LL,0x40000000000000LL,0x80000000000000LL ,0x100000000000000LL,0x200000000000000LL,0x400000000000000LL,0x800000000000000LL ,0x1000000000000000LL,0x2000000000000000LL,0x4000000000000000LL,0x8000000000000000LL}; unsigned long leanum[24]={3,5,9,15,25,27,45,81,75,125,135,225,243,405,729, 375,675,1215,2187,625,1125,2025,3645,6561}; unsigned int numleamul[24][4]={ {3,0,0,0},{5,0,0,0},{9,0,0,0},{3,5,0,0},{5,5,0,0},{3,9,0,0},{5,9,0,0}, {9,9,0,0},{5,5,3,0},{5,5,5,0},{9,5,3,0},{9,5,5,0},{9,9,3,0},{9,9,5,0}, {9,9,9,0},{5,5,5,3},{5,5,9,3},{9,9,5,3},{9,9,9,3},{5,5,5,5},{9,5,5,5}, {9,9,5,5},{9,9,9,5},{9,9,9,9}}; int RmEqualReg(int reg,int rm,int sib) { int rm0; int reg1=-1,reg2=-1; rm0=rm&0x7; if(sib==CODE16){ switch(rm0){ case 0: reg1=BX; reg2=SI; break; case 1: reg1=BX; reg2=DI; break; case 2: reg1=BP; reg2=SI; break; case 3: reg1=BP; reg2=DI; break; case 4: reg1=SI; break; case 5: reg1=DI; break; case 6: if((rm&0xC0)!=0)reg1=BP; break; case 7: reg1=BX; break; } } else{ if(rm0==4){ reg1=sib&7; reg2=(sib>>3)&7; if(reg1==5&&(rm&0xc0)==0)reg1=-1; if(reg2==4)reg2=-1; } else{ reg1=rm0; if(reg1==5&&(rm&0xc0)==0)reg1=-1; } } if(reg==reg1||reg==reg2)return TRUE; return FALSE; } void startmul(int razr) { if(razr==r8)outword(0xE08A); //mov ah,al else{ op66(razr); outword(0xD08B); //mov dx,ax warningreg(regs[razr/2-1][2]); } } void lshiftmul(int num,int razr,int reg=AX) { if(razr==r8){ if(num==1)outword(0xC002); //add al,al else{ if(chip==0){ op(0xB1); //mov cl,num op(num); outword(0xE0D2); //shl al,cl warningreg(begs[1]); } else{ outword(0xE0C0); //shl al,num op(num); } } } else{ if(num==1){ op66(razr); op(1); op(0xC0+reg*9); //add reg,reg } else{ if(chip==0){ op(0xB1); //mov cl,num op(num); op(0xD3); op(0xE0+reg); //shl ax,cl warningreg(begs[1]); } else{ if(chip>2&&optimizespeed&&leamul32(li[num],reg,razr))return; op66(razr); op(0xC1); op(0xE0+reg); //shl ax,num op(num); } } } } void submul(int razr) { if(razr==r8)outword(0xC42A); //sub al,ah else{ op66(razr); outword(0xC22B); //sub ax,dx } } void addmul(int razr) { if(razr==r8)outword(0xC402); //add al,ah else{ op66(razr); outword(0xC203); //add ax,dx } } int leamul32(unsigned long num,int reg,int razr) { if(num==0)return FALSE; int vop=0,i=8*reg+4; switch(num){ case 9: vop+=0x40; case 5: vop+=0x40; case 3: vop+=0x40; op66(razr); op67(r32); // AX * n = LEA AX,[EAX*n+?EAX] op(0x8d); op(reg==BP?i|rm_mod01:i); op(vop+9*reg); if(reg==BP)op(0); return TRUE; } // if(chip>3&&chip<7)return FALSE; //избежать AGI для 486,p5,p5mmx switch(num){ case 2: vop=reg; break; case 4: vop=0x85; break; case 8: vop=0xc5; break; default: return FALSE; } op66(razr); op67(r32); // AX * n = LEA AX,[EAX*n+?EAX] op(0x8d); if(vop!=0x85&&vop!=0xc5&®==BP)i|=rm_mod01; op(i); op(vop+8*reg); if(vop==0x85||vop==0xc5)outdword(0L); else if(reg==BP)op(0); return TRUE; } int speedmul32(unsigned long num,int reg,int razr) { int i; for(i=3;i<24;i++){ if(leanum[i]==num){ leamul32(numleamul[i][0],reg,razr); leamul32(numleamul[i][1],reg,razr); leamul32(numleamul[i][2],reg,razr); leamul32(numleamul[i][3],reg,razr); return TRUE; } } for(unsigned int j=1;jnum)break; for(i=0;i<15;i++){ unsigned long lm=leanum[i]*v; if(lm==num){ leamul32(numleamul[i][0],reg,razr); lshiftmul(j,razr,reg); leamul32(numleamul[i][1],reg,razr); leamul32(numleamul[i][2],reg,razr); return TRUE; } } } if(reg==EAX)return speedmul(num,r32); return FALSE; } int speedmul(unsigned long num, int razr) //поиск возможности замены умножения на //сдвиги и сложения { int first,second; for(unsigned int j=1;jnum)break; if((num%(v-1))==0){ second=caselong(num/(v-1)); if(second!=NUMNUM){ first=caselong(v); if(first!=1){ startmul(razr); lshiftmul(first,razr); submul(razr); if(second!=0)lshiftmul(second,razr); setzeroflag=TRUE; return TRUE; } } } if((v+1)>num)break; if((num%(v+1))==0){ second=caselong(num/(v+1)); if(second!=NUMNUM){ first=caselong(v); startmul(razr); lshiftmul(first,razr); addmul(razr); if(second!=0)lshiftmul(second,razr); setzeroflag=TRUE; return TRUE; } } if(num>10){ if((v-1)>(num-1))break; if(((num-1)%(v-1))==0){ second=caselong((num-1)/(v-1)); if(second!=NUMNUM&&second!=1){ first=caselong(v); if(first!=1){ startmul(razr); lshiftmul(first,razr); submul(razr); lshiftmul(second,razr); addmul(razr); setzeroflag=TRUE; return TRUE; } } } if((v+1)>(num-1))break; if(((num-1)%(v+1))==0){ second=caselong((num-1)/(v+1)); if(second!=NUMNUM){ first=caselong(v); startmul(razr); lshiftmul(first,razr); addmul(razr); lshiftmul(second,razr); addmul(razr); setzeroflag=TRUE; return TRUE; } } if((v-1)>(num+1))break; if(((num+1)%(v-1))==0){ second=caselong((num+1)/(v-1)); if(second!=NUMNUM){ first=caselong(v); if(first!=1){ startmul(razr); lshiftmul(first,razr); submul(razr); lshiftmul(second,razr); submul(razr); setzeroflag=TRUE; return TRUE; } } } if((v+1)>(num+1))break; if(((num+1)%(v+1))==0){ second=caselong((num+1)/(v+1)); if(second!=NUMNUM&&second!=1){ first=caselong(v); startmul(razr); lshiftmul(first,razr); addmul(razr); lshiftmul(second,razr); submul(razr); setzeroflag=TRUE; return TRUE; } } } } return FALSE; } void CheckRegForLea(int reg,int *idx,int *base, int *zoom,unsigned long *val, unsigned int *rflag,ITOK *posttok) { // printf("in:reg=%02X base=%02X idx=%02X zoom=%02X\n",reg,*base,*idx,*zoom); for(;;){ // printf("tok=%d flag=%08X %s\n",tok2,itok2.flag,itok2.name); // printf("tok=%d tok2=%d %s\n",tok,tok2,itok2.name); if((tok==tk_plus||tok==tk_minus)&&(tok2==tk_minus|| (tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_double)|| (tok2==tk_postnumber&&posttok->post==0)||(tok==tk_plus&&tok2==tk_rmnumber&&(itok2.flag&f_useidx)==0))){ goto con1; } if((tok!=tk_plus&&(!(tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_double))) ||(tok2!=tk_reg32&&tok2!=tk_number)||tok2==tk_rmnumber){ break; } if(tok==tk_plus&&tok2==tk_reg32&&(itok2.number==reg||(*idx!=-1&&*base!=-1))){ break; } if(tok==tk_mult&&(tok2!=tk_number||*zoom!=-1||*val!=0||*idx!=-1))break; con1: if(tok==tk_minus){ if(tok2==tk_postnumber||(tok2==tk_number&&(itok2.flag&f_reloc)))break; nexttok(); if(tok==tk_minus){ if(tok2!=tk_number)break; nexttok(); *val+=itok.number; } else *val-=itok.number; if(tok==tk_number)*rflag^=itok.flag; else *posttok=itok; } else if(tok==tk_plus){ nexttok(); if(tok==tk_number){ *val+=itok.number; *rflag^=itok.flag; } else if(tok==tk_postnumber){ *val+=itok.number; *posttok=itok; } else if(tok==tk_rmnumber){ int r1,r2,z; ExpandRm(itok.rm,itok.sib,&z,&r1,&r2); if(z&&*zoom>0)break; if(r1>=0&&r2>=0&&(*idx>=0||*base>=0))break; *val+=itok.number; if(*zoom<=0)*zoom=z; if(*base==-1){ if(r1>=0){ *base=r1; r1=-1; } else{ *base=r2; r2=-1; } } if(*idx==-1){ if(r1>=0)*idx=r1; else if(r2>=0)*idx=r2; } } else{ if(*base==-1)*base=itok.number; else *idx=itok.number; } } else if(tok==tk_mult){ *zoom=0; switch(itok2.number){ case 8: *zoom=*zoom+1; case 4: *zoom=*zoom+1; case 2: *zoom=*zoom+1; case 1: *idx=*base; *base=-1; break; case 9: *zoom=*zoom+1; case 5: *zoom=*zoom+1; case 3: *zoom=*zoom+1; *idx=*base; break; default: *zoom=-1; } if(*zoom==-1)break; nexttok(); } else break; nexttok(); if(*base!=-1&&*idx!=-1&&tok2!=tk_number)break; } if(*zoom==-1&&*base==-1){ *base=*idx; *idx=-1; } // printf("out:reg=%02X base=%02X idx=%02X zoom=%02X\n",reg,*base,*idx,*zoom); } int OutLea(int reg,int idx,int base, int zoom,unsigned long val, unsigned int rflag,ITOK *posttok) { int mod=rm_mod00; int q; if(zoom==-1)zoom=0; if(val!=0){ if(short_ok(val,TRUE)!=0)mod=rm_mod01; else mod=rm_mod10; } if((rflag&f_reloc)!=0||posttok->post)mod=rm_mod10; if(idx==-1){ idx=base; base=-1; } if(base==-1){ if(zoom==0){ op66(r32); op67(r32); op(0x8d); if(idx==5&&mod==rm_mod00)mod=rm_mod01; op((reg*8+idx)|mod); if(idx==4)op(idx*9); } else{ if(idx==4)return FALSE; mod=rm_mod10; op66(r32); op67(r32); op(0x8d); op(reg*8+4); op(idx*8+5+(zoom<<6)); } } else{ if(idx==4){ if(base==-1){ idx=-1; base=4;} else if(zoom==0){ q=base; base=idx; idx=q; } else return FALSE; } if(base==5&&mod==rm_mod00){ if(idx!=-1&&idx!=5){ if(zoom==0){ q=base; base=idx; idx=q; } else mod=rm_mod01; } else mod=rm_mod01; } op66(r32); op67(r32); op(0x8d); op((reg*8+4)|mod); //sib op((zoom<<6)+(idx<<3)+base); } if(mod==rm_mod01)op(val); else if(mod==rm_mod10){ if(posttok->post)setwordpost(posttok); else if((rflag&f_reloc)!=0)AddReloc(); outdword(val); } else if(mod==rm_mod00&&base==5)outdword(val); return TRUE; } int Reg32ToLea2(int reg) //оптимизация сложения 32-битных регистров в LEA { int idx,base,zoom; unsigned long val; int otok,otok2,otype2; unsigned char ocha,next; unsigned int oinptr,rflag; int oline; ITOK oitok; ITOK posttok; if(tok!=tk_minus&&tok!=tk_plus&&tok!=tk_mult)return FALSE; if(tok==tk_minus&&(!((tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_double)||tok2==tk_postnumber)))return FALSE; if(tok==tk_mult&&(!(tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_double&&(itok2.flag&f_reloc)==0)))return FALSE; if(tok==tk_plus&&tok2!=tk_reg32&&tok2!=tk_number&&tok2!=tk_postnumber&&(!(tok2==tk_rmnumber&&(itok2.flag&f_useidx)==0)))return FALSE; if(cur_mod)return FALSE; posttok.post=0; idx=zoom=-1; base=reg; if(tok==tk_mult){ zoom=0; switch(itok2.number){ case 8: zoom++; case 4: zoom++; case 2: zoom++; case 1: idx=reg; base=-1; break; //new! case 9: zoom++; case 5: zoom++; case 3: // if(!(am32==FALSE&&tok!=tk_plus&&(!(tok2==tk_minus||tok2==tk_number)))){ if(am32){ zoom++; idx=base=reg; break; } // end new!! default: return FALSE; } if(zoom==0){ zoom=-1; base=reg; idx=-1; } } val=0; rflag=0; oinptr=inptr2; ocha=cha2; otok=tok; oitok=itok; otok2=tok2; otype2=itok2.type; oline=linenumber; if(tok==tk_mult){ nexttok(); nexttok(); } CheckRegForLea(reg,&idx,&base,&zoom,&val,&rflag,&posttok); next=0; if(idx==-1)next=1; if(base==-1)next|=2; if(zoom==-1)next|=4; if(val==0&&rflag==0&&posttok.post==0)next|=8; // printf("next=%d\n",next); switch(next){ case 1: // idx=-1 Rb+N if(base==ESP&&val==1)goto retfalse; case 4: // zoom=-1 Rb+Ri+N if(val<2||val>127)goto retfalse; break; case 2: // base=-1 Ri*Z+N if(zoom<3){ if(zoom==2&&val>2){ if(val<128)goto retfalse; break; } goto retfalse; } case 0: case 8: // val=0 Rb+Ri*Z break; default: // case 12: // val=0 zoom=-1 Rb+Ri // case 10: // val=0 base=-1 Ri*Z // case 13: // val=0 idx=-1 zoom=-1 Rb // case 5: // idx=-1 zoom=-1 Rb+N // case 3: // idx=-1 base=-1 N // case 6: // base=-1 zoom=-1 Ri+N // case 11: // val=0 base=-1 idx=-1 - // case 9: // val=0 idx=-1 Rb // case 14: // val=0 base=-1 zoom=-1 Ri // case 7: // idx=-1 base=-1 zoom=-1 N // case 15: // val=0 base=-1 idx=-1 zoom=-1 retfalse: inptr2=oinptr; cha2=ocha; tok=otok; itok=oitok; tok2=otok2; itok2.type=(unsigned short)otype2; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } endoffile=0; linenum2=linenumber=oline; return FALSE; } if(OutLea(reg,idx,base,zoom,val,rflag,&posttok)==FALSE)goto retfalse; ClearReg(reg); // printf("%s (%u) Combination %d\n",(startfileinfo+currentfileinfo)->filename,linenumber,next); return TRUE; } int RegEqualToLea(int reg) { int idx,base,zoom; unsigned long val; int otok,otok2; unsigned char ocha,next; unsigned int oinptr,rflag; ITOK oitok; ITOK oitok2; ITOK posttok; if(cur_mod)return FALSE; oinptr=inptr2; ocha=cha2; otok=tok; oitok=itok; otok2=tok2; oitok2=oitok; base=idx=zoom=-1; val=0; rflag=0; posttok.post=0; tok=tk_plus; CheckRegForLea(reg,&idx,&base,&zoom,&val,&rflag,&posttok); if(tok!=tk_semicolon)goto retfalse; if(base==-1)base=reg; else if(idx==-1)idx=reg; else goto retfalse; next=0; if(idx==-1)next=1; if(base==-1)next|=2; if(zoom==-1)next|=4; if(val==0&&rflag==0&&posttok.post==0)next|=8; // printf("base=%d idx=%d zoom=%d val=%d next=%d\n",base,idx,zoom,val,next); if(val==0&&rflag==0&&posttok.post==0)next|=8; switch(next){ case 5: // idx=-1 zoom=-1 Rb+N if(reg==EAX&&(val>127||val<0xffffff80))goto retfalse; if(val<3||val>0xfffffffd)goto retfalse; if(base==ESP)goto retfalse; break; case 4: // zoom=-1 Rb+Ri+N if(val==1||val==0xffffffff)goto retfalse; break; case 0: case 8: // val=0 Rb+Ri*Z break; default: // case 13: // val=0 idx=-1 zoom=-1 Rb // case 3: // idx=-1 base=-1 N // case 6: // base=-1 zoom=-1 Ri+N // case 11: // val=0 base=-1 idx=-1 - // case 9: // val=0 idx=-1 Rb // case 14: // val=0 base=-1 zoom=-1 Ri // case 7: // idx=-1 base=-1 zoom=-1 N // case 15: // val=0 base=-1 idx=-1 zoom=-1 retfalse: inptr2=oinptr; cha2=ocha; tok=otok; itok=oitok; tok2=otok2; itok2=oitok2; endoffile=0; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } // printf("return input=%08X inptr=%08X\n",input,inptr2); return FALSE; } // printf("next=%d\n",next); if(OutLea(reg,idx,base,zoom,val,rflag,&posttok)==FALSE)goto retfalse; return TRUE; } int Reg32ToLea(int reg) //оптимизация сложения 32-битных регистров в LEA { int idx,base,zoom; unsigned long val; int otok,otok2,otype2; unsigned char ocha,next; unsigned int oinptr,rflag; int oline; ITOK oitok; ITOK posttok; if(tok!=tk_reg32&&tok!=tk_number&&tok!=tk_postnumber&&(!(tok==tk_rmnumber&&(itok.flag&f_useidx)==0)))return FALSE; if(cur_mod)return FALSE; posttok.post=0; idx=base=zoom=-1; val=0; rflag=0; // printf("input=%08X inptr=%08X\n",input,inptr2); oinptr=inptr2; ocha=cha2; otok=tok; oitok=itok; otok2=tok2; otype2=itok2.type; oline=linenumber; // printf("tok=%d type=%d %s\n",tok,itok.type,itok.name); if(tok==tk_number){ if(itok.rm==tk_float||itok.rm==tk_double||itok.rm==tk_qword)return FALSE; val=doconstdwordmath(); rflag=postnumflag; if((rflag&f_reloc)&&tok==tk_mult)goto retfalse; } else if(tok==tk_postnumber){ posttok=itok; tok=tk_number; val=doconstdwordmath(); if(tok==tk_mult)goto retfalse; } else if(tok==tk_rmnumber){ ExpandRm(itok.rm,itok.sib,&zoom,&base,&idx); val=itok.number; nexttok(); } else{ base=itok.number; nexttok(); } if(tok==tk_mult){ nexttok(); if(base==-1&&tok==tk_reg32){ if(itok.number==reg)goto retfalse; idx=itok.number; } else if(base!=-1&&tok==tk_number){ if((itok.flag&f_reloc)&&(itok.rm==tk_float||itok.rm==tk_double||itok.rm==tk_qword))goto retfalse; idx=base; base=-1; val=itok.number; } else goto retfalse; nexttok(); zoom=0; switch(val){ case 8: zoom++; case 4: zoom++; case 2: zoom++; case 1: break; //new! case 9: zoom++; case 5: zoom++; case 3: // if(!(am32==FALSE&&tok!=tk_plus&&(!(tok2==tk_minus||tok2==tk_number)))){ if(am32||((tok==tk_plus||tok==tk_minus)&&(tok2==tk_number||tok2==tk_minus))){ zoom++; base=idx; break; } // end new!! default: goto retfalse; } if(zoom==0){ zoom=-1; base=idx; idx=-1; } val=0; } CheckRegForLea(reg,&idx,&base,&zoom,&val,&rflag,&posttok); next=0; if(idx==-1)next=1; if(base==-1)next|=2; if(zoom==-1)next|=4; if(val==0&&rflag==0&&posttok.post==0)next|=8; switch(next){ case 5: // idx=-1 zoom=-1 Rb+N case 1: // idx=-1 Rb+N if(base==ESP&&val==1)goto retfalse; case 12: // val=0 zoom=-1 Rb+Ri if(base==reg)goto retfalse; break; case 10: // val=0 base=-1 Ri*Z if(optimizespeed==FALSE||idx==reg)goto retfalse; break; case 2: // base=-1 Ri*Z+N if(optimizespeed)break; if(zoom<3){ if(zoom==2&&val>2){ if(val<128){ if(idx!=reg)break; goto retfalse; } break; } if(zoom==1&&val>3&&idx!=reg)break; goto retfalse; } case 0: case 4: // zoom=-1 Rb+Ri+N case 8: // val=0 Rb+Ri*Z break; default: // case 13: // val=0 idx=-1 zoom=-1 Rb // case 3: // idx=-1 base=-1 N // case 6: // base=-1 zoom=-1 Ri+N // case 11: // val=0 base=-1 idx=-1 - // case 9: // val=0 idx=-1 Rb // case 14: // val=0 base=-1 zoom=-1 Ri // case 7: // idx=-1 base=-1 zoom=-1 N // case 15: // val=0 base=-1 idx=-1 zoom=-1 retfalse: inptr2=oinptr; cha2=ocha; tok=otok; itok=oitok; tok2=otok2; itok2.type=(unsigned short)otype2; linenum2=linenumber=oline; endoffile=0; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } // printf("return input=%08X inptr=%08X\n",input,inptr2); return FALSE; } // printf("flag=%08X\n",rflag); if(OutLea(reg,idx,base,zoom,val,rflag,&posttok)==FALSE)goto retfalse; ClearReg(reg); return TRUE; } void CheckRegForLea16(int reg,int *idx,int *base,unsigned long *val,unsigned int *rflag,ITOK *posttok) { int endloop=FALSE; for(;;){ if(tok!=tk_plus&&(!(tok==tk_minus&&((tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_qword&&itok2.rm!=tk_double)||tok2==tk_postnumber))))break; if(tok2==tk_postnumber&&(posttok->post||tok==tk_minus))break; if(tok2==tk_reg){ if(itok2.number==reg)endloop=TRUE; else if(*base==-1){ switch(itok2.number){ case BX: case BP: case SI: case DI: *base=itok2.number; break; default: endloop=TRUE; break; } } else if(*idx==-1){ switch(itok2.number){ case BX: case BP: if(*base==BX||*base==BP)endloop=TRUE; else{ *idx=*base; *base=itok2.number; } break; case SI: case DI: if(*base==SI||*base==DI)endloop=TRUE; else{ *idx=itok2.number; } break; default: endloop=TRUE; break; } } else break; if(endloop)break; nexttok(); } else if(tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_qword&&itok2.rm!=tk_double){ if(tok==tk_plus)*val+=itok2.number; else *val-=itok2.number; nexttok(); *rflag^=itok.flag; } else if(tok2==tk_postnumber){ if(posttok->post)break; if(tok==tk_plus)*val+=itok2.number; else *val-=itok2.number; nexttok(); *posttok=itok; } else break; nexttok(); } } void OutLea16(int reg,int idx,int base,unsigned int val,int rflag,ITOK *posttok) { int mod=rm_mod00; int rm; if(val!=0){ if(short_ok(val,FALSE)!=0)mod=rm_mod01; else mod=rm_mod10; } if((rflag&f_reloc)!=0||posttok->post)mod=rm_mod10; rm=CalcRm16(base,idx); op66(r16); op67(r16); op(0x8D); op((rm+reg*8)|mod); if(mod==rm_mod01)op(val); else if(mod==rm_mod10){ if(posttok->post)setwordpost(posttok); else if((rflag&f_reloc)!=0)AddReloc(); outword(val); } } int Reg16ToLea(int reg) //оптимизация сложения 16-битных регистров в LEA { int idx,base; unsigned long val; int otok,otok2,otype2; unsigned char ocha,next; unsigned int oinptr,rflag; int oline; ITOK oitok; ITOK posttok; if(cur_mod)return FALSE; posttok.post=0; // if(tok!=tk_reg&&tok!=tk_number&&am32!=0&&tok2!=tk_plus)return FALSE; if(!((tok==tk_reg||(tok==tk_number&&itok.rm!=tk_float&&itok.rm!=tk_double)&&tok==tk_postnumber)&&tok2==tk_plus))return FALSE; idx=base=-1; if(tok==tk_reg){ if(itok.number==reg)return FALSE; switch(itok.number){ case BX: case BP: case SI: case DI: base=itok.number; break; default: return FALSE; } } val=0; rflag=0; oinptr=inptr2; ocha=cha2; otok=tok; oitok=itok; otok2=tok2; otype2=itok2.type; oline=linenumber; if(tok==tk_postnumber){ posttok=itok; tok=tk_number; } if(tok==tk_number){ val=doconstdwordmath(); rflag=postnumflag; } else nexttok(); CheckRegForLea16(reg,&idx,&base,&val,&rflag,&posttok); next=0; if(idx==-1)next=1; if(base==-1)next|=2; if(val==0&&rflag==0&&posttok.post==0)next|=4; switch(next){ case 0: //base+idx+num case 1: //base+num // case 2: //idx+num // case 3: //num case 4: //base+idx // case 6: //idx // case 7: // break; case 5: //base if(am32==0)break; default: retfalse: inptr2=oinptr; cha2=ocha; tok=otok; itok=oitok; tok2=otok2; itok2.type=(unsigned short)otype2; linenum2=linenumber=oline; endoffile=0; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } return FALSE; } OutLea16(reg,idx,base,val,rflag,&posttok); return TRUE; } int Reg16ToLea2(int reg) //оптимизация сложения 16-битных регистров в LEA { int idx,base; unsigned long val; int otok,otok2,otype2; unsigned char ocha,next; unsigned int oinptr,rflag; int oline; ITOK oitok; ITOK posttok; if(cur_mod)return FALSE; posttok.post=0; if(tok==tk_plus&&((tok2==tk_reg&&itok2.number!=reg)||(tok2==tk_number&&itok2.rm!=tk_float&&itok2.rm!=tk_double))&& (reg==BX||reg==BP||reg==SI||reg==DI)){ val=0; rflag=0; oinptr=inptr2; ocha=cha2; otok=tok; oitok=itok; otok2=tok2; otype2=itok2.type; oline=linenumber; idx=-1; base=reg; CheckRegForLea16(reg,&idx,&base,&val,&rflag,&posttok); next=0; if(idx==-1)next=1; if(base==-1)next|=2; if(val==0&&rflag==0&&posttok.post==0)next|=4; switch(next){ case 1: //base+num if(val<3&&rflag==0&&posttok.post==0)goto retfalse; case 0: //base+idx+num // case 2: //idx+num // case 3: //num case 4: //base+idx // case 6: //idx // case 7: // break; // case 5: //base default: retfalse: inptr2=oinptr; cha2=ocha; tok=otok; itok=oitok; tok2=otok2; itok2.type=(unsigned short)otype2; endoffile=0; linenum2=linenumber=oline; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } return FALSE; } OutLea16(reg,idx,base,val,rflag,&posttok); return TRUE; } return FALSE; } int OptimNum() //оптимизация цифровых операндов { int otok,oinptr,deistv,negflag,starttok; char ocha2; long long val; unsigned int flag,oflag; int plusreloc=0; if(optnumber==FALSE||cur_mod)return FALSE; //оптимизация отключена if(tok==tk_minus&&(itok2.flag&f_reloc))return FALSE; deistv=0; negflag=0; starttok=otok=tok; oflag=itok.flag; oinptr=inptr2; ocha2=cha2; nexttok(); flag=itok.flag; val=itok.lnumber; switch(otok){ case tk_minus: val=-val; case tk_plus: for(;;){ //оптимизация сложений-вычитаний nexttok(); if((tok!=tk_plus&&tok!=tk_minus)||tok2!=tk_number|| (tok==tk_minus&&(itok2.flag&f_reloc)&&plusreloc==0)){//не цыфра или другое действие tok=otok; cha2=ocha2; inptr2=oinptr; endoffile=0; if(deistv==0)break; //ничего не было оптимизировано warningoptnum(); tok=tk_plus; itok.lnumber=val; itok.flag|=flag; return TRUE; } deistv=tok; nexttok(); oinptr=inptr2; ocha2=cha2; if(deistv==tk_minus){ val-=itok.lnumber; if(itok.flag&f_reloc)plusreloc--; } else{ val+=itok.lnumber; if(itok.flag&f_reloc)plusreloc++; } flag^=itok.flag; } break; case tk_divminus: otok=tk_div; goto LL1; case tk_multminus: otok=tk_mult; LL1: negflag=TRUE; case tk_div: case tk_mult: for(;;){ nexttok(); if((tok!=tk_div&&tok!=tk_mult&&tok!=tk_divminus&&tok!=tk_multminus)|| tok2!=tk_number|| (otok!=tok&&((val>itok2.lnumber&&(val%itok2.lnumber)!=0) ||(valitok.lnumber)val=val/itok.lnumber; else if(val2&&(*expand==FALSE)&&optimizespeed&&leamul32(num,reg,razr)){ setzeroflag=FALSE; return; } switch(num){ case 0: ZeroReg(reg,razr); setzeroflag=TRUE; case 1: *expand=FALSE; break; /* AX * 1 = AX */ case 2: /* AX * 2 = ADD AX,AX */ if(*expand==TRUE){ if(optimizespeed==FALSE)goto num_imul; if(sign)cwdq(razr); else{ op66(razr); outword(0xD231); } } op66(razr); op(1); op(0xC0+9*reg); // ADD reg,reg if(*expand==TRUE){ op66(razr); outword(0xd283); //adc dx,0 op(0); ClearReg(DX); } setzeroflag=TRUE; break; default: vop=caselong(num); if(vop!=NUMNUM){ if(chip<1&&razr==r16){ if(*expand==TRUE){ if(optimizespeed==FALSE)goto num_imul; op(0xB1); op(vop); /* MOV CL,num */ op66(r16); if(sign)op(0x99); else outword(0xD231); outdword(0xd213c001); //ADD AX,AX ADC DX,DX outword(0xfae2); //LOOP -6 warningreg(regs[0][2]); ClearReg(DX); } else{ if(reg==CX)goto num_imul; if(vop>3){ for(;vop!=0;vop--){ op66(r16); op(3); //add op(0xc0+reg*9); } return; } op(0xB1); op(vop); /* MOV CL,num */ op(0xD3); op(0xE0+reg); //SHL reg,CL } ConstToReg(vop,CL,r8); warningreg(begs[1]); } else{/* SHL AX,num */ if(*expand==TRUE){ if(optimizespeed==FALSE)goto num_imul; // op66(razr); ClearDX(razr,sign); /* if(sign)cwdq(razr); else{ op66(razr); outword(0xC031); }*/ if(chip<3&&razr==r16){ op(0xB1); op(vop); /* MOV CL,num */ outdword(0xd213c001); //ADD AX,AX ADC DX,DX outword(0xfae2); //LOOP -6 ConstToReg(vop,CL,r8); warningreg(begs[1]); } else{ op66(razr); op(0x0f); outword(0xC2a4); //SHLD DX,AX,num op(vop); op66(razr); outword(0xE0C1); //SHL AX,num op(vop); } ClearReg(DX); warningreg(regs[razr/2-1][2]); } else{ op66(razr); op(0xc1); op(0xe0+reg); // SHL reg,imm8 op(vop); if(cpu<2)cpu=2; } } setzeroflag=TRUE; break; } if(chip<7&&*expand==FALSE&&optimizespeed&&speedmul32(num,reg,razr))break; num_imul: if((razr==r16&&chip<2)||(*expand==TRUE)){ if(reg==AX){ op66(razr); op(0xB9); /* MOV CX,# */ if((flag&f_reloc)!=0)AddReloc(); razr==r16?outword((unsigned int)num):outdword(num); op66(razr); if(sign)outword(0xE9F7); /* IMUL CX */ else outword(0xE1F7); /* MUL CX */ ConstToReg(num,CX,razr); warningreg(regs[razr/2-1][1]); } else{ op66(r16); op(0x90+reg); //XCHG AX,reg op66(r16); op(reg!=DX?0xBA:0xB9); outword(num); //mov DX,num op66(r16); op(0xF7); op(reg!=DX?0xE2:0xE1); // mul DX op66(r16); op(0x90+reg); //XCHG AX,reg warningreg(regs[0][reg!=DX?2:1]); ClearReg(DX); } } else{ if((flag&f_reloc)==0&&short_ok(num,razr/2-1))i=2; //короткая форма op66(razr); op(0x69+i); //imul op(0xc0+reg*9); if(i==2)op(num); else{ if((flag&f_reloc)!=0)AddReloc(); razr==r16?outword((unsigned int)num):outdword(num); } } setzeroflag=FALSE; break; } } /* --------------- byte, char, word, int math starts ----------------- */ long long CalcNumber(int sign) { long long hold; switch(sign){ case 0: hold=doconstdwordmath(); break; case 1: hold=doconstlongmath(); break; case 2: hold=doconstfloatmath(); break; case 3: hold=doconstdoublemath(); break; default: hold=doconstqwordmath(); break; } return hold; } int OnlyNumber(int sign) /*-----------------11.09.00 12:44------------------- проверить что строка состоит только из цифр. --------------------------------------------------*/ { ITOK oitok=itok; unsigned char ocha=cha2; unsigned int oinptr=inptr2; unsigned int otok2=tok2; int otype2=itok2.type; itok.lnumber=CalcNumber(sign); // printf("tok=%d num=%d type=%d\n",tok,itok.number,itok.type); if(itok.type==tp_stopper){ return TRUE; //только цифры } cha2=ocha; //востановить исходное состояние inptr2=oinptr; tok2=otok2; tok=tk_number; itok=oitok; itok2.type=(unsigned short)otype2; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr){ free(strinf.bufstr); strinf.bufstr=NULL; } return FALSE; } void MultiAssignFloat(int type,int npointr=0) { int otok; ITOK wtok; char *wbuf; SINFO wstr; char *ofsstr=NULL; if(tok!=type)illegalfloat(); wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; otok=tok; nexttok(); // getoperand(); int numpointr=0; nexttok(); if(tok==tk_float||tok==tk_double)nexttok(); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign)MultiAssignFloat(type,numpointr); else{ if(tok==tk_pointer)cpointr(BX,numpointr); if(tok==tk_floatvar&&tok2==tk_semicolon){ tok=tk_dwordvar; do_e_axmath(1,r32,&ofsstr); } else doeaxfloatmath(tk_reg32,AX); } if(otok==tk_pointer){ if(wtok.type==tk_proc){ wtok.rm=wtok.sib; if(am32)wtok.sib=CODE32; else wtok.sib=CODE16; compressoffset(&wtok); } else{ int razr=typesize(itok.type); if(npointr<=wtok.npointr)getpointeradr(&wtok,wbuf,&wstr,npointr-1,razr,BX); else unuseableinput(); wtok=itok; } } if((wtok.rm==rm_d16&&wtok.sib==CODE16)||(wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0))){ op66(r32); outseg(&wtok,1); op(0xA3); /* MOV [word],AX */ if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); //???? else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,r32,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0x89); op(wtok.rm); /* MOV [rmword],reg */ outaddress(&wtok); } } int MultiAssign(int razr,int usereg,int npointr) { int otok; ITOK wtok; char *wbuf; SINFO wstr; int sign=0,rettype,nrazr,posiblret,pointr=0; int hnumber=0; int ureg; char *ofsstr=NULL; wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; otok=tok; if(tok==tk_bits){ usereg=EAX;//USEONLY_AX; nrazr=r32; rettype=tk_dword; int i=itok.bit.siz+itok.bit.ofs; if(i<9){ nrazr=r8; rettype=tk_byte; } else if(i<17){ rettype=tk_word; nrazr=r16; } else if(i>32)nrazr=r64; } else{ nrazr=GetVarSize(tok); switch(tok){ case tk_beg: ureg=itok.number; if(ureg>3)ureg-=4; if(usereg>ureg)usereg=ureg; break; case tk_reg: case tk_reg32: if(usereg>itok.number)usereg=itok.number; break; } // if(tok==tk_beg)usereg|=USEFIRST4REG; } posiblret=nrazr; if(nrazr>razr&&nrazritok.npointr){ unuseableinput(); } ureg=AX; if(tok2==tk_assign){ ureg=hnumber=MultiAssign(razr,usereg,numpointr); if(ofsstr){ free(ofsstr); ofsstr=NULL; } } else{ if(tok==tk_pointer){ int reg=idxregs[2]; if(reg==ureg)reg=idxregs[1]; cpointr(reg,numpointr); } if(usereg==USEALLREG){ switch(tok){ case tk_reg: case tk_reg32: usereg=itok.number; break; case tk_beg: usereg=(itok.number>3?itok.number-4:itok.number); break; default: usereg=EAX; break; } } switch(rettype){ case tk_char: case tk_byte: if(tok2==tk_semicolon&&usereg!=0&&usereg<4){ ureg=hnumber=usereg; // if(tok==tk_beg&&itok.number<4)ureg=hnumber=itok.number; getintoreg(usereg,r16,sign,&ofsstr); } /* if(tok2==tk_semicolon&&tok==tk_beg&&usereg<2){ if((usereg==1&&itok.number<4)||usereg==0){ ureg=hnumber=itok.number; nexttok(); break; } }*/ else doalmath(sign,&ofsstr); if(ofsstr)IDZToReg(ofsstr,usereg,r8); break; case tk_int: case tk_word: if(tok2==tk_semicolon&&usereg!=0){ ureg=hnumber=usereg; // if(tok==tk_reg)ureg=hnumber=itok.number; getintoreg(usereg,r16,sign,&ofsstr); } else do_e_axmath(sign,r16,&ofsstr); if(ofsstr)IDZToReg(ofsstr,usereg,r16); break; case tk_float: doeaxfloatmath(tk_reg32,AX); break; default: if(tok2==tk_semicolon&&usereg!=0&&tok!=tk_floatvar){ ureg=hnumber=usereg; // if(tok==tk_reg32)ureg=hnumber=itok.number; getintoreg(usereg,r32,sign,&ofsstr); } else{ if(tok==tk_floatvar&&tok2==tk_semicolon)tok=tk_dwordvar; do_e_axmath(sign,r32,&ofsstr); } if(ofsstr)IDZToReg(ofsstr,usereg,r32); break; } } if(ofsstr){ free(ofsstr); ofsstr=NULL; } switch ( nrazr ) { case r8: posiblret=tk_byte; break; case r16: posiblret=tk_word; break; case r32: posiblret=tk_dword; break; } convert_returnvalue(posiblret,rettype); if(otok==tk_pointer)cwpointr(&wtok,wbuf,&wstr,&otok,npointr,ureg); switch ( otok ) { case tk_intvar: case tk_wordvar: case tk_longvar: case tk_dwordvar: case tk_floatvar: #ifdef OPTVARCONST CheckRegToConst(hnumber,&wtok,otok>tk_wordvar?r32:r16); #endif KillVar(wtok.name); AddRegVar(hnumber,razr,&wtok); if(hnumber==0&&((wtok.rm==rm_d16&&wtok.sib==CODE16)||(wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(nrazr); outseg(&wtok,1); op(0xA3); /* MOV [word],AX */ if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); //???? else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,nrazr,&wstr,&wtok); op66(nrazr); outseg(&wtok,2); op(0x89); op(wtok.rm+hnumber*8); /* MOV [rmword],reg */ outaddress(&wtok); } break; case tk_charvar: case tk_bytevar: #ifdef OPTVARCONST CheckRegToConst(hnumber,&wtok,r8); #endif KillVar(wtok.name); AddRegVar(hnumber,r8,&wtok); if(hnumber==0&&((wtok.rm==rm_d16&&wtok.sib==CODE16)||(wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ outseg(&wtok,1); op(0xA2); /* MOV [byte],AL */ if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,1,&wstr,&wtok); outseg(&wtok,2); /* MOV [rmbyte],AL */ op(0x88); op(wtok.rm+hnumber*8); outaddress(&wtok); } break; case tk_bits: if(razr!=r64){ op66(nrazr==r32?r32:r16); op(0x50); //push eax if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=4; reg2bits(&wtok,razr); op66(nrazr==r32?r32:r16); op(0x58); //pop eax } else{ op66(r32); op(0x50); //push eax int siz=wtok.bit.siz; op66(r32); op(0x50); //push eax wtok.bit.siz=32-wtok.bit.ofs; if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=8; reg2bits(&wtok,r32); op66(r32); op(0x58); //pop eax op66(r32); //shr eax,size outword(0xE8C1); op(wtok.bit.siz); wtok.bit.siz=siz+wtok.bit.ofs-32; wtok.bit.ofs=0; wtok.number+=4; reg2bits(&wtok,r8); op66(r32); op(0x58); //pop eax } break; case tk_reg: case tk_reg32: if(wtok.number!=hnumber){ if(RegToReg(hnumber,wtok.number,nrazr)==NOINREG){ op66(nrazr); op(0x89); op(0xC0+wtok.number+hnumber*8); //mov reg,AX } else waralreadinitreg(regs[nrazr/4][wtok.number],regs[nrazr/4][hnumber]); } break; case tk_beg: if(razr>r8&&wtok.number>3&&(wtok.number%4)==hnumber)preerror("register AH,BH,CH,DH should be first"); if(wtok.number!=hnumber){ if(RegToReg(hnumber,wtok.number,r8)==NOINREG){ op(0x88); op(0xC0+wtok.number+hnumber*8); //mov beg,AL } else waralreadinitreg(begs[wtok.number],begs[hnumber]); } break; case tk_seg: op(0x8E); /* MOV SEG,AX */ op(0xC0+wtok.number*8+hnumber); break; default: thisundefined(wtok.name); } return hnumber; } int do_d_wordvar(int sign,int razr,int terminater) //signed or unsigned 16 or 32 bit memory variable { unsigned char next=1,getfromAX=0; unsigned int vop=0,otok,rettype,posiblret; ITOK wtok; char *wbuf,*rbuf; SINFO wstr; int retrez=0,pointr=0,hnumber=EAX; int numpointr=0; char *ofsstr=NULL; int reg1=idxregs[0],reg2=idxregs[1]; #ifdef OPTVARCONST int initconst=FALSE; int operand; #endif unsigned int oaddESP=addESP; // sign==0?rettype=(razr==r16?tk_word:tk_dword):rettype=(razr==r16?tk_int:tk_long); posiblret=rettype=(sign==0?(razr==r16?tk_word:tk_dword):(razr==r16?tk_int:tk_long)); wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; otok=tok; while(RmEqualReg(hnumber,itok.rm,itok.sib))hnumber++; nexttok(); #ifdef OPTVARCONST operand=tok; #endif switch(tok){ case tk_assign: //= if(!((tok2==tk_reg||tok2==tk_reg32)&&ScanTok3()==terminater)){ ofsstr=GetLecsem(terminater); } if(ofsstr){ int retreg; if((retreg=CheckIDZReg(ofsstr,AX,razr))!=NOINREG){ GetEndLex(terminater); if(retreg==SKIPREG)retreg=AX; if((GetRegVar(&wtok)&(1<itok.npointr){ unuseableinput(); } if(tok2==tk_assign){ hnumber=MultiAssign(razr,USEALLREG,numpointr); if(ofsstr){ free(ofsstr); ofsstr=NULL; } next=0; goto getfromax; } if(tok==tk_pointer)cpointr(am32==TRUE?EAX:BX,numpointr); CheckMinusNum(); // printf("tok=%d tok2=%d\n",tok,tok2); if(itok2.type==tp_opperand){ //сложное выражение if(tok==tk_number){ //проверка и суммирование чисел if(OnlyNumber(rettype==tk_float?2:sign)){ next=0; itok.flag=(unsigned char)postnumflag; if(postnumflag==0)goto loadconst; goto numbertovar; } } goto labl1; } else{ // if(hnumber!=EAX&&(tok==tk_reg||tok==tk_reg32)&&itok.number==EAX)goto labl1; #ifdef OPTVARCONST CheckConstVar3(&tok,&itok,razr); #endif switch(tok){ case tk_number: loadconst: if((itok.flag&f_reloc)==0){ #ifdef OPTVARCONST if(razr==r16)itok.lnumber&=0xffff; else itok.lnumber&=0xffffffff; if((initconst=Const2Var(&wtok,itok.lnumber,itok.rm))==FALSE){ waralreadinitvar(wtok.name,itok.number); initconst=TRUE; break; } #endif if(itok.number==0){ CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); break; } if((razr==r32&&itok.number==0xFFFFFFFF)||(razr==r16&&itok.number==0xFFFF)){ CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x83); op(wtok.rm+0x8); outaddress(&wtok); op(0xFF); break; } if(regoverstack&&razr==r32&&short_ok(itok.number,TRUE)){ CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); op(0x6A); op(itok.number); //push short number op66(razr); outseg(&wtok,2); op(0x8f); op(wtok.rm); outaddress(&wtok); break; } } case tk_postnumber: case tk_undefofs: numbertovar: CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xC7); //mov word[],number op(wtok.rm); outaddress(&wtok); if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); else if((itok.flag&f_reloc)!=0)AddReloc(); if(razr==r16){ if(am32!=FALSE&&tok!=tk_number)dwordvalexpected(); outword((unsigned int)itok.number); } else outdword(itok.number); break; case tk_apioffset: CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xC7); //mov word[],number op(wtok.rm); outaddress(&wtok); AddApiToPost(itok.number); break; case tk_reg32: // if(razr==r16)goto labl1; case tk_reg: if(razr==r32&&tok==tk_reg)goto labl1; regtovar: if((unsigned int)itok.number==0){ getfromAX=1; hnumber=0; } else{ // if(wbuf==0&&wstr.bufstr==NULL){ KillVar(wtok.name); AddRegVar(itok.number,razr,&wtok); vop++; // } CheckAllMassiv(wbuf,razr,&wstr,&wtok,reg1,reg2); op66(razr); outseg(&wtok,2); op(0x89); op((unsigned int)itok.number*8+wtok.rm); outaddress(&wtok); } break; case tk_seg: if(razr==r32)goto labl1; CheckAllMassiv(wbuf,2,&wstr,&wtok); op66(r16); outseg(&wtok,2); op(0x8C); op((unsigned int)itok.number*8+wtok.rm); outaddress(&wtok); if((unsigned int)itok.number==FS||(unsigned int)itok.number==GS)if(cpu<3)cpu=3; break; case tk_string: CheckAllMassiv(wbuf,1,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xC7); op(wtok.rm); outaddress(&wtok); if(razr==r16){ if(am32)dwordvalexpected(); outword(addpoststring()); } else outdword(addpoststring()); break; case tk_doublevar: vop=4; case tk_floatvar: intinstack(vop); getfromAX=0; CheckAllMassiv(wbuf,4,&wstr,&wtok); outseg(&wtok,2); //fistp var op(razr==r16?0xDF:0xDB); op(wtok.rm+0x18); outaddress(&wtok); if(sign==0)warningretsign(); fwait3(); hnumber=EAX; break; case tk_new: donew(); getfromAX=1; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif if(ofsstr){ free(ofsstr); ofsstr=NULL; } hnumber=0; break; case tk_delete: dodelete(); terminater=next=0; getfromAX=1; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif if(ofsstr)free(ofsstr); hnumber=0; break; case tk_longvar: case tk_dwordvar: if((rettype==tk_long||rettype==tk_dword)&&hnumber&®overstack)goto pushvar; goto labl1; case tk_intvar: case tk_wordvar: if((rettype==tk_int||rettype==tk_word)&&hnumber&®overstack){ pushvar: CheckAllMassiv(bufrm,razr,&strinf); op66(razr); outseg(&itok,2); op(0xFF); // PUSH [dword] op(0x30+itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x8f); op(wtok.rm); outaddress(&wtok); break; } goto labl1; default: labl1: getfromAX=1; if(rettype==tk_char||rettype==tk_byte){ if(hnumber==0)retrez=doalmath(sign,&ofsstr); else{ retrez=getintoreg(hnumber,razr,sign,&ofsstr); posiblret=rettype; } } else if(rettype==tk_int||rettype==tk_word){ if(hnumber==0)retrez=do_e_axmath(sign,r16,&ofsstr); else retrez=getintoreg(hnumber,r16,sign,&ofsstr); } else if(rettype==tk_float||rettype==tk_double){ doeaxfloatmath(tk_fpust,AX,rettype==tk_float?0:4); getfromAX=0; CheckAllMassiv(wbuf,4,&wstr,&wtok); outseg(&wtok,2); //fistp var op(razr==r16?0xDF:0xDB); op(wtok.rm+0x18); outaddress(&wtok); if(sign==0)warningretsign(); fwait3(); hnumber=EAX; } else{ if(hnumber==0)retrez=do_e_axmath(sign,r32,&ofsstr); else retrez=getintoreg(hnumber,r32,sign,&ofsstr); } next=0; break; } } if(getfromAX){ getfromax: #ifdef OPTVARCONST initconst=CheckRegToConst(hnumber,&wtok,razr); #endif if(retrez==0)retrez=razr==r16?tk_reg:tk_reg32; convert_returnvalue(posiblret,rettype); if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar))wtok.number+=addESP-oaddESP; if(wbuf==NULL&&wstr.bufstr==NULL&&hnumber==0&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(razr); outseg(&wtok,1); op(0xA3); // MOV [word],AX if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); //???? else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,razr,&wstr,&wtok,reg1,reg2); // printf("flag=%08X rm=%d num=%d post=%d sib=%d\n",wtok.flag,wtok.rm,wtok.number,wtok.post,wtok.sib); op66(razr); outseg(&wtok,2); op(0x89); op(wtok.rm+hnumber*8); // MOV [rmword],AX outaddress(&wtok); } if(ofsstr)IDZToReg(ofsstr,hnumber,razr); else ClearReg(hnumber); KillVar(wtok.name); AddRegVar(hnumber,razr,&wtok); } else{ // printf("vop=%d %s\n",vop,wtok.name); if(vop==0)KillVar(wtok.name); } if(ofsstr)free(ofsstr); break; case tk_minusminus: vop=0x8; case tk_plusplus: #ifdef OPTVARCONST initconst=UpdVarConst(&wtok,1,tk_byte,tok); #endif CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xFF); op(vop+wtok.rm); outaddress(&wtok); KillVar(wtok.name); break; case tk_cdecl: case tk_pascal: case tk_fastcall: case tk_stdcall: vop=tok; nexttok(); if(tok!=tk_openbracket){ expected('('); FindStopTok(); } case tk_openbracket: //вызов процедуры по адресу в регистре param[0]=0; int i; i=0; switch ( vop ) { case tk_cdecl: case tk_stdcall: i=swapparam(); break; case tk_pascal: doparams(); break; case tk_fastcall: doregparams(); break; default: if(comfile==file_w32)swapparam(); else doparams(); } if(vop!=tk_cdecl)i=0; CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); op(0xFF); op(0x10+wtok.rm); outaddress(&wtok); clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif if(i)CorrectStack(i); break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: getoperand(am32==TRUE?EAX:BX); if(tok==tk_float){ getoperand(am32==TRUE?EAX:BX); doeaxfloatmath(tk_reg32,AX); goto axtovar; } if(itok2.type==tp_opperand){ if(tok==tk_number){ if(OnlyNumber(sign)){ next=0; otok=tok; tok=tk_number; goto num; } } retrez=razr==r16?tk_reg:tk_reg32; do_e_axmath(sign,razr,&ofsstr); if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar))wtok.number+=addESP-oaddESP; axtovar: CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x01+vop); op(wtok.rm); /* ADD [anyword],AX */ outaddress(&wtok); next=0; } else{ switch(tok){ case tk_number: case tk_postnumber: case tk_undefofs: num: #ifdef OPTVARCONST if(tok==tk_number&&(itok.flag&f_reloc)==0){ initconst=UpdVarConst(&wtok,itok.lnumber,itok.rm,operand); } #endif CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); if(tok==tk_number&&(itok.flag&f_reloc)==0&&itok.number==1&&(vop==0||vop==0x28)){ if(vop)vop=8; op(0xFF); op(vop+wtok.rm); outaddress(&wtok); } else if(tok!=tk_undefofs&&tok!=tk_postnumber&&(itok.flag&f_reloc)==0&& short_ok(itok.number,razr/2-1)){ op(0x83); op(vop+wtok.rm); outaddress(&wtok); op((unsigned int)itok.number); } else{ op(0x81); op(vop+wtok.rm); outaddress(&wtok); if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); else if((itok.flag&f_reloc)!=0)AddReloc(); razr==r16?outword(itok.number):outdword(itok.number); } if(next==0)tok=otok; break; case tk_apioffset: CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x81); op(vop+wtok.rm); outaddress(&wtok); AddApiToPost(itok.number); break; case tk_reg32: if(razr==r16)goto defxor; case tk_reg: if(tok==tk_reg&&razr==r32)goto defxor; #ifdef OPTVARCONST initconst=CheckUpdRegToConst(itok.number,&wtok,operand,razr); #endif CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x01+vop); op((unsigned int)itok.number*8+wtok.rm); outaddress(&wtok); break; default: defxor: retrez=razr==r16?tk_reg:tk_reg32; do_e_axmath(sign,razr,&ofsstr); if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar))wtok.number+=addESP-oaddESP; CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x01+vop); op(wtok.rm); /* ADD [anyword],AX */ outaddress(&wtok); next=0; break; } } // puts(wtok.name); KillVar(wtok.name); break; case tk_multequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper){ if(tok==tk_number){ if(itok.number==1)break; if(itok.number==0){ ZeroReg(hnumber,razr); goto getfromax; } #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&wtok,itok.lnumber,itok.rm,operand); } #endif if(hnumber==0)getinto_e_ax(sign,otok,&wtok,wbuf,&wstr,razr,TRUE); else getinto_reg(otok,&wtok,wbuf,&wstr,razr,hnumber); vop=0; RegMulNum(hnumber,itok.number,razr,sign,(int *)&vop,itok.flag); goto getfromax; } } if(hnumber==0)do_e_axmath(sign,razr,&ofsstr); else getintoreg(hnumber,razr,sign,&ofsstr); if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar)){ wtok.number+=addESP-oaddESP; oaddESP=addESP; } CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); if(hnumber==0){ outseg(&wtok,2); op(0xF7); // imul/mul var if(sign)op(0x28+wtok.rm); else op(0x20+wtok.rm); } else{ outseg(&wtok,3); outword(0xaf0f); op(wtok.rm+hnumber*8); } outaddress(&wtok); next=0; KillVar(wtok.name); goto getfromax; case tk_divequals: getoperand(am32==TRUE?EAX:BX); hnumber=0; if(itok2.type==tp_stopper){ if(tok==tk_number){ if(itok.number==1)break; #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&wtok,itok.lnumber,itok.rm,operand); } #endif getinto_e_ax(sign,otok,&wtok,wbuf,&wstr,razr,TRUE); DivMod(0,sign,razr,0); next=0; goto getfromax; } getintoreg_32(CX,razr,sign,&ofsstr); } else{ do_e_axmath(sign,razr,&ofsstr); if(optimizespeed)outword(0xC88B); //mov CX,ax else op(0x90+ECX); //xchg ax,Cx if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar)){ wtok.number+=addESP-oaddESP; oaddESP=addESP; } } getinto_e_ax(sign,otok,&wtok,wbuf,&wstr,razr,TRUE); ClearDX(razr,sign); op66(razr); op(0xF7); if(sign)op(0xF8+ECX); // IDIV CX else op(0xF0+ECX); // DIV CX next=0; warningreg(regs[razr/2-1][ECX]); KillVar(wtok.name); goto getfromax; case tk_swap: KillVar(wtok.name); int regdi; regdi=TRUE; getoperand(); rbuf=bufrm; bufrm=NULL; if(am32!=FALSE&&wbuf!=NULL&&wstr.bufstr!=NULL)regdi=FALSE; switch(tok){ case tk_reg32: if(razr==r16)swaperror(); case tk_reg: if(tok==tk_reg&&razr==r32)swaperror(); #ifdef OPTVARCONST initconst=SwapVarRegConst(itok.number,&wtok,razr); #endif CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x87); op((unsigned int)itok.number*8+wtok.rm); outaddress(&wtok); ClearReg(itok.number); break; case tk_qwordvar: case tk_longvar: case tk_dwordvar: if(razr==r16)swaperror(); case tk_intvar: case tk_wordvar: if((tok==tk_intvar||tok==tk_wordvar)&&razr==r32)swaperror(); #ifdef OPTVARCONST ClearVarByNum(&itok); #endif if(hnumber==0)getinto_e_ax(sign,otok,&wtok,wbuf,&wstr,razr,TRUE); else{ if(regoverstack&&(!((bufrm||strinf.bufstr)&&(wbuf||wstr.bufstr)))){ CheckAllMassiv(bufrm,razr,&strinf); op66(razr); outseg(&itok,2); op(0xFF); // PUSH [dword] op(0x30+itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xFF); // PUSH [dword] op(0x30+wtok.rm); outaddress(&wtok); CheckAllMassiv(bufrm,razr,&strinf); op66(razr); outseg(&itok,2); op(0x8f); op(itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0x8f); op(wtok.rm); outaddress(&wtok); break; } getinto_reg(otok,&wtok,wbuf,&wstr,razr,hnumber); } CheckAllMassiv(rbuf,razr,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); op66(razr); outseg(&itok,2); op(0x87); /* XCHG AX,[wloc] */ op(itok.rm+hnumber*8); outaddress(&itok); goto getfromax; case tk_seg: if(razr==r32)swaperror(); op66(r16); op(0x8C); /* MOV AX,seg */ op(0xC0+(unsigned int)itok.number*8); CheckAllMassiv(wbuf,2,&wstr,&wtok); op66(r16); outseg(&wtok,2); op(0x87); /* XCHG AX,[wloc] */ op(wtok.rm); outaddress(&wtok); op66(r16); op(0x8E); /* MOV seg,AX */ op(0xC0+(unsigned int)itok.number*8); break; case tk_floatvar: if(razr==r16)swaperror(); if(sign==1){ CheckAllMassiv(wbuf,4,&wstr,&wtok); outseg(&wtok,2); //fild op(0xDB); op(wtok.rm); outaddress(&wtok); CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fld val op(0xd9); op(itok.rm); outaddress(&itok); } else{ CheckInitBP(); op66(r32); //push 0L outword(0x6a); CheckAllMassiv(wbuf,4,&wstr,&wtok); op66(r32); //push var if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=8; addESP+=8; outseg(&wtok,2); op(0xFF); op(wtok.rm+0x30); outaddress(&wtok); fildq_stack(); CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fld val op(0xd9); op(itok.rm); outaddress(&itok); RestoreBP(); if(optimizespeed||am32==0){ outword(0xC483); op(8); } else{ op(0x58); // pop EAX op(0x58); // pop EAX } addESP-=8; } outseg(&wtok,2);//fistp var op(0xDB); op(wtok.rm+0x18); outaddress(&wtok); outseg(&itok,2); //fstp val op(0xd9); op(itok.rm+0x18); outaddress(&itok); fwait3(); break; default: swaperror(); break; } break; case tk_rrequals: vop=8; if(sign)vop+=0x10; case tk_llequals: KillVar(wtok.name); getoperand(am32==TRUE?ECX:BX); if(itok2.type!=tp_stopper){ doalmath(0,&ofsstr); // all shifts unsigned byte ClearReg(AX); ClearReg(CX); outword(0xC188); // MOV CL,AL if(addESP!=oaddESP&&am32&&ESPloc&&(wtok.type==tp_paramvar||wtok.type==tp_localvar))wtok.number+=addESP-oaddESP; CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xD3); op(0x20+vop+wtok.rm); // SHL [rmword],CL outaddress(&wtok); warningreg(begs[1]); next=0; } else if(tok==tk_number){ #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&wtok,itok.lnumber,itok.rm,operand); } #endif CheckAllMassiv(wbuf,razr,&wstr,&wtok); if((unsigned int)itok.number==1){ op66(razr); outseg(&wtok,2); op(0xD1); op(0x20+vop+wtok.rm); /* SHL [rmword],1 */ outaddress(&wtok); } else if((unsigned int)itok.number!=0){ if(chip<2&&razr==r16){ getintobeg(CL,&ofsstr); op66(r16); outseg(&wtok,2); op(0xD3); op(0x20+vop+wtok.rm); /* SHL [rmword],CL */ outaddress(&wtok); warningreg(begs[1]); ClearReg(CX); next=0; } else{ op66(razr); outseg(&wtok,2); op(0xC1); op(0x20+vop+wtok.rm); /* SHL [rmword],imm8 */ outaddress(&wtok); if(cpu<2)cpu=2; } op((unsigned int)itok.number); } } else{ if(tok!=tk_beg||(unsigned int)itok.number!=CL){ getintobeg(CL,&ofsstr); warningreg(begs[1]); ClearReg(CX); next=0; } CheckAllMassiv(wbuf,razr,&wstr,&wtok); op66(razr); outseg(&wtok,2); op(0xD3); op(0x20+vop+wtok.rm); /* SHL [rmword],CL */ outaddress(&wtok); } break; default: operatorexpected(); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&wtok); #endif if(next)nexttok(); if(terminater==tk_semicolon)seminext(); if(razr==r32&&cpu<3)cpu=3; return retrez; } int dobytevar(int sign,int terminater) // byte, char { unsigned char next=1,getfromAX=0; unsigned int vop=0,otok,rettype,posiblret=0; ITOK btok; char *bbuf,*rbuf; int retrez=0,pointr=0,hnumber=AL; SINFO bstr; int numpointr=0; char *ofsstr=NULL; #ifdef OPTVARCONST int initconst=FALSE; int operand; #endif unsigned int oaddESP=addESP; sign==0?posiblret=rettype=tk_byte:posiblret=rettype=tk_char; bstr=strinf; strinf.bufstr=NULL; btok=itok; bbuf=bufrm; bufrm=NULL; otok=tok; while(RmEqualReg(hnumber,itok.rm,itok.sib))hnumber++; nexttok(); #ifdef OPTVARCONST operand=tok; #endif switch(tok){ case tk_assign: if(!((tok2==tk_reg||tok2==tk_reg32||tok2==tk_beg)&&ScanTok3()==terminater)){ ofsstr=GetLecsem(terminater); } if(ofsstr){ int retreg; if((retreg=CheckIDZReg(ofsstr,AX,r8))!=NOINREG){ GetEndLex(terminater); tok=tk_beg; itok.number=retreg==SKIPREG?AX:retreg; goto regtovar; } } nexttok(); convert_type(&sign,(int *)&rettype,&pointr); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign){ hnumber=MultiAssign(r8,USEALLREG,numpointr); if(ofsstr){ free(ofsstr); ofsstr=NULL; } next=0; goto getfromax; } if(tok==tk_pointer)cpointr(am32==TRUE?EAX:BX,numpointr); CheckMinusNum(); if(itok2.type==tp_opperand){ if(rettype!=tk_float&&tok==tk_number){ //проверка и суммирование чисел if(OnlyNumber(sign)){ next=0; goto numbertovar; } } goto labl1; } else{ #ifdef OPTVARCONST if(tok>=tk_charvar&&tok<=tk_doublevar&&itok.npointr==0){ if(CheckConstVar(&itok))tok=tk_number; } #endif switch(tok){ case tk_number: numbertovar: #ifdef OPTVARCONST if((initconst=Const2Var(&btok,itok.lnumber&0Xff,itok.rm))==FALSE){ waralreadinitvar(btok.name,itok.number); initconst=TRUE; break; } #endif CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xC6); op(btok.rm); outaddress(&btok); op((unsigned int)itok.number); break; case tk_reg32: case tk_reg: if((unsigned int)itok.number>BX)goto labl1; case tk_beg: regtovar: if((unsigned int)itok.number==0){ getfromAX=1; hnumber=0; } else{ KillVar(btok.name); AddRegVar(itok.number,r8,&btok); vop++; CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0x88); op((unsigned int)itok.number*8+btok.rm); outaddress(&btok); } break; case tk_seg: segbyteerror(); break; default: labl1: if(rettype==tk_char||rettype==tk_byte){ if(hnumber==0)retrez=doalmath(sign,&ofsstr); else retrez=getintobeg(hnumber,&ofsstr); } else if(rettype==tk_int||rettype==tk_word){ if(hnumber==0)retrez=do_e_axmath(sign,r16,&ofsstr); else retrez=getintoreg(hnumber,r16,sign,&ofsstr); } else if(rettype==tk_float){ doeaxfloatmath(tk_reg32); rettype=tk_long; hnumber=0; } else{ if(hnumber==0)retrez=do_e_axmath(sign,r32,&ofsstr); else retrez=getintoreg(hnumber,r32,sign,&ofsstr); } getfromAX=1; next=0; break; } } if(getfromAX){ getfromax: #ifdef OPTVARCONST initconst=CheckRegToConst(hnumber,&btok,r8); #endif if(retrez==0)retrez=tk_reg; convert_returnvalue(posiblret,rettype); if(addESP!=oaddESP&&am32&&ESPloc&&(btok.type==tp_paramvar||btok.type==tp_localvar))btok.number+=addESP-oaddESP; if(bbuf==NULL&&bstr.bufstr==NULL&&hnumber==0&&((btok.rm==rm_d16&&btok.sib==CODE16)||(btok.rm==rm_d32&&(btok.sib==CODE32||btok.sib==0)))){ outseg(&btok,1); op(0xA2); // MOV [byte],AL if(btok.post==UNDEF_OFSET){ AddUndefOff(2,btok.name); btok.post=0; } if(am32==FALSE)outword(btok.number); else outdword(btok.number); } else{ CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); // MOV [rmbyte],AL op(0x88); op(btok.rm+hnumber*8); outaddress(&btok); } if(ofsstr)IDZToReg(ofsstr,hnumber,r8); else ClearReg(hnumber); KillVar(btok.name); AddRegVar(hnumber,r8,&btok); } else if(vop)KillVar(btok.name); if(ofsstr)free(ofsstr); break; case tk_multequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper&&tok==tk_number){ if(itok.number==1)break; if(itok.number==0){ outword(0xB0+hnumber); goto getfromax; } #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&btok,itok.lnumber,itok.rm,tk_mult); } #endif } doalmath(sign,&ofsstr); hnumber=0; if(addESP!=oaddESP&&am32&&ESPloc&&(btok.type==tp_paramvar||btok.type==tp_localvar)){ btok.number+=addESP-oaddESP; oaddESP=addESP; } CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xF6); if(sign)op(0x28+btok.rm); else op(0x20+btok.rm); outaddress(&btok); next=0; KillVar(btok.name); goto getfromax; case tk_divequals: hnumber=0; getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper){ if(tok==tk_number){ if(itok.number==1)break; #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&btok,itok.lnumber,itok.rm,tk_div); } #endif } getintobeg(CL,&ofsstr); warningreg(begs[1]); } else{ doalmath(sign,&ofsstr); outword(0xC88A); //mov Cl,al if(addESP!=oaddESP&&am32&&ESPloc&&(btok.type==tp_paramvar||btok.type==tp_localvar)){ btok.number+=addESP-oaddESP; oaddESP=addESP; } } if(sign)cbw(); else xorAHAH(); getintoal(otok,&btok,bbuf,&bstr); warningreg(begs[3]); op(0xF6); if(sign)op(0xF8+CL); // IDIV CL else op(0xF0+CL); // DIV CL next=0; ClearReg(CX); KillVar(btok.name); goto getfromax; case tk_minusminus: vop=0x8; case tk_plusplus: #ifdef OPTVARCONST initconst=UpdVarConst(&btok,1,tk_byte,tok); #endif CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xFE); op(vop+btok.rm); outaddress(&btok); KillVar(btok.name); break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: KillVar(btok.name); getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_opperand){ if(tok==tk_number){ if(OnlyNumber(sign)){ next=0; otok=tok; tok=tk_number; goto num; } } doalmath(sign,&ofsstr); if(addESP!=oaddESP&&am32&&ESPloc&&(btok.type==tp_paramvar||btok.type==tp_localvar))btok.number+=addESP-oaddESP; CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(vop); op(btok.rm); // ADD [anybyte],AL outaddress(&btok); next=0; retrez=tk_reg; } else{ switch(tok){ case tk_number: num: #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&btok,itok.lnumber,itok.rm,operand); } #endif CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); if(itok.number==1&&(vop==0||vop==0x28)){ if(vop)vop=8; op(0xFE); op(vop+btok.rm); outaddress(&btok); } else{ op(0x80); op(vop+btok.rm); outaddress(&btok); op((unsigned int)itok.number); } if(next==0)tok=otok; break; case tk_beg: #ifdef OPTVARCONST initconst=CheckUpdRegToConst(itok.number,&btok,operand,r8); #endif CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(vop); op((unsigned int)itok.number*8+btok.rm); outaddress(&btok); break; case tk_seg: segbyteerror(); break; default: retrez=tk_reg; doalmath(sign,&ofsstr); CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(vop); op(btok.rm); /* ADD [anybyte],AL */ outaddress(&btok); next=0; break; } } break; case tk_swap: KillVar(btok.name); getoperand(); rbuf=bufrm; bufrm=NULL; switch(tok){ case tk_beg: #ifdef OPTVARCONST initconst=SwapVarRegConst(itok.number,&btok,r8); #endif CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0x86); /* XCHG beg,[anybloc] */ op((unsigned int)itok.number*8+btok.rm); outaddress(&btok); ClearReg(itok.number>3?itok.number-4:itok.number); break; case tk_bytevar: case tk_charvar: #ifdef OPTVARCONST initconst=SwapVarConst(&itok,&btok); #endif if(hnumber==0)getintoal(otok,&btok,bbuf,&bstr); else getinto_reg(otok,&btok,bbuf,&bstr,r8,hnumber); CheckAllMassiv(rbuf,1,&strinf,&itok,(am32!=FALSE&&bbuf!=NULL&&bstr.bufstr!=NULL)?BX:DI,DX); outseg(&itok,2); op(0x86); /* XCHG AL,[bloc] */ op(itok.rm+hnumber*8); outaddress(&itok); KillVar(itok.name); goto getfromax; default: swaperror(); break; } break; case tk_rrequals: vop=8; if(sign)vop+=0x10; case tk_llequals: KillVar(btok.name); getoperand(am32==TRUE?ECX:BX); if(itok2.type!=tp_stopper){ doalmath(0,&ofsstr); // all shifts unsigned byte outword(0xC188); // MOV CL,AL if(addESP!=oaddESP&&am32&&ESPloc&&(btok.type==tp_paramvar||btok.type==tp_localvar))btok.number+=addESP-oaddESP; CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xD2); op(0x20+vop+btok.rm); /* SHL [byte],CL */ outaddress(&btok); warningreg(begs[1]); ClearReg(CX); ClearReg(AX); next=0; } else if(tok==tk_number){ #ifdef OPTVARCONST if((itok.flag&f_reloc)==0){ initconst=UpdVarConst(&btok,itok.lnumber,itok.rm,operand); } #endif if((unsigned int)itok.number==1){ CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xD0); op(0x20+vop+btok.rm); /* SHL [byte],1 */ outaddress(&btok); } else if((unsigned int)itok.number!=0){ CheckAllMassiv(bbuf,1,&bstr,&btok); if(chip<2){ getintobeg(CL,&ofsstr); outseg(&btok,2); op(0xD2); op(0x20+vop+btok.rm); /* SHL [byte],CL */ outaddress(&btok); warningreg(begs[1]); ClearReg(CX); next=0; } else{ outseg(&btok,2); op(0xC0); op(0x20+vop+btok.rm); /* SHL [byte],imm8 */ outaddress(&btok); if(cpu<2)cpu=2; } op((unsigned int)itok.number); } } else{ if(tok!=tk_beg||(unsigned int)itok.number!=CL){ getintobeg(CL,&ofsstr); warningreg(begs[1]); ClearReg(CX); next=0; } CheckAllMassiv(bbuf,1,&bstr,&btok); outseg(&btok,2); op(0xD2); op(0x20+vop+btok.rm); /* SHL [byte],CL */ outaddress(&btok); } break; default: operatorexpected(); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&btok); #endif if(next)nexttok(); if(terminater==tk_semicolon)seminext(); return retrez; } void getinto_reg(int gtok,ITOK *gstok,char *&gbuf,SINFO *gstr,int razr,int reg) { unsigned int i=0; int vop=0; int reg1=SI,reg2=DI; switch(gtok){ case tk_dwordvar: case tk_longvar: i+=4; longvar: CheckAllMassiv(gbuf,i,gstr,gstok,reg1,reg2); op66(razr); outseg(gstok,2); op(0x8B); op(gstok->rm+reg*8); outaddress(gstok); ClearReg(reg); break; case tk_intvar: vop=8; case tk_wordvar: i=2; goto longvar; case tk_bytevar: case tk_charvar: CheckAllMassiv(gbuf,i,gstr,gstok,reg1,reg2); outseg(gstok,2); op(0x8A); op(gstok->rm+reg*8); outaddress(gstok); ClearReg(reg); break; } } void getinto_e_ax(int sign,int gtok,ITOK *gstok,char *&gbuf,SINFO *gstr,int razr,int useAX) { unsigned int i=0; int vop=0; int reg1=idxregs[0],reg2=idxregs[1]; if(am32){ reg1=useAX==FALSE?EAX:idxregs[0]; reg2=idxregs[3]; } // printf("tok=%u %s\n",gtok,gstok->name); switch(gtok){ case tk_bits: vop=gstok->bit.siz+gstok->bit.ofs; if(vop<=64)i=r64; if(vop<=32)i=r32; if(vop<=16)i=r16; bits2reg(AX,((unsigned int)razr>i?razr:i)); break; case tk_postnumber: op66(razr); op(0xB8); /* MOV EAX,# */ (gstok->flag&f_extern)==0?setwordpost(gstok):setwordext(&gstok->number); razr==r16?outword(gstok->number):outdword(gstok->number); ClearReg(AX); break; case tk_rmnumber: CheckAllMassiv(gbuf,gstok->size,gstr,gstok,reg1,reg2); if(gstok->rm||am32==0){ op66(razr); op67(gstok->sib==CODE16?r16:r32); if(gstok->post==0)outseg(gstok,2); op(0x8D); op(gstok->rm); if(gstok->post!=0&&gstok->post!=UNDEF_OFSET){ if((gstok->flag&f_extern)==0){ i=outptr; if(am32&&gstok->rm==rm_sib)outptr++; setwordpost(gstok); outptr=i; } else setwordext(&gstok->number); } outaddress(gstok); /* LEA AX,[rm] */ ClearReg(AX); } else nexttok(); break; case tk_doublevar: vop=4; case tk_floatvar: CheckInitBP(); if(cpu<3)cpu=3; op66(r32); op(0x50); //push EAX if(ESPloc&&am32&&gstok->segm==SS)gstok->number+=4; addESP+=4; CheckAllMassiv(gbuf,4,gstr,gstok,reg1,reg2); outseg(gstok,2); //fld floatvar op(0xd9+vop); op(gstok->rm); outaddress(gstok); fistp_stack(); op66(r32); op(0x58); //pop EAX addESP-=4; RestoreBP(); ClearReg(AX); break; case tk_qwordvar: i=4; case tk_dwordvar: case tk_longvar: i+=4; longvar: if((gstok->rm==rm_d16&&gstok->sib==CODE16)||(gstok->rm==rm_d32&&(gstok->sib==CODE32||gstok->sib==0))){ op66(razr); outseg(gstok,1); op(0xA1); if(gstok->post==UNDEF_OFSET)AddUndefOff(2,gstok->name); if(am32==FALSE)outword((unsigned int)gstok->number); else outdword(gstok->number); } else{ CheckAllMassiv(gbuf,i,gstr,gstok,reg1,reg2); op66(razr); outseg(gstok,2); op(0x8B); op(gstok->rm); outaddress(gstok); } ClearReg(AX); break; case tk_intvar: vop=8; case tk_wordvar: i=2; if(razr==r16)goto longvar; i=1; if(optimizespeed&&vop==0&&chip>3&&chip<7)goto optpent; movxx: CheckAllMassiv(gbuf,1+i,gstr,gstok,reg1,reg2); op66(razr); outseg(gstok,3); /* MOVSX EAX,[charvar] */ op(0x0F); op(0xB6+vop+i); op(gstok->rm); outaddress(gstok); ClearReg(AX); break; case tk_charvar: vop=8; if(razr==r16){ if((gstok->rm==rm_d16&&gstok->sib==CODE16)||(gstok->rm==rm_d32&&(gstok->sib==CODE32||gstok->sib==0))){ outseg(gstok,1); op(0xA0); if(am32==FALSE)outword(gstok->number); else outdword(gstok->number); } else{ CheckAllMassiv(gbuf,1,gstr,gstok,reg1,reg2); outseg(gstok,2); op(0x8A); op(gstok->rm); outaddress(gstok); } cbw(); ClearReg(AX); break; } goto movxx; case tk_bytevar: optpent: if((gstok->rm==rm_d16&&gstok->sib==CODE16)||(gstok->rm==rm_d32&&(gstok->sib==CODE32||gstok->sib==0))){ ZeroReg(EAX,razr); if(i)op66(r16); outseg(gstok,1); op(0xA0+i); if(am32==FALSE)outword(gstok->number); else outdword(gstok->number); ClearReg(AX); break; } if((chip>=3&&(!optimizespeed))||RmEqualReg(AX,gstok->rm,gstok->sib))goto movxx; ZeroReg(EAX,razr); CheckAllMassiv(gbuf,1+i,gstr,gstok,SI,reg2); if(i)op66(r16); outseg(gstok,2); op(0x8A+i); op(gstok->rm); outaddress(gstok); break; case tk_beg: if(gstok->number==AL&&(!sign)&&razr==r16){ xorAHAH(); ClearReg(AX); break; } if(optimizespeed&&chip>3&&chip<7){ if(sign){ if(razr==r32)goto movxxr; if(gstok->number!=AL){ op(0x88); op(0xC0+gstok->number*8); //mov al,beg } if(gstok->number!=AH)outword(0xC488); //mov ah,al outword(0xFCC0); //sar ah,7 op(7); } else{ if(razr==r32&&(gstok->number==AL||gstok->number==AH)){ /*if(chip==4)*/goto movxxr; /* op(0x88); op(0xC1+gstok->number*8); //mov cl,beg xorEAXEAX(); outword(0xC888); // mov al,cl warningreg(begs[1]); break;*/ } if(gstok->number==AH)outdword(0xE430E088); //mov al,ah xor ah,ah else{ ZeroReg(EAX,razr); op(0x88); op(0xC0+gstok->number*8); //mov al,beg } } ClearReg(AX); break; } movxxr: if(chip>2||razr==r32){ op66(razr); if(sign)outword(0xBE0F); else outword(0xB60F); op(0xC0+(unsigned int)gstok->number); // MOVxX AX,beg } else{ op(0x88); op(0xC0+gstok->number*8); if(sign)cbw(); else xorAHAH(); } ClearReg(AX); break; case tk_reg: if(razr==r32){ if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=gstok->number; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(r16); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ #ifdef OPTVARCONST FreeGlobalConst(); #endif clearregstat(); break; } if(optimizespeed&&(!sign)&&chip>3&&chip<7){ if(gstok->number==AX){ goto movxr; /* op66(r16); outword(0xC189); //mov cx,AX xorEAXEAX(); op66(r16); outword(0xC889); //mov aX,cX warningreg(regs[0][1]);*/ } else{ xorEAXEAX(); op66(r16); op(0x89); op(0xC0+gstok->number*8); //mov ax,reg } } else{ movxr: op66(r32); op(0x0F); /* MOVSX or MOVZX EAX,reg */ if(sign)op(0xBF); else op(0xB7); op(0xC0+gstok->number); } RegToReg(AX,gstok->number,razr); break; } case tk_reg32: if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=gstok->number; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(razr); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif break; } if(gstok->number!=AX){ op66(razr); op(0x89); op(0xC0+gstok->number*8); RegToReg(AX,gstok->number,razr); } break; case tk_seg: if(razr==r32)op66(r32); op(0x8C); //mov var,SS op(0xC0+gstok->number*8); ClearReg(AX); break; case tk_string: op66(razr); op(0xB8); if(razr==r16){ if(am32)dwordvalexpected(); outword(addpoststring(CS,gstok->number,gstok->flag)); } else outdword(addpoststring(CS,gstok->number,gstok->flag)); ClearReg(AX); break; default: valueexpected(); break; } if(razr==r32&&cpu<3)cpu=3; } int caselong(unsigned long val) { int vop=0; unsigned long num; for(;vop0x20){ op66(razr); op(0x90+EDX); //xchg ax,dx } goto defreg32; case tk_bits: int vops; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; bits2reg(CX,(razr2||razr==r32){ op66(razr); op(0x0f); outword(0xC2a4); //SHLD DX,AX,num op(itok.number); } else{ if((unsigned int)itok.number==1)outdword(0xd213c001); //ADD AX,AX ADC DX,DX else if((unsigned int)itok.number!=0){ getintobeg(CL,&ofsstr); outdword(0xd213c001); //ADD AX,AX ADC DX,DX outword(0xfae2); //LOOP -6 warningreg(begs[1]); next=0; } break; } } lshiftmul(itok.number,razr); setzeroflag=TRUE; } else goto llminus; break; case tk_llminus: tok=tk_minus; // do optimization 286+ here later llminus: if(!((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&itok.number==1)){ getintobeg(CL,&ofsstr); warningreg(begs[1]); } else getoperand(); next=0; if(expand==TRUE){ if(chip>2||razr==r32){ op66(razr); op(0x0f); outword(0xC2a5); //SHLD DX,AX,CL } else outdword(0xd213c001); //ADD AX,AX ADC DX,DX outword(0xfae2); //LOOP -6 break; } op66(razr); outword(0xE0D3); /* SHL AX,CL */ setzeroflag=TRUE; break; case tk_rr: if(sign)vop=0x10; getoperand(); if(expand==TRUE){ if(tok==tk_number){ if((unsigned int)itok.number==1){ op66(razr); outword(0xead1); //shr dx,1 ror ax,1 op66(razr); outword(0xc8d1); //shr dx,1 ror ax,1 setzeroflag=TRUE; } else if((unsigned int)itok.number!=0){ if(chip>2||razr==r32){ op66(razr); op(0x0f); outword(0xd0ac); //shrd ax,dx,num op(itok.number); op66(razr); op(0xc1); op(0xea+vop);//s?r dx,num op(itok.number); setzeroflag=TRUE; } else{ next=0; getintobeg(CL,&ofsstr); warningreg(begs[1]); op(0xd1); op(0xea+vop);//s?r dx,1 outdword(0xfae2d8d1); //rcr ax,1 LOOP -6 setzeroflag=FALSE; } } } else goto rrminus; } else{ RshiftReg(razr,EAX,vop); setzeroflag=TRUE; next=0; } break; case tk_rrminus: if(sign)vop=0x10; tok=tk_minus; // do optimization 286+ here later rrminus: if(!((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&itok.number==1)){ getintobeg(CL,&ofsstr); warningreg(begs[1]); } else getoperand(); if(expand==TRUE){ if(chip>2||razr==r32){ op66(razr); op(0x0f); outword(0xd0ad); //shrd ax,dx,cl op66(razr); op(0xd3); op(0xea+vop);//s?r dx,num setzeroflag=TRUE; } else{ op(0xd1); op(0xea+vop);//s?r dx,1 outdword(0xfae2d8d1); //rcr ax,1 //LOOP -6 setzeroflag=FALSE; } } else{ op66(razr); op(0xD3); op(0xE8+vop); /* SR AX,CL */ setzeroflag=TRUE; } next=0; break; default: operatorexpected(); break; } calcnumber=FALSE; ClearReg(EAX); if(negflag){ NegReg(razr,EAX); setzeroflag=TRUE; negflag=0; } if(next)nexttok(); } calcnumber=FALSE; ClearReg(EAX); if(tok==tk_eof)unexpectedeof(); if(razr==r32&&cpu<3)cpu=3; } void getintoal(int gtok,ITOK *gstok,char *&gbuf,SINFO *gstr) // AH may also be changed { unsigned int i=0; switch(gtok){ case tk_bits: int razr; i=gstok->bit.siz+gstok->bit.ofs; if(i<=64)razr=r64; if(i<=32)razr=r32; if(i<=16)razr=r16; if(i<=8)razr=r8; bits2reg(AL,razr); break; case tk_number: op(0xB0); /* MOV AL,# */ op(gstok->number); ConstToReg(gstok->number,AL,r8); break; case tk_rmnumber: CheckAllMassiv(gbuf,gstok->size,gstr,gstok); op66(r16); op67(gstok->sib==CODE16?r16:r32); if(gstok->post==0)outseg(gstok,2); op(0x8D); /* LEA AX,[rm] */ op(gstok->rm); if(gstok->post!=0&&gstok->post!=UNDEF_OFSET){ if((gstok->flag&f_extern)==0){ i=outptr; if(am32&&gstok->rm==rm_sib)outptr++; setwordpost(gstok); outptr=i; } else setwordext(&gstok->number); } outaddress(gstok); ClearReg(AL); break; case tk_postnumber: op66(r16); op(0xB8); /* MOV AX,# */ (gstok->flag&f_extern)==0?setwordpost(gstok):setwordext(&gstok->number); outword(gstok->number); ClearReg(AL); break; case tk_floatvar: if(cpu<3)cpu=3; CheckInitBP(); op66(r32); outword(0x6a); //push 0 if(ESPloc&&am32&&gstok->segm==SS)gstok->number+=4; addESP+=4; CheckAllMassiv(gbuf,4,gstr,gstok); outseg(gstok,2); //fld floatvar op(0xd9); op(gstok->rm); outaddress(gstok); fistp_stack(); op66(r32); op(0x58); //pop EAX addESP-=4; RestoreBP(); ClearReg(AL); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_bytevar: case tk_charvar: i++; if((gstok->rm==rm_d16&&gstok->sib==CODE16)||(gstok->rm==rm_d32&&(gstok->sib==CODE32||gstok->sib==0))){ outseg(gstok,1); op(0xA0); //mov AL, if(gstok->post==UNDEF_OFSET)AddUndefOff(2,gstok->name); if(am32==FALSE)outword(gstok->number); else outdword(gstok->number); } else{ CheckAllMassiv(gbuf,i,gstr,gstok); outseg(gstok,2); op(0x8A); op(gstok->rm); outaddress(gstok); } ClearReg(AL); break; case tk_reg32: if(gstok->number>BX){ i=1; if(gstok->number!=AX)op66(r32); } goto beg1; case tk_reg: if(gstok->number>BX){ i=1; if(gstok->number!=AX)op66(r16); } case tk_beg: beg1: if(gstok->number!=AL){ op(0x88+i); //mov [],AL op(0xC0+gstok->number*8); } ClearReg(AL); break; case tk_seg: op66(r16); op(0x8C); op(0xC0+gstok->number*8); break; ClearReg(AL); default: bytevalexpected(0); break; } } int doalmath(int sign,char **ofsstr) { int negflag=0,i=0; int rettype=tk_beg; if(tok==tk_minus){ if(CheckMinusNum()==FALSE){ negflag=1; getoperand(am32==TRUE?EAX:BX); } } #ifdef OPTVARCONST if(tok>=tk_charvar&&tok<=tk_doublevar&&itok.npointr==0){ if(CheckConstVar(&itok)){ tok=tk_number; calcnumber=TRUE; } } #endif switch(tok){ case tk_number: op(0xB0); //mov AL,num i=CalcNumber(sign); op(i); ConstToReg(i,AL,r8); break; case tk_at: getoperand(am32==TRUE?EAX:BX); i++; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: if(itok.flag&f_retproc)rettype=(itok.flag&f_retproc)/256+tk_overflowflag-1; if((!i)||macros(sign!=0?tk_char:tk_byte)==0)procdo(sign!=0?tk_char:tk_byte); nexttok(); if(*ofsstr){ free(*ofsstr); *ofsstr=NULL; } break; default: SINFO bstr=strinf; strinf.bufstr=NULL; ITOK btok; char *bbuf; btok=itok; bbuf=bufrm; bufrm=NULL; getintoal(tok,&btok,bbuf,&bstr); nexttok(); break; } #ifdef OPTVARCONST calcnumber=FALSE; #endif if(negflag){ if(optimizespeed&&(chip==5||chip==6))outdword(0xC0FEFF34); //xor AL,-1 AL++ else outword(0xD8F6);// NEG AL setzeroflag=TRUE; } if(itok.type!=tp_stopper&&tok!=tk_eof&&itok.type!=tp_compare){ doalmath2(sign); rettype=tk_beg; } return rettype; } void doalmath2(int sign) { int vop,i,next; int expand=FALSE,optnum=FALSE; int negflag=0; char *ofsstr=NULL; while(itok.type!=tp_stopper&&tok!=tk_eof&&itok.type!=tp_compare){ vop=0; i=0; next=1; #ifdef OPTVARCONST if(tok2>=tk_charvar&&tok2<=tk_doublevar&&itok2.npointr==0){ if(CheckConstVar(&itok2)){ tok2=tk_number; calcnumber=TRUE; } } #endif if(tok2==tk_number)optnum=OptimNum(); int oldtok=tok; switch(tok){ case tk_xor: vop+=0x08; case tk_minus: vop+=0x08; case tk_and: vop+=0x18; case tk_or: vop+=0x08; case tk_plus: if(optnum==FALSE)getoperand(); else{ tok=tk_number; optnum=FALSE; } switch(tok){ case tk_number: if(itok.number==0&&oldtok!=tk_and)break; if(itok.number==255&&oldtok==tk_and)break; op(0x04+vop); op((unsigned int)itok.number); /* OPT AL,num */ break; case tk_rmnumber: CheckAllMassiv(bufrm,itok.size,&strinf); op66(r16); op67(itok.sib==CODE16?r16:r32); if(itok.post==0)outseg(&itok,2); op(0x8D); /* LEA CX,[rm] */ op(0x8+itok.rm); if(itok.post!=0&&itok.post!=UNDEF_OFSET){ if((itok.flag&f_extern)==0){ unsigned int ooutptr=outptr; if(am32&&itok.rm==rm_sib)outptr++; setwordpost(&itok); outptr=ooutptr; } else setwordext(&itok.number); } outaddress(&itok); op(vop); /* OPT AL,CL */ op(0xC8); warningreg(regs[0][1]); break; case tk_postnumber: op66(r16); op(0x05+vop); /* OPT AX,# */ (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); outword((unsigned int)itok.number); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_charvar: case tk_bytevar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0x02+vop); op(itok.rm); outaddress(&itok); break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: op66(r16); op(0x50); //push AX addESP+=2; unsigned char oaddstack; oaddstack=addstack; addstack=FALSE; procdo(sign!=0?tk_char:tk_byte); addstack=oaddstack; addESP-=2; op66(r16); op(0x58+CX); itok.number=CX; warningreg(regs[0][CX]); if(vop>0x20){ op66(r16); op(0x90+CX); //xchg ax,Cx } goto defbeg; case tk_bits: int razr; i=itok.bit.siz+itok.bit.ofs; if(i<=64)razr=r64; if(i<=32)razr=r32; if(i<=16)razr=r16; if(i<=8)razr=r8; bits2reg(CL,razr); itok.number=CL; if(razr==r64)razr=r32; warningreg(razr==r8?begs[1]:(regs[razr/2-1][1])); goto defbeg; case tk_doublevar: i=4; case tk_floatvar: Float2reg32(EAX,i); itok.number=0; case tk_beg: defbeg: op(vop); op(0xC0+(unsigned int)itok.number*8); break; case tk_reg32: case tk_reg: if((unsigned int)itok.number>BX){ op66(r16); op(0x89); /* MOV CX,reg */ warningreg(regs[0][1]); op(0xC1+(unsigned int)itok.number*8); /* MOV instr */ itok.number=CL; } goto defbeg; default: valueexpected(); break; } setzeroflag=TRUE; if(expand==TRUE){ if(oldtok==tk_plus){ outword(0xd480); //ADC AH,0 op(0); } else if(oldtok==tk_minus){ outword(0xdc80); //SBB AH,0 op(0); } setzeroflag=FALSE; } break; case tk_modminus: negflag=1; case tk_mod: negflag=1-negflag; vop=1; case tk_divminus: negflag=1-negflag; case tk_div: if(optnum==FALSE)getoperand(); else{ tok=tk_number; optnum=FALSE; } if(tok==tk_number){ if(negflag){ itok.number=-itok.number; negflag=0; } itok.number&=255; if(vop){ //% if(itok.number==0)DevideZero(); if(caselong(itok.number)!=NUMNUM){ op(0x24); /* AND AL,number-1 */ op((unsigned int)itok.number-1); setzeroflag=TRUE; } else{ if(expand==FALSE){ if(sign)cbw(); else xorAHAH(); } op(0xB1); op((unsigned int)itok.number); /* MOV CL,# */ if(sign)outword(0xF9F6); /* IDIV CL */ else outword(0xF1F6); /* DIV CL */ outword(0xE088);// MOV AL,AH setzeroflag=FALSE; warningreg(begs[1]); break; } } else{ switch((unsigned int)itok.number){ case 0: DevideZero(); break; case 1: break; case 2: op(0xd0+expand); if(sign)op(0xf8); else op(0xE8);// SHR AL,1 setzeroflag=TRUE; break; default: vop=caselong(itok.number); if(vop!=NUMNUM){ if(chip<2){ op(0xB1); op(vop); /* MOV CL,num */ op(0xd2+expand); if(sign)op(0xF8); // SAR AL,CL else op(0xE8); // SHR AL,CL warningreg(begs[1]); } else{ op(0xc0+expand); if(sign)op(0xF8); /* SAR AL,num */ else op(0xE8); /* SHR AL,num */ op(vop); if(cpu<2)cpu=2; } setzeroflag=TRUE; } else{ if(expand==FALSE){ if(optimizespeed&&(itok.flag&f_reloc)==0&&sign==0){ //for signed needed new algoritm //замена деления умножением itok.number=256/(unsigned int)itok.number+1; if(chip>4){ xorAHAH(); op66(r16); outword(0xC06B); //imul AX,num op(itok.number); warningreg(regs[0][2]); } else{ op(0xB2); //mov DL,num op(itok.number); outword(0xE2F6); //mul DL warningreg(begs[2]); } outword(0xE088); //mov AL.AH setzeroflag=FALSE; break; } if(sign)cbw(); else xorAHAH(); } op(0xB1); /* MOV CL,# */ op((unsigned int)itok.number); if(sign)outword(0xF9F6); /* IDIV CL */ else outword(0xF1F6); /* DIV CL */ setzeroflag=FALSE; warningreg(begs[1]); } } } } else{ case tk_doublevar: i=4; if(tok==tk_floatvar){ Float2reg32(ECX,i); itok.number=ECX; tok=tk_beg; sign=1; } if(expand==FALSE){ if(sign)cbw(); else xorAHAH(); } switch(tok){ case tk_rmnumber: case tk_postnumber: getintoreg_32(CX,r16,sign,&ofsstr,FALSE); if(sign)outword(0xF9F6); // IDIV CL else outword(0xF1F6); // DIV CL setzeroflag=FALSE; warningreg(regs[0][1]); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_charvar: case tk_bytevar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0xF6); if(sign)op(0x38+itok.rm); else op(0x30+itok.rm); outaddress(&itok); setzeroflag=FALSE; break; case tk_bits: int razr; i=itok.bit.siz+itok.bit.ofs; if(i<=64)razr=r64; if(i<=32)razr=r32; if(i<=16)razr=r16; if(i<=8)razr=r8; bits2reg(CL,razr); itok.number=CL; if(razr==r64)razr=r32; warningreg(razr==r8?begs[1]:(regs[razr/2-1][1])); goto defdiv; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: op66(r16); op(0x50); //push AX addESP+=2; unsigned char oaddstack; oaddstack=addstack; addstack=FALSE; procdo(sign!=0?tk_char:tk_byte); addstack=oaddstack; addESP-=2; op66(r16); op(0x58+CX); itok.number=CX; warningreg(regs[0][CX]); op66(r16); op(0x90+CX); //xchg ax,cx case tk_beg: defdiv: op(0xF6); if(sign)op(0xF8+(unsigned int)itok.number); else op(0xF0+(unsigned int)itok.number); setzeroflag=FALSE; break; case tk_reg32: case tk_reg: if((unsigned int)itok.number>BX){ op66(r16); op(0x89); /* MOV CX,reg */ warningreg(regs[0][1]); op(0xC1+(unsigned int)itok.number*8); /* MOV instr */ itok.number=CL; } goto defdiv; default: valueexpected(); break; } if(vop)outword(0xE088);// MOV AL,AH } expand=FALSE; break; case tk_multminus: negflag=1; case tk_mult: expand=expandvar(); if(optnum==FALSE)getoperand(); else{ tok=tk_number; optnum=FALSE; } switch(tok){ case tk_number: if(negflag){ itok.number=-itok.number; negflag=0; } itok.number&=255; switch((unsigned int)itok.number){ case 0: /* AL * 0 = MOV AL,0 */ outword(0x00B0); case 1: expand=FALSE; setzeroflag=FALSE; break; /* AL * 1 = AL */ case 2: if(expand==TRUE){ if(sign)cbw(); else xorAHAH(); } outword(0xC000+expand); // AL * 2 = ADD AL,AL setzeroflag=TRUE; break; default: vop=caselong(itok.number); if(vop!=NUMNUM){ if(chip<1){ if(expand==TRUE){ if(optimizespeed==FALSE&&sign==FALSE)goto num_imul; if(sign)cbw(); else xorAHAH(); } op(0xB1); op(vop); /* MOV CL,num */ outword(0xE0D2+expand);// SHL AL,CL warningreg(begs[1]); } else{ if(expand==TRUE){ if(optimizespeed==FALSE&&sign==FALSE)goto num_imul; if(sign)cbw(); else xorAHAH(); op66(r16); } outword(0xe0c0+expand); //SHL AX/L,num op(vop); if(cpu<1)cpu=1; } setzeroflag=TRUE; } else if(expand==FALSE&&optimizespeed!=FALSE&& speedmul(itok.number,r8)!=FALSE); else{ num_imul: op(0xB1); /* MOV CL,# */ op((unsigned int)itok.number); if(sign)outword(0xE9F6);// IMUL CL else outword(0xE1F6); // MUL CL setzeroflag=FALSE; warningreg(begs[1]); } } break; case tk_rmnumber: case tk_postnumber: getintoreg_32(CX,r16,sign,&ofsstr,FALSE); if(sign)outword(0xE9F6); // IMUL CL else outword(0xE1F6); // MUL CL setzeroflag=FALSE; warningreg(regs[0][1]); break; case tk_doublevar: i=4; case tk_floatvar: Float2reg32(ECX,i); itok.number=ECX; outword(0xE9F6); // IMUL CL setzeroflag=FALSE; warningreg(begs[1]); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_charvar: case tk_bytevar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0xF6); if(sign)op(0x28+itok.rm); else op(0x20+itok.rm); outaddress(&itok); setzeroflag=FALSE; break; case tk_bits: int razr; i=itok.bit.siz+itok.bit.ofs; if(i<=64)razr=r64; if(i<=32)razr=r32; if(i<=16)razr=r16; if(i<=8)razr=r8; bits2reg(CL,razr); itok.number=CL; if(razr==r64)razr=r32; warningreg(razr==r8?begs[1]:(regs[razr/2-1][1])); goto defmul; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: op66(r16); op(0x50); //push AX addESP+=2; unsigned char oaddstack; oaddstack=addstack; addstack=FALSE; procdo(sign!=0?tk_char:tk_byte); addstack=oaddstack; addESP-=2; op66(r16); op(0x58+DX); itok.number=DX; warningreg(regs[0][DX]); case tk_beg: defmul: op(0xF6); if(sign)op(0xE8+(unsigned int)itok.number); else op(0xE0+(unsigned int)itok.number); setzeroflag=FALSE; break; case tk_reg32: case tk_reg: if((unsigned int)itok.number>BX){ op66(r16); op(0x89); /* MOV CX,reg */ warningreg(regs[0][1]); op(0xC1+(unsigned int)itok.number*8); /* MOV instr */ itok.number=CL; } goto defmul; default: valueexpected(); break; } break; case tk_xorminus: vop+=0x10; case tk_andminus: vop+=0x18; case tk_orminus: vop+=0x08; getoperand(); if(tok==tk_number){ itok.number=-itok.number; op(0x04+vop); op((unsigned int)itok.number); } else{ getintobeg(CL,&ofsstr); if(optimizespeed&&(chip==5||chip==6)){ op(0x80); outdword(0xC1FEFFE1); //and CL,-1 inc CL } else outword(0xD9F6); // NEG CL op(0x00+vop); op(0xC8); /* opt AL,CL */ warningreg(begs[1]); next=0; } setzeroflag=TRUE; break; case tk_rr: vop=8; if(sign)vop+=0x10; case tk_ll: getoperand(); if(tok==tk_number){ if((unsigned int)itok.number==1){ if(expand==TRUE)op66(r16); op(0xD0+expand); op(0xE0+vop); /* SR AL,1 */ } else if((unsigned int)itok.number!=0){ if(chip<2) goto llminus; else{ if(expand==TRUE)op66(r16); op(0xC0+expand); op(0xE0+vop); /* SR AL,imm8 */ op((unsigned int)itok.number); if(cpu<2)cpu=2; } } setzeroflag=TRUE; } else goto llminus; break; case tk_rrminus: vop=8; if(sign)vop+=0x10; case tk_llminus: tok=tk_minus; // need 286+ opt some time llminus: if(!((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&itok.number==1)){ getintobeg(CL,&ofsstr); warningreg(begs[1]); } else getoperand(); if(expand==TRUE)op66(r16); op(0xD2+expand); op(0xE0+vop); setzeroflag=TRUE; next=0; break; default: operatorexpected(); break; } if(negflag){ if(optimizespeed&&(chip==5||chip==6))outdword(0xC0FEFF34); //xor AL,-1 AL++ else outword(0xD8F6);// NEG AL negflag=0; setzeroflag=TRUE; } if(next)nexttok(); ClearReg(AX); } #ifdef OPTVARCONST calcnumber=FALSE; #endif if(tok==tk_eof)unexpectedeof(); } /* =============== doreg_32(), dobeg(), doseg() ===============*/ int doreg_32(int reg,int razr,int terminater) { unsigned char next=1; int vop=0,sign=0; int i; int reg1=idxregs[0],reg2=idxregs[1]; unsigned long ii; int rettype=tk_reg; int rrettype,pointr=0; int numpointr=0; char *ofsstr=NULL; if(reg==reg1){ reg1=idxregs[1]; reg2=idxregs[2]; } if(reg==reg2)reg2=idxregs[2]; if(reg==ESP)RestoreStack(); rrettype=razr==r16?tk_word:tk_dword; nexttok(); switch(tok){ case tk_assign://= if(am32)idxregs[4]=reg; if(!((tok2==tk_reg||tok2==tk_reg32||tok2==tk_beg)&&ScanTok3()==terminater)){ ofsstr=GetLecsem(terminater); } else{ nexttok(); switch(tok){ case tk_beg: i=r8; break; case tk_reg: i=r16; break; case tk_reg32: i=r32; break; } if(i!=razr||RegToReg(reg,itok.number,i)==NOINREG)goto nn1; waralreadinitreg(regs[razr/4][itok.number],regs[razr/4][reg]); if(am32)idxregs[4]=255; break; } if(ofsstr){ int retreg; if((retreg=CheckIDZReg(ofsstr,reg,razr))!=NOINREG){ GetEndLex(terminater); if(razr==r16)tok=tk_reg; else tok=tk_reg32; itok.number=retreg==SKIPREG?reg:retreg; goto nn1; } } nexttok(); convert_type(&sign,&rrettype,&pointr,am32==TRUE?reg:BX); if(rrettype==tk_float||rrettype==tk_double){ if(am32)idxregs[4]=255; doeaxfloatmath(tk_reg32,reg,rrettype==tk_float?0:4); next=0; if(ofsstr){ IDZToReg(ofsstr,reg,razr); free(ofsstr); } break; } while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign){ int hnumber=MultiAssign(razr,USEALLREG,numpointr); // puts("end MultAssign"); if(ofsstr){ free(ofsstr); ofsstr=NULL; } if(reg!=hnumber){ op66(razr); op(0x89); op(0xC0+reg+hnumber*8); //mov reg,AX } next=0; /* if(ofsstr){ IDZToReg(ofsstr,reg,razr); free(ofsstr); }*/ if(am32)idxregs[4]=255; break; } // printf("tok=%d %s\n",tok,itok.name); if(tok==tk_pointer)cpointr(am32==TRUE?reg:BX,numpointr); if(tok==tk_new||tok==tk_delete){ if(tok==tk_new)donew(); else{ dodelete(); terminater=next=0; } if(am32)idxregs[4]=255; if(reg!=AX){ GenRegToReg(reg,AX,(am32+1)*2); } clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif if(ofsstr){ free(ofsstr); ofsstr=NULL; } break; } nn1: if(am32)idxregs[4]=255; if(reg==AX){ if(rrettype==tk_char||rrettype==tk_byte)rettype=doalmath(sign,&ofsstr); else if(rrettype==tk_int||rrettype==tk_word)rettype=do_e_axmath(sign,r16,&ofsstr); else rettype=do_e_axmath(sign,r32,&ofsstr); convert_returnvalue(razr==r16?tk_word:tk_dword,rrettype); } else{ if(rrettype==tk_char||rrettype==tk_byte&®<=BX){ rettype=getintobeg(reg,&ofsstr); if(itok.type!=tp_stopper&&tok!=tk_eof){ dobegmath(reg); rettype=tk_beg; } op66(razr); op(0x0F); if(!sign)op(0xB6); else op(0xBE); op(0xC0+reg*9); } else{ if(rrettype==tk_int||rrettype==tk_word)next=r16; else next=r32; rettype=getintoreg(reg,next,sign,&ofsstr); if(next==r16&&razr==r32){ op66(r32); op(0x0F); if(!sign)op(0xB7); else op(0xBF); op(0xC0+reg*9); } } } next=0; if(ofsstr){ IDZToReg(ofsstr,reg,razr); free(ofsstr); } break; case tk_plusplus: op66(razr); op(0x40+reg); ClearReg(reg); break; case tk_minusminus: op66(razr); op(0x48+reg); ClearReg(reg); break; case tk_cdecl: case tk_pascal: case tk_fastcall: case tk_stdcall: vop=tok; nexttok(); if(tok!=tk_openbracket){ expected('('); FindStopTok(); } case tk_openbracket: //вызов процедуры по адресу в регистре param[0]=0; i=0; switch ( vop ) { case tk_cdecl: case tk_stdcall: i=swapparam(); break; case tk_pascal: doparams(); break; case tk_fastcall: doregparams(); break; default: if(comfile==file_w32)swapparam(); else doparams(); } if(vop!=tk_cdecl)i=0; op66(razr); op(0xFF); op(0xD0+reg); /* CALL reg with stack params */ if(i)CorrectStack(i); clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif break; case tk_swap: getoperand(reg==BX?SI:BX); switch(tok){ case tk_qwordvar: case tk_longvar: case tk_dwordvar: if(razr==r16)swaperror(); i=4; goto swapint; case tk_intvar: case tk_wordvar: i=2; if(razr==r32)swaperror(); swapint: ClearReg(reg); CheckAllMassiv(bufrm,i,&strinf,&itok,reg1,reg2); op66(razr); outseg(&itok,2); op(0x87); op(reg*8+itok.rm); outaddress(&itok); break; case tk_reg32: if(razr==r16)swaperror(); goto swapreg; case tk_reg: if(razr==r32)swaperror(); swapreg: if(reg!=(int)itok.number){ if(RegSwapReg(reg,itok.number,razr)==NOINREG){; op66(razr); if(reg==AX)op(0x90+(unsigned int)itok.number); else if((unsigned int)itok.number==AX)op(0x90+reg); else{ op(0x87); op(0xC0+(unsigned int)itok.number+reg*8); } } else waralreadinitreg(regs[razr/4][reg],regs[razr/4][itok.number]); } break; default: swaperror(); break; } break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: ClearReg(reg); if(am32&&uselea&&tok==tk_plusequals){ if(RegEqualToLea(reg)){ next=0; break; } } if(CheckAddOnly()){ inptr2--; cha2=' '; if(tok==tk_plusequals)tok=tk_plus; else tok=tk_minus; if(reg==EAX)do_e_axmath2(0,razr,0); else doregmath_32(reg,razr,0,&ofsstr); next=0; break; } getoperand(reg==BX?SI:BX); if(itok2.type==tp_opperand&&tok!=tk_number&&tok!=tk_undefofs&&tok!=tk_postnumber)goto defadd; CheckMinusNum(); idrec *rrec; int opost; i=tok; switch(tok){ case tk_postnumber: case tk_undefofs: ii=itok.number; rrec=itok.rec; opost=itok.post; char uname[IDLENGTH]; strcpy(uname,itok.name); if(itok.flag&f_extern)goto addnum; tok=tk_number; case tk_number: ii=doconstdwordmath(); next=0; if(itok.type==tp_opperand){ if(reg==EAX){ sign=ECX; if((tok2==tk_reg||tok2==tk_reg32)&&itok2.number==ECX)sign=EDX; warningreg(regs[razr/2-1][sign]); } if(i==tk_postnumber||i==tk_undefofs){ op66(razr); op(0xB8+reg); // MOV reg,# if(i==tk_postnumber)(postnumflag&f_extern)==0?setwordpost(&itok):setwordext((long *)&ii); else{ if((postnumflag&f_reloc)!=0)AddReloc(); if(i==tk_undefofs)AddUndefOff(2,uname); } razr==r16?outword(ii):outdword(ii); } else MovRegNum(razr,postnumflag&f_reloc,ii,sign); if(sign==EAX)do_e_axmath2(0,razr,0); else doregmath_32(sign,razr,0,&ofsstr); itok.number=sign; goto addreg; } if((postnumflag&f_reloc)==0&&i!=tk_undefofs&&i!=tk_postnumber&&optnumadd(ii,reg,razr,vop))break; addnum: op66(razr); if(reg==AX)op(0x05+vop); else{ op(0x81); op(0xC0+vop+reg); } itok.rec=rrec; itok.post=opost; if(i==tk_postnumber)(postnumflag&f_extern)==0?setwordpost(&itok):setwordext((long *)&ii); else{ if((postnumflag&f_reloc)!=0)AddReloc(); if(i==tk_undefofs)AddUndefOff(2,uname); } razr==r16?outword(ii):outdword(ii); break; case tk_qwordvar: case tk_longvar: case tk_dwordvar: i=4; goto wordadd; case tk_intvar: case tk_wordvar: i=2; if(razr==r32)valueexpected(); wordadd: CheckAllMassiv(bufrm,i,&strinf,&itok,reg1,reg2); op66(razr); outseg(&itok,2); op(0x03+vop); op(reg*8+itok.rm); outaddress(&itok); break; case tk_reg: if(razr==r32)valueexpected(); case tk_reg32: addreg: op66(razr); op(0x01+vop); op(0xC0+reg+(unsigned int)itok.number*8); break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: unsigned char oaddstack; if(reg==EAX){ op66(razr); op(0x50); //push AX addESP+=razr==r16?2:4; warningreg(regs[razr/2-1][EDX]); oaddstack=addstack; addstack=FALSE; } procdo(razr==r16?tk_word:tk_dword); if(itok2.type==tp_opperand){ nexttok(); do_e_axmath2(0,razr,0); next=0; } if(reg==EAX){ addstack=oaddstack; addESP-=razr==r16?2:4; op66(razr); op(0x58+EDX); //pop dx if(vop>0x20){ op66(razr); op(0x90+EDX); //xchg ax,dx } op66(razr); op(0x01+vop); op(0xc0+EDX*8); //add ax,dx } else{ op66(razr); op(0x01+vop); op(0xc0+reg); //add reg,ax } break; case tk_seg: if(razr==r32)valueexpected(); case tk_bytevar: case tk_charvar: case tk_beg: defadd: if(reg==AX){ getintoreg_32(ECX,razr,sign,&ofsstr); doregmath_32(ECX,razr,sign,&ofsstr); sign=CX; //sign исп как пром регистр } else{ do_e_axmath(0,razr,&ofsstr); sign=EAX; } warningreg(regs[razr/2-1][sign]); op66(razr);// OPT reg32,ECX op(0x01+vop); op(0xC0+reg+sign*8); next=0; break; default: valueexpected(); break; } break; case tk_rrequals: vop+=0x08; case tk_llequals: ClearReg(reg); getoperand(am32==TRUE?ECX:reg==BX?SI:BX); CheckMinusNum(); if(tok==tk_number){ ii=doconstlongmath(); next=0; if(itok.type==tp_opperand){ if(reg==ECX)regshifterror(); op(0xB0+CL); op(ii); //mov CL,num dobegmath(CL); warningreg(begs[1]); ConstToReg(ii,CL,r8); goto shiftcl; } if(ii==1){ op66(razr); op(0xD1); op(0xE0+reg+vop); } /* SHL reg,1 */ else if(ii!=0){ if(chip<2&&razr==r16){ op(0xB0+CL); op(ii); //mov CL,num warningreg(begs[1]); ConstToReg(ii,CL,r8); goto shiftcl; } else{ op66(razr); op(0xC1); op(0xE0+reg+vop); /* SHL reg,imm8 */ op(ii); if(cpu<2)cpu=2; } } } else if(reg!=CX){ if(!(itok2.type==tp_stopper&&(tok==tk_beg||tok==reg||tok==tk_reg32)&&itok.number==CL)){ getintobeg(CL,&ofsstr); dobegmath(CL); warningreg(begs[1]); ClearReg(CL); next=0; } shiftcl: op66(razr); op(0xD3); op(0xE0+vop+reg); /* SHL AX,CL */ } else regshifterror(); break; case tk_multequals: ClearReg(reg); getoperand(reg==BX?SI:BX); CheckMinusNum(); if(tok==tk_number){ ii=doconstlongmath(); next=0; if(itok.type==tp_opperand){ if(reg==EAX)sign=ECX; MovRegNum(razr,postnumflag&f_reloc,ii,sign); if(sign==EAX)do_e_axmath2(0,razr,0); else doregmath_32(ECX,razr,0,&ofsstr); ConstToReg(ii,sign,razr); goto mulreg; } i=0; RegMulNum(reg,ii,razr,0,&i,itok.flag); } else{ if(itok2.type==tp_stopper)next=(unsigned char)MulReg(reg,razr); else{ if(reg==AX){ getintoreg_32(ECX,razr,sign,&ofsstr); doregmath_32(ECX,razr,sign,&ofsstr); sign=CX; //sign исп как пром регистр } else{ do_e_axmath(0,razr,&ofsstr); sign=EAX; } mulreg: warningreg(regs[razr/2-1][sign]); ClearReg(sign); op66(razr); outword(0xAF0F); op(0xC0+reg*8+sign); next=0; } } break; case tk_divequals: getoperand(reg==BX?SI:BX); ClearReg(reg); CheckMinusNum(); if(tok==tk_number){ ii=doconstlongmath(); next=0; if(itok.type==tp_opperand){ op66(razr); op(0x50+reg); //push reg addESP+=razr==r16?2:4; MovRegNum(razr,postnumflag&f_reloc,ii,EAX); do_e_axmath2(0,razr,0); ClearReg(AX); goto divreg; } if((vop=caselong(ii))!=NUMNUM&&(!(reg==ECX&&chip<2))){ if(vop!=0){ if(chip<2&&razr==r16){ op(0xB1); op(vop); /* MOV CL,num */ op(0xD3); op(0xE8+reg); // SHR reg,CL warningreg(begs[1]); ClearReg(CX); } else{ op66(razr); op(0xC1); op(0xE8+reg); // SHR reg,num op(vop); } } } else{ if(reg!=EAX){ op66(razr); op(0x90+reg); //xchg reg,AX } DivNum(ii,razr,0); if(reg!=EAX){ op66(razr); op(0x90+reg); //xchg reg,AX warningreg(regs[razr/2-1][EAX]); ClearReg(AX); } } } else if(itok2.type==tp_stopper){ if(reg!=EAX){ op66(razr); op(0x90+reg); //xchg reg,AX } DivMod(0,0,razr,0); next=0; if(reg!=EAX){ op66(razr); op(0x90+reg); //xchg reg,AX warningreg(regs[razr/2-1][EAX]); ClearReg(AX); } } else{ op66(razr); op(0x50+reg); //push reg addESP+=razr==r16?2:4; do_e_axmath(0,razr,&ofsstr); divreg: op66(razr); sign=reg; if(reg==EAX){ sign=ECX; warningreg(regs[razr/2-1][ECX]); ClearReg(CX); } addESP-=razr==r16?2:4; op(0x58+sign); //pop sign op66(razr); op(0x90+sign); //xchg AX,sign op66(razr); op(0xF7); op(0xF0+sign); // DIV reg op66(razr); if(reg!=EAX){ if(optimizespeed){ op(0x89); op(0xC0+reg); //mov reg,AX } else op(0x90+reg); //xchg AX,sign } warningreg(regs[razr/2-1][EAX]); ClearReg(AX); next=0; } break; default: operatorexpected(); break; } if(next)nexttok(); if(terminater==tk_semicolon)seminext(); if(razr==r32&&cpu<3)cpu=3; // puts("return doreg_32"); return rettype; } int optnumadd(unsigned long num,int reg,int razr,int vop) { int nrazr=0; if(num==0){ if(vop==0x20){ //&= ZeroReg(reg,razr); setzeroflag=TRUE; } return TRUE; //+= -= |= ^= } if(vop==8){ //|= if(num<65536&&razr==r32)nrazr=razr=r16; if((unsigned short)num<256&&razr==r16&®<4){ if(reg==AX)op(0x0C); else{ op(0x80); op(0xc8+reg); } op(num); return TRUE; } if(nrazr==r16){ op66(r16); if(reg==AX)op(0x0D); else{ op(0x81); op(0xc8+reg); } outword(num); return TRUE; } } if(num==1){ if(vop==0x28){ //-= op66(razr); op(0x48+reg); setzeroflag=TRUE; return TRUE; } if(vop==0){ //+= op66(razr); op(0x40+reg); setzeroflag=TRUE; return TRUE; } } if(!optimizespeed&&num==2&&((razr==r16&&am32==FALSE)||(razr==r32&&am32))){ if(vop==0x28){ //-= op(0x48+reg); op(0x48+reg); setzeroflag=TRUE; return TRUE; } if(vop==0){ //+= op66(razr); op(0x40+reg); op66(razr); op(0x40+reg); setzeroflag=TRUE; return TRUE; } } if((razr==r16&&(unsigned short)num==0xffff)|| (razr==r32&&num==0xffffffff)){ if(vop==0x28){ //-= op66(razr); op(0x40+reg); setzeroflag=TRUE; return TRUE; } if(vop==0){ //+= op66(razr); op(0x48+reg); setzeroflag=TRUE; return TRUE; } if(vop==0x20)return TRUE; //&= if(vop==0x30){ //^= if(optimizespeed&&(chip==5||chip==6))return FALSE; op66(razr); op(0xF7); op(0xD0+reg); //Not reg setzeroflag=FALSE; return TRUE; } } if(vop==0x20){ //&= if(num>=0xFFFF0000&&razr==r32)nrazr=razr=r16; if(razr==r16&&(unsigned short)num>=0xFF00&®<4){ if(reg==AL)op(0x24); else{ op(128); op(0xE0+reg); } op(num); return TRUE; } if(nrazr==r16){ op66(r16); if(reg==AX)op(0x25); else{ op(129); op(0xE0+reg); } outword(num); return TRUE; } } if(!optimizespeed&&(razr==r16&&(unsigned short)num==0xfffe&&am32==FALSE)|| (razr==r32&&num==0xfffffffe&&am32)){ if(vop==0x28){ //-= op(0x40+reg); op(0x40+reg); setzeroflag=TRUE; return TRUE; } if(vop==0){ //+= op(0x48+reg); op(0x48+reg); setzeroflag=TRUE; return TRUE; } } if(short_ok(num,razr/2-1)){ op66(razr); op(0x83); op(0xC0+vop+reg); op(num); setzeroflag=TRUE; return TRUE; } return FALSE; } int dobeg(int beg,int terminater) { unsigned char next=1; int vop=0,i=0,sign=0; int rettype=tk_beg,pointr=0;; int rrettype=tk_byte; int numpointr=0; char *ofsstr=NULL; nexttok(); switch(tok){ case tk_assign: if(!((tok2==tk_reg||tok2==tk_reg32||tok2==tk_beg)&&ScanTok3()==terminater)){ ofsstr=GetLecsem(terminater); } else{ nexttok(); if(RegToReg(beg,itok.number,r8)==NOINREG)goto nn1; waralreadinitreg(begs[itok.number],begs[beg]); break; } if(ofsstr){ int retreg; if((retreg=CheckIDZReg(ofsstr,beg,r8))!=NOINREG){ GetEndLex(terminater); tok=tk_beg; itok.number=retreg==SKIPREG?beg:retreg; goto nn1; } } nexttok(); convert_type(&sign,&rrettype,&pointr,am32==TRUE?(beg>3?beg-4:beg):BX); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign){ int hnumber=MultiAssign(r8,(beg>3?beg-4:beg),numpointr); if(ofsstr){ free(ofsstr); ofsstr=NULL; } if(beg!=hnumber){ op(0x88); op(0xC0+beg+hnumber*8); //mov beg,AL } next=0; if(ofsstr){ IDZToReg(ofsstr,beg,r8); free(ofsstr); } break; } if(tok==tk_pointer)cpointr(am32==TRUE?(beg>3?beg-4:beg):BX,numpointr); nn1: if(beg==AL){ if(rrettype==tk_char||rrettype==tk_byte)rettype=doalmath(sign,&ofsstr); else if(rrettype==tk_int||rrettype==tk_word)rettype=do_e_axmath(sign,r16,&ofsstr); else rettype=do_e_axmath(sign,r32,&ofsstr); next=0; } else{ if(rrettype==tk_char||rrettype==tk_byte||beg>BL){ rettype=getintobeg(beg,&ofsstr); if(itok.type!=tp_stopper&&tok!=tk_eof){ dobegmath(beg); rettype=tk_beg; } } else{ if(rrettype==tk_int||rrettype==tk_word)next=r16; else next=r32; rettype=getintoreg(beg,next,sign,&ofsstr); } next=0; } if(ofsstr){ IDZToReg(ofsstr,beg,r8); free(ofsstr); } break; case tk_plusplus: op(0xFE); op(0xC0+beg); ClearReg(beg>3?beg%4:beg); break; case tk_minusminus: op(0xFE); op(0xC8+beg); ClearReg(beg>3?beg%4:beg); break; case tk_swap: getoperand(beg==BL||beg==BH?SI:BX); switch(tok){ case tk_charvar: case tk_bytevar: CheckAllMassiv(bufrm,1,&strinf); outseg(&itok,2); op(0x86); op(beg*8+itok.rm); outaddress(&itok); KillVar(itok.name); ClearReg(beg>3?beg-4:beg); break; case tk_beg: if(beg!=(int)itok.number){ if(RegSwapReg(beg,itok.number,r8)==NOINREG){ op(0x86); op(0xC0+(unsigned int)itok.number+beg*8); } else waralreadinitreg(begs[beg],begs[itok.number]); } break; default: swaperror(); break; } break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: ClearReg(beg>3?beg%4:beg); if(CheckAddOnly()){ inptr2--; cha2=' '; if(tok==tk_plusequals)tok=tk_plus; else tok=tk_minus; if(beg==AL)doalmath2(0); else dobegmath(beg); next=0; break; } getoperand(beg==BL||beg==BH?SI:BX); if(itok2.type==tp_opperand&&tok!=tk_number){ if(beg==AL){ getintobeg(CL,&ofsstr); dobegmath(CL); sign=CL; //sign исп как пром регистр } else{ doalmath(0,&ofsstr); sign=EAX; } warningreg(begs[sign]); op(0x00+vop); op(0xC0+beg+sign*8); next=0; break; } switch(tok){ case tk_number: i=doconstlongmath(); next=0; if(i==0&&(vop==0||vop==0x28||vop==8))break; if(i==255&&vop==0x20)break; if(beg==AL)op(0x04+vop); else{ op(0x80); op(0xC0+vop+beg); } op(i); break; case tk_qwordvar: i+=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_wordvar: case tk_intvar: i++; case tk_charvar: case tk_bytevar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0x02+vop); op(beg*8+itok.rm); outaddress(&itok); break; case tk_beg: op(0x00+vop); op(0xC0+beg+(unsigned int)itok.number*8); break; case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: case tk_ID: case tk_id: op66(r16); i=beg<4?beg:beg-4; op(0x50+i); addESP+=2; warningreg(regs[0][i]); procdo(tk_byte); if(itok2.type==tp_opperand){ nexttok(); doalmath2(0); next=0; } addESP-=2; op66(r16); op(0x58+(i!=AX?i:CX)); if(i!=AX){ op(0x00+vop); op(0xc0+beg); } else{ if(vop>0x20){ op(0x86); op(0xC0+CL+beg); //xchg al,cl } op(0x00+vop); op(0xc0+CL*8+beg); } break; case tk_reg: if((unsigned int)itok.number3?beg%4:beg); if(itok2.type==tp_stopper&&tok==tk_number){ if((unsigned int)itok.number==1){ op(0xD0); op(0xE0+beg+vop); } /* SHL beg,1 */ else if((unsigned int)itok.number!=0){ if(chip<2)goto shiftbeg; else{ op(0xc0); op(0xe0+beg+vop); op((unsigned int)itok.number); } } } else{ shiftbeg: if(beg!=CL){ if(itok2.type==tp_stopper&&tok==tk_beg&&itok.number==CL){ op(0xD2); op(0xE0+vop+beg); /* SHL beg,CL */ } else{ ClearReg(CL); getintobeg(CL,&ofsstr); dobegmath(CL); next=0; warningreg(begs[1]); op(0xD2); op(0xE0+vop+beg); /* SHL beg,CL */ } } else regshifterror(); } break; default: operatorexpected(); break; } if(next)nexttok(); if(terminater==tk_semicolon)seminext(); return rettype; } void doseg(int seg) { unsigned char next=1; int numpointr=0; char *ofsstr=NULL; if(seg==CS)preerror("CS not used for destention"); if(seg==FS||seg==GS)if(cpu<3)cpu=3; if(seg==SS)RestoreStack(); nexttok(); KillVar(segs[seg]); if(tok==tk_assign){ nexttok(); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign){ itok.number=MultiAssign(r16,USEALLREG,numpointr); if(ofsstr){ free(ofsstr); ofsstr=NULL; } goto getfromreg; } if(tok==tk_pointer)cpointr(am32==TRUE?EAX:BX,numpointr); if(itok2.type!=tp_opperand){ switch(tok){ case tk_reg: getfromreg: op(0x8E); op(0xC0+seg*8+(unsigned int)itok.number); /* MOV seg,reg */ break; case tk_intvar: case tk_wordvar: case tk_longvar: case tk_dwordvar: case tk_qwordvar: CheckAllMassiv(bufrm,2,&strinf); op66(r16); outseg(&itok,2); op(0x8E); op(seg*8+itok.rm); outaddress(&itok); /* MOV seg,[wordvar] */ break; case tk_seg: if(optimizespeed==FALSE||(regoverstack&&chip>2)){ PushSeg((unsigned int)itok.number); PopSeg(seg); break; } goto segax; case tk_number: if(regoverstack&&chip>1){ // op66(r16); if(short_ok(itok.number)&&(itok.flag&f_reloc)==0){ op(0x6A); op(itok.number); } else{ op(0x68); if((itok.flag&f_reloc)!=0)AddReloc(); if(am32)outdword(itok.number); else outword(itok.number); } PopSeg(seg); if(cpu<2)cpu=2; break; } goto segax; default: goto segax; } } else{ segax: do_e_axmath(0,r16,&ofsstr); op(0x8E); /* MOV SEG,AX */ op(0xC0+seg*8); next=0; } } else if(tok==tk_swap){ getoperand(); switch(tok){ case tk_intvar: case tk_wordvar: KillVar(itok.name); op66(r16); op(0x8C); op(0xC0+seg*8); /* MOV AX,SEG */ CheckAllMassiv(bufrm,2,&strinf); op66(r16); outseg(&itok,2); op(0x87); op(itok.rm); outaddress(&itok); /* XCHG AX,[word] */ op66(r16); op(0x8E); op(0xC0+seg*8); /* MOV seg,AX */ break; case tk_seg: KillVar(segs[itok.number]); PushSeg(seg); PushSeg(itok.number); PopSeg(seg); PopSeg(itok.number); break; default: preerror("Only int, word variables valid for segment register ><"); break; } } else segoperror(); if(next)nextseminext(); else seminext(); } void PushSeg(int seg) { switch(seg){ case DS: op(0x1E); break; case CS: op(0x0E); break; case SS: op(0x16); break; case ES: op(0x06); break; case FS: outword(0xA00F); if(cpu<3)cpu=3; break; case GS: outword(0xA80F); if(cpu<3)cpu=3; break; } } void PopSeg(int seg) { switch(seg){ case DS: op(0x1F); break; case SS: op(0x17); break; case ES: op(0x07); break; case FS: outword(0xA10F); if(cpu<3)cpu=3; break; case GS: outword(0xA90F); if(cpu<3)cpu=3; break; } } // =============== doregmath_32(), dobegmath() =============== void doregmath_32(int reg,int razr,int sign,char **ofsstr,int fdiv) // math done is on all regs except AX // all other registers preserved { int vop,i,optnum,negflag=FALSE; while(itok.type!=tp_stopper&&tok!=tk_eof){ if(negflag){ NegReg(razr,reg); negflag=FALSE; } i=vop=0; optnum=FALSE; #ifdef OPTVARCONST CheckConstVar3(&tok2,&itok2,razr); if(tok2==tk_number)calcnumber=TRUE; #endif if(uselea){ if(razr==r32){ if(Reg32ToLea2(reg))continue; //оптимизация сложения 32-битных регистров в LEA } else if(Reg16ToLea2(reg))continue; if(itok.type==tp_stopper||tok==tk_eof)break; } if(tok2==tk_number)optnum=OptimNum(); switch(tok){ case tk_xor: vop+=0x08; case tk_minus: vop+=0x08; case tk_and: vop+=0x18; case tk_or: vop+=0x08; case tk_plus: if(optnum==FALSE)getoperand(reg==BX?SI:BX); else tok=tk_number; switch(tok){ case tk_number: if((itok.flag&f_reloc)==0&&optnumadd(itok.number,reg,razr,vop))break; case tk_postnumber: case tk_undefofs: op66(razr); op(0x81); op(0xC0+vop+reg); if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); else if((itok.flag&f_reloc)!=0)AddReloc(); razr==r16?outword((unsigned int)itok.number):outdword(itok.number); break; case tk_apioffset: op66(razr); op(0x81); op(0xC0+vop+reg); AddApiToPost(itok.number); break; case tk_doublevar: i=4; case tk_floatvar: Float2reg32(EAX,i); itok.number=EAX; warningreg(regs[1][EAX]); goto defreg32; case tk_bits: int vops,reg2s; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; if(vops=tk_charvar&&tok2<=tk_doublevar&&itok2.npointr==0){ if(CheckConstVar(&itok2)){ tok2=tk_number; calcnumber=TRUE; } } #endif if(tok2==tk_number)optnum=OptimNum(); int oldtok=tok; switch(tok){ case tk_xor: vop+=0x08; case tk_minus: vop+=0x08; case tk_and: vop+=0x18; case tk_or: vop+=0x08; case tk_plus: if(optnum==FALSE)getoperand(beg==BL||beg==BH?SI:BX); else{ tok=tk_number; optnum=FALSE; } switch(tok){ case tk_number: if(itok.number==0&&oldtok!=tk_and)break; else if(itok.number==1){ if(oldtok==tk_plus){ op(0xFE); op(0xC0+beg); break; } if(oldtok==tk_minus){ op(0xFE); op(0xC8+beg); break; } } else if((unsigned char)itok.number==0xff){ if(oldtok==tk_minus){ op(0xFE); op(0xC0+beg); break; } if(oldtok==tk_plus){ op(0xFE); op(0xC8+beg); break; } } op(0x80); op(0xC0+vop+beg); op((unsigned int)itok.number); break; case tk_bits: int vops,reg2s; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; if(i<=8)vops=r8; reg2s=CL; if(beg==CL)reg2s=BL; bits2reg(reg2s,vops); if(vops==r64)vops=r32; warningreg(vops==r8?begs[reg2s]:regs[vops/2-1][reg2s]); itok.number=reg2s; case tk_beg: op(0x00+vop); op(0xC0+beg+(unsigned int)itok.number*8); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_bytevar: case tk_charvar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0x02+vop); op(beg*8+itok.rm); outaddress(&itok); break; case tk_postnumber: case tk_reg: case tk_rmnumber: begworderror(); break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc:// begcallerror(); break; case tk_declare: procdo(tk_byte); if(beg!=AL){ op(0x00+vop); op(0xc0+beg); } break; default: valueexpected(); break; } break; case tk_xorminus: vop+=0x10; case tk_andminus: vop+=0x18; case tk_orminus: vop+=0x08; getoperand(beg==BL||beg==BH?SI:BX); if(tok==tk_number){ itok.number=-itok.number; op(0x80); op(0xC0+vop +beg); op((unsigned int)itok.number); } else negregerror(); break; case tk_rr: vop=8; case tk_ll: nexttok(); if(tok==tk_number){ if((unsigned int)itok.number==1){ if(vop==0){ op(2); op(0xC0+9*beg); // ADD reg,reg } else{ op(0xD0); op(0xE8+beg); /* SHR reg,1 */ } } else if((unsigned int)itok.number!=0){ if(chip<2)begmathoperror(); else{ op(0xc0); op(0xe0+beg+vop); // SHL reg,imm8 op((unsigned int)itok.number); if(cpu<2)cpu=2; } } } else if(tok==tk_beg&&itok.number==CL&&beg!=CL){ op(0xD2); op(0xE0+beg+vop); // SHL xXX,CL } else begmathoperror(); break; case tk_multminus: negflag=TRUE; case tk_mult: if(optnum==FALSE)getoperand(beg==BL||beg==BH?SI:BX); else{ tok=tk_number; optnum=FALSE; } if(negflag&&tok==tk_number){ itok.number=-itok.number; negflag=FALSE; } switch(tok){ case tk_number: itok.number&=255; switch((unsigned int)itok.number){ case 0: // beg * 0 = MOV beg,0 outword(0x00B0+beg); case 1: break; //beg*1=beg case 2: op(0); op(0xC0+9*beg); // beg * 2 = ADD beg,beg break; default: vop=caselong(itok.number); if(vop!=NUMNUM){ if(chip<1)begmathoperror(); else{ op(0xc0); op(0xe0+beg); //SHL beg,num op(vop); if(cpu<1)cpu=1; } } else begmathoperror(); } break; default: begmathoperror(); break; } break; case tk_divminus: case tk_modminus: case tk_div: case tk_mod: case tk_rrminus: case tk_llminus: begmathoperror(); break; default: operatorexpected(); break; } #ifdef OPTVARCONST calcnumber=FALSE; #endif nexttok(); ClearReg(beg%4); } } // ============= getintoreg_32(), getintobeg() ============ int getintoreg_32(int reg,int razr,int sign,char **ofsstr,int useloop) // get into word reg (except AX) with enum { int negflag=0,next=1,i=0; int swap=0,oflag=0; unsigned long holdnumber=0; int reg1=idxregs[0],reg2=idxregs[1]; int rettype=tk_reg; int loop=0,otok; // printf("line %d tok=%d %s\n",linenumber,tok,itok.name); if(!am32){ if(reg==idxregs[1]||reg==idxregs[2]){ reg1=reg; if(reg==idxregs[1])reg2=idxregs[0]; } } else{ reg1=reg; if(reg==idxregs[1])reg2=idxregs[0]; } if(tok==tk_minus){ if(CheckMinusNum()==FALSE){ negflag=1; getoperand(am32==FALSE?BX:reg); } } loopswitch: if(uselea){ if(razr==r32){ if(cpu<3)cpu=3; if(Reg32ToLea(reg)){ return tk_reg; } } else if(Reg16ToLea(reg)){ return tk_reg; } } loopswitch1: #ifdef OPTVARCONST CheckConstVar3(&tok,&itok,razr); if(tok==tk_number)calcnumber=TRUE; #endif otok=tok; // printf("reg=%d tok=%d\n",reg,tok); switch(tok){ case tk_number: if(useloop==FALSE)MovRegNum(razr,itok.flag&f_reloc,itok.number,reg); else{ holdnumber=CalcNumber(sign); if(loop==0)oflag=postnumflag; else oflag^=postnumflag; loop++; if(tok==tk_mult){ nexttok(); swap=1; goto loopswitch1; } if(tok==tk_plus&&tok2==tk_postnumber){ nexttok(); // getoperand(am32==TRUE?EAX:BX); goto loopswitch1; } MovRegNum(razr,oflag&f_reloc,holdnumber,reg); next=0; } break; case tk_postnumber: case tk_undefofs: if(!swap){ op66(razr); op(0xB8+reg); /* MOV AX,# */ swap=1; } if(tok==tk_undefofs){ AddUndefOff(2,itok.name); // AddUndefOff(0,itok.name); // itok.flag=0; //new 07.07.04 23:57 } else (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(useloop==FALSE)holdnumber=itok.number; else{ tok=tk_number; holdnumber+=doconstdwordmath(); if(otok!=tk_postnumber){ if(loop==0)oflag=postnumflag; else oflag^=postnumflag; loop++; } if(tok==tk_plus&&tok2==tk_postnumber){ nexttok(); goto loopswitch1; } swap=0; next=0; } if(useloop&&(oflag&f_reloc))AddReloc(); if(razr==r16)outword(holdnumber); else outdword(holdnumber); ClearReg(reg); break; case tk_apioffset: op66(razr); op(0xB8+reg); /* MOV AX,# */ AddApiToPost(itok.number); ClearReg(reg); break; case tk_rmnumber: CheckAllMassiv(bufrm,itok.size,&strinf,&itok,reg1,reg2); if((am32&&itok.rm==reg&®!=EBP&®!=ESP)||(am32==0&®==itok.rm&& (reg==SI||reg==DI||reg==BX)))break; op66(razr); op67(itok.sib==CODE16?r16:r32); if(itok.post==0)outseg(&itok,2); op(0x8D); // LEA reg,[rm] op(reg*8+itok.rm); if(itok.post!=0&&itok.post!=UNDEF_OFSET){ if((itok.flag&f_extern)==0){ unsigned int ooutptr=outptr; if(am32&&itok.rm==rm_sib)outptr++; setwordpost(&itok); outptr=ooutptr; } else setwordext(&itok.number); } if(useloop==FALSE)outaddress(&itok); else{ ITOK oitok; oitok=itok; tok=tk_number; itok.rm=tk_dword; oitok.number=doconstdwordmath(); outaddress(&oitok); next=0; } ClearReg(reg); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=4; dwordvar: CheckAllMassiv(bufrm,i,&strinf,&itok,reg1,reg2); op66(razr); outseg(&itok,2); op(0x8B); op(reg*8+itok.rm); outaddress(&itok); ClearReg(reg); break; case tk_intvar: case tk_wordvar: i=2; if(razr==r16)goto dwordvar; CheckAllMassiv(bufrm,2,&strinf,&itok,reg1,reg2); if(tok==tk_wordvar&&optimizespeed&&chip>3&&chip<7&&RmEqualReg(reg,itok.rm,itok.sib)==FALSE){ ZeroReg(reg,r32); op66(r16); outseg(&itok,2); //mov reg,var op(0x8B); } else{ op66(r32); outseg(&itok,3); //movxx reg,var op(0x0F); op(tok==tk_wordvar?0xB7:0xBF); } op(reg*8+itok.rm); outaddress(&itok); ClearReg(reg); break; case tk_doublevar: i=4; case tk_floatvar: Float2reg32(reg,i,reg1,reg2); ClearReg(reg); break; case tk_bytevar: case tk_charvar: if(chip>2||razr==r32){ CheckAllMassiv(bufrm,1,&strinf,&itok,reg1,reg2); if(reg<=EBX&&tok==tk_bytevar&&optimizespeed&&chip>3&&chip<7&&RmEqualReg(reg,itok.rm,itok.sib)==FALSE){ ZeroReg(reg,razr); outseg(&itok,2); op(0x8A); } else{ op66(razr); outseg(&itok,3); op(0xf); if(tok==tk_bytevar)op(0xb6); else op(0xbe); } op(reg*8+itok.rm); // MOVZX regL,[byte] outaddress(&itok); ClearReg(reg); break; } if(reg<=BX){ if(reg==AX&&itok.rm==rm_d16&&itok.sib==CODE16){ outseg(&itok,1); op(0xA0); // MOV AL,[byte] outword((unsigned int)itok.number); } else{ CheckAllMassiv(bufrm,1,&strinf,&itok,reg1,reg2); outseg(&itok,2); op(0x8A); op(reg*8+itok.rm); // MOV regL,[byte] outaddress(&itok); } ClearReg(reg); op(0x30); op(0xC0+(reg+4)*9); // XOR regH,regH } else regbyteerror(); break; case tk_reg: if(razr==r32){ if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=itok.number; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(r16); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ itok.number=0; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif } if(optimizespeed&&chip>3&&chip<7&®!=(int)itok.number){ ZeroReg(reg,r32); op(0x89); op(0xC0+reg+(unsigned int)itok.number*8); } else{ op66(r32); outword(0xB70F); op(0xC0+reg*8+(unsigned int)itok.number); } RegToReg(reg,itok.number,r32); break; } case tk_reg32: if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=itok.number; reg2=tok==tk_reg32?r32:r16; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(reg2); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ itok.number=0; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif } if(reg!=(int)itok.number){ op66(razr); op(0x89); op(0xC0+reg+(unsigned int)itok.number*8); RegToReg(reg,itok.number,r32); } break; case tk_bits: int vops; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; bits2reg(reg,(razr2||razr==r32){ if(optimizespeed&&chip>3&&chip<7&®<4&®!=(int)(itok.number%4)){ ZeroReg(reg,razr); op(0x88); op(0xC0+reg+(unsigned int)itok.number*8); // MOV regL,beg } else{ op66(razr); outword(0xb60f); op(0xC0+reg*8+(unsigned int)itok.number); // MOVZX regL,beg } } else if(reg>BX)regbyteerror(); else{ op(0x88); op(0xC0+reg+(unsigned int)itok.number*8); // MOV regL,beg op(0x30); op(0xC0+(reg+4)*9); // XOR regH,regH } ClearReg(reg); break; case tk_at: getoperand(am32==FALSE?BX:reg); i++; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: if(itok.flag&f_retproc)rettype=(itok.flag&f_retproc)/256+tk_overflowflag-1; if((!i)||macros(razr==r16?tk_word:tk_dword)==0)procdo(razr==r16?tk_word:tk_dword); itok.number=0; tok=(razr==r16?tk_reg:tk_reg32); if(*ofsstr!=NULL){ free(*ofsstr); ofsstr=NULL; } // printf("tok=%d num=%d tok2=%d\n",tok,itok.number,tok2); goto loopswitch; // break; case tk_string: op66(razr); op(0xB8+reg); if(razr==r16){ if(am32)dwordvalexpected(); outword(addpoststring()); } else outdword(addpoststring()); ClearReg(reg); break; default: valueexpected(); break; } #ifdef OPTVARCONST calcnumber=FALSE; #endif if(negflag)NegReg(razr,reg); if(swap){ negflag=0; RegMulNum(reg,holdnumber,razr,0,&negflag,oflag); ClearReg(reg); } if(next)nexttok(); // printf("tok=%d num=%d tok2=%d\n",tok,itok.number,tok2); return rettype; } int getintobeg(int beg,char **ofsstr) // get into beg (CL,DL,BL not others) with enum { int negflag=0,i=0; int rettype=tk_beg; if(tok==tk_minus){ if(CheckMinusNum()==FALSE){ negflag=1; getoperand(am32==TRUE?(beg>3?beg-4:beg):BX); } } #ifdef OPTVARCONST if(tok>=tk_charvar&&tok<=tk_doublevar&&itok.npointr==0){ // printf("type1=%d type2=%d\n",itok.type,itok2.type); if(CheckConstVar(&itok)){ tok=tk_number; calcnumber=TRUE; } } #endif switch(tok){ case tk_number: op(0xB0+beg); i=(int)doconstlongmath(); op(i); ConstToReg(i,beg,r8); break; case tk_rmnumber: CheckAllMassiv(bufrm,itok.size,&strinf); op66(r16); op67(itok.sib==CODE16?r16:r32); if(itok.post==0)outseg(&itok,2); op(0x8D); // LEA reg,[rm] op(beg*8+itok.rm); if(itok.post!=0&&itok.post!=UNDEF_OFSET){ if((itok.flag&f_extern)==0){ unsigned int ooutptr=outptr; if(am32&&itok.rm==rm_sib)outptr++; setwordpost(&itok); outptr=ooutptr; } else setwordext(&itok.number); } outaddress(&itok); ClearReg(beg%4); break; case tk_postnumber: op66(r16); op(0xB8+beg); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); outword((unsigned int)itok.number); nexttok(); ClearReg(beg%4); break; case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: i++; case tk_charvar: case tk_bytevar: i++; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0x8A); op(beg*8+itok.rm); outaddress(&itok); nexttok(); ClearReg(beg%4); break; case tk_doublevar: i=4; case tk_floatvar: Float2reg32((beg<4?beg:beg-4),i); if(beg>3){ op(0x88); op(0xC0+beg+8*(beg-4)); } nexttok(); ClearReg(beg%4); break; case tk_bits: int vops; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; if(i<=8)vops=r8; if(beg>BX&&vops!=r8){ op66(vops==r64?r32:vops); op(0x50); if(ESPloc&&am32&&itok.segm==SS)itok.number+=4; addESP+=vops==r16?2:4; bits2reg(AX,vops); op(0x88); op(0xC0+beg); op66(vops==r64?r32:vops); addESP-=vops==r16?2:4; op(0x58); } else bits2reg(beg,vops); nexttok(); break; case tk_beg: if(beg!=(int)itok.number){ op(0x88); op(0xC0+beg+(unsigned int)itok.number*8); RegToReg(beg,itok.number,r8); } nexttok(); break; case tk_reg32: case tk_reg: if(begrm; if(outtok->sib==CODE16){ if(rm==rm_d16){ if(outtok->post==UNDEF_OFSET){ AddUndefOff(2,outtok->name); outtok->post=0; } outword(outtok->number); } else{ rm&=rm_mod11; if(rm==rm_mod11)internalerror(badadr); else if(rm==rm_mod10){ if(outtok->post==UNDEF_OFSET){ AddUndefOff(2,outtok->name); outtok->post=0; } outword(outtok->number); } else if(rm!=rm_mod00)op(outtok->number); } } else{ if(rm==rm_d32){ if(outtok->post==UNDEF_OFSET){ AddUndefOff(2,outtok->name); outtok->post=0; } outdword(outtok->number); } else{ if((rm&7)==rm_sib){ op(outtok->sib); if(rm==4&&(outtok->sib&7)==5){ if(outtok->post==UNDEF_OFSET){ AddUndefOff(2,outtok->name); outtok->post=0; } outdword(outtok->number); } } rm&=rm_mod11; if(rm==rm_mod11)internalerror(badadr); else if(rm==rm_mod10){ if(outtok->post==UNDEF_OFSET){ AddUndefOff(2,outtok->name); outtok->post=0; } outdword(outtok->number); } else if(rm==rm_mod01)op(outtok->number); } } } /*-----------------05.01.00 23:37------------------- Обработка float операции с переменными типа float --------------------------------------------------*/ int dofloatvar(int addop,int retrez,int terminater) { unsigned char next=1, getfromEAX=0; unsigned int vop=0,rettype=tk_float,posiblret=tk_float,sign=0; char *wbuf,*rbuf; ITOK wtok; SINFO wstr; int pointr=0; int razr,i=0; int type=tk_floatvar; if(addop){ rettype=posiblret=tk_double; razr=8; type=tk_doublevar; } wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; KillVar(itok.name); char *ofsstr=NULL; nexttok(); switch(tok){ case tk_assign: //= getoperand(am32==TRUE?EAX:BX); convert_type((int *)&sign,(int *)&rettype,&pointr); if(tok2==tk_assign){ MultiAssignFloat(type); next=0; goto getfromeax; } CheckMinusNum(); if(itok2.type==tp_opperand){ //составное if(tok==tk_number){ //проверка и суммирование чисел if(OnlyNumber(rettype==tk_float?2:3)){ next=0; itok.flag=(unsigned char)postnumflag; itok.rm=rettype; goto numbertovar; } } getfromEAX=1; if(rettype==tk_char||rettype==tk_byte)doalmath(sign,&ofsstr); else if(rettype==tk_int||rettype==tk_word)do_e_axmath(sign,r16,&ofsstr); else if(rettype==tk_long||rettype==tk_dword)do_e_axmath(sign,r32,&ofsstr); else goto labl1; } else{ switch(tok){ case tk_number: numbertovar: if(rettype==tk_float){ if(itok.rm==tk_double)itok.fnumber=itok.dnumber; else if(itok.rm!=tk_float){ float temp=itok.number; *(float *)&itok.number=temp; } } else{ if(itok.rm==tk_float)itok.dnumber=itok.fnumber; else if(itok.rm!=tk_double)itok.dnumber=itok.lnumber; } CheckAllMassiv(wbuf,razr,&wstr,&wtok); for(i=0;i<2;i++){ op66(r32); if((itok.flag&f_reloc)==0&&itok.number==0){ outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); } else if(regoverstack&&short_ok(itok.number,TRUE)&&(itok.flag&f_reloc)==0){ op(0x6A); op(itok.number); //push short number op66(r32); outseg(&wtok,2); op(0x8f); op(wtok.rm); outaddress(&wtok); } else{ outseg(&wtok,2); op(0xC7); //mov word[],number op(wtok.rm); outaddress(&wtok); if((itok.flag&f_reloc)!=0)AddReloc(); outdword(itok.number); } if(i==1||rettype==tk_float)break; itok.lnumber>>=32; wtok.number+=4; compressoffset(&wtok); } break; case tk_doublevar: case tk_floatvar: if(tok!=type)goto labl1; ITOK w1tok; char *w1buf; w1buf=bufrm; bufrm=NULL; w1tok=itok; SINFO w1str; w1str=strinf; strinf.bufstr=NULL; getinto_e_ax(0,tok==tk_floatvar?tk_dwordvar:tk_qwordvar,&w1tok,w1buf,&w1str,r32); if(tok==tk_doublevar){ if((wtok.rm==rm_d16&&wtok.sib==CODE16)||(wtok.rm==rm_d32&&wtok.sib==CODE32)){ op66(r32); outseg(&wtok,1); op(0xA3); // MOV [dword],EAX if(am32)outdword(wtok.number); else outword(wtok.number); } else{ CheckAllMassiv(wbuf,4,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0x89); op(wtok.rm); // MOV [rmdword],EAX outaddress(&wtok); } itok.number+=4; compressoffset(&itok); wtok.number+=4; compressoffset(&wtok); ITOK w1tok; char *w1buf; w1buf=bufrm; bufrm=NULL; w1tok=itok; SINFO w1str; w1str=strinf; strinf.bufstr=NULL; getinto_e_ax(0,tk_qwordvar,&w1tok,w1buf,&w1str,r32); } getfromEAX=1; break; default: labl1: if((i=doeaxfloatmath(tk_fpust))==tk_fpust||i==tk_double){ getfromEAX=0; if(retrez==tk_floatvar||retrez==tk_doublevar){ CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } else retrez=tk_fpust; } else getfromEAX=1; next=0; } } if(getfromEAX){ getfromeax: retrez=tk_reg32; convert_returnvalue(posiblret,rettype); if((wtok.rm==rm_d16&&wtok.sib==CODE16)||(wtok.rm==rm_d32&&wtok.sib==CODE32)){ op66(r32); outseg(&wtok,1); op(0xA3); // MOV [dword],EAX if(am32)outdword(wtok.number); else outword(wtok.number); } else{ CheckAllMassiv(wbuf,4,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0x89); op(wtok.rm); // MOV [rmdword],EAX outaddress(&wtok); } } break; case tk_minusminus: vop=0x28; case tk_plusplus: incvar: outword(0xe8d9); //fld1 CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fadd var op(0xd8+addop); op(wtok.rm+vop); outaddress(&wtok); if(retrez==tk_floatvar||retrez==tk_doublevar){ outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } break; case tk_divequals: vop+=0x10; case tk_minusequals: vop+=0x20; case tk_multequals: vop+=8; case tk_plusequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper){ if(tok==tk_number){ if((itok.rm==tk_float&&itok.fnumber==1.0)|| (itok.rm==tk_double&&itok.dnumber==1.0)|| (itok.rm!=tk_float&&itok.rm!=tk_double&&itok.lnumber==1)){ if(vop==0||vop==0x28)goto incvar; break; } if((itok.rm==tk_float&&itok.fnumber==0.0)|| (itok.rm==tk_double&&itok.dnumber==0.0)||itok.lnumber==0){ switch(vop){ case 0x38: DevideZero(); break; case 8: outword(0xEED9); //FLDZ if(retrez==tk_floatvar||retrez==tk_doublevar){ CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } break; } break; } } } if(itok2.type==tp_opperand){ doeaxfloatmath(tk_fpust); endequals: next=0; endequals1: CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fsubr var op(0xd8+addop); op(wtok.rm+vop); outaddress(&wtok); if(retrez==tk_floatvar||retrez==tk_doublevar){ outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } } else{ switch(tok){ case tk_number: if(rettype==tk_float){ if(itok.rm==tk_double)itok.fnumber=itok.dnumber; else if(itok.rm!=tk_float){ float temp=itok.number; *(float *)&itok.number=temp; } } else{ if(itok.rm==tk_float)itok.dnumber=itok.fnumber; else if(itok.rm!=tk_double)itok.dnumber=itok.lnumber; } if(vop==0x38){ // div 22.12.05 22:10 vop=8; //mult if(itok.rm==tk_float)itok.fnumber=1/itok.fnumber; else itok.dnumber=1/itok.dnumber; } op66(r32); op(0xD9+addop); op((am32==FALSE?0x06:0x05)); //fld AddFloatConst(itok.lnumber,rettype); outword(0); if(am32)outword(0); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fsubr var op(0xd8+addop); op(wtok.rm+vop); outaddress(&wtok); if(retrez==tk_floatvar||retrez==tk_doublevar){ outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } break; case tk_longvar: sign=2; case tk_floatvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,2); //fld val or fild val op(0xd9+sign); op(itok.rm); outaddress(&itok); goto endequals1; case tk_qwordvar: sign=2; i=0x28; case tk_doublevar: CheckAllMassiv(bufrm,8,&strinf); outseg(&itok,2); //fldq val or fild val op(0xdd+sign); op(itok.rm+i); outaddress(&itok); goto endequals1; case tk_dwordvar: CheckInitBP(); op66(r32); //push 0L outword(0x6a); if(ESPloc&&am32&&itok.segm==SS)itok.number+=4; addESP+=4; CheckAllMassiv(bufrm,4,&strinf); op66(r32); //push var outseg(&itok,2); op(0xFF); op(itok.rm+0x30); outaddress(&itok); if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=4; addESP+=4; fildq_stack(); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fsubr var op(0xd8+addop); op(wtok.rm+vop); outaddress(&wtok); if(optimizespeed||am32==0){ outword(0xC483); op(8); } else{ op(0x58); // pop EAX op(0x58); // pop EAX } addESP-=8; if(retrez==tk_floatvar||retrez==tk_doublevar){ outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } RestoreBP(); break; case tk_reg32: //добавить обработку интерпритации float, long CheckInitBP(); op66(r32); //push 0L outword(0x6a); op66(r32); //push reg32 op(0x50+(unsigned int)itok.number); if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=8; addESP+=8; fildq_stack(); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fsubr var op(0xd8+addop); op(wtok.rm+vop); outaddress(&wtok); if(optimizespeed||am32==0){ outword(0xC483); op(8); } else{ op(0x58); // pop EAX op(0x58); // pop EAX } addESP-=8; if(retrez==tk_floatvar||retrez==tk_doublevar){ outseg(&wtok,2); //fstp var op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } RestoreBP(); break; default: if(doeaxfloatmath(tk_fpust)==tk_assign){ CheckInitBP(); op66(r32); //push EAX op(0x50); op(0xD9+addop); fld_stack(4+localsize); fwait3(); RestoreBP(); op66(r32); op(0x58); } goto endequals; } } break; case tk_swap: int regdi; regdi=TRUE; getoperand(); rbuf=bufrm; bufrm=NULL; if(am32!=FALSE&&wbuf!=NULL&&wstr.bufstr!=NULL)regdi=FALSE; switch(tok){ case tk_reg32: //добавить обработку интерпритации float, long CheckInitBP(); op66(r32); //push 0L outword(0x6a); op66(r32); //push reg32 op(0x50+(unsigned int)itok.number); if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=8; addESP+=8; fildq_stack(); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9+addop); op(wtok.rm); outaddress(&wtok); op(0xdb); if(am32){ if(optimizespeed)outword(0x241c); //fistp ssdword[bp-8]/ssdword[esp] else{ outword(0x245C); op(4); } } else{ int dob; dob=8; if(!optimizespeed)dob=4; if(short_ok(localsize+dob,FALSE)==0){ op(0x9E); outword(-dob-localsize); } else{ op(0x5E); op(-dob-localsize); } } outseg(&wtok,2);//fstp val op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); op66(r32); // pop reg32 op(0x58+(unsigned int)itok.number); if(!optimizespeed){ op66(r32); // pop reg32 op(0x58+(unsigned int)itok.number); } else{ outword(0xC483); op(4); } addESP-=8; RestoreBP(); break; case tk_longvar: CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fild op(0xDB); op(itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9+addop); op(wtok.rm); outaddress(&wtok); outseg(&itok,2);//fistp var op(0xDB); op(itok.rm+0x18); outaddress(&itok); outseg(&wtok,2); //fstp val op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); break; case tk_qwordvar: CheckAllMassiv(rbuf,8,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fildq val op(0xdd); op(itok.rm+0x28); outaddress(&itok); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9+addop); op(wtok.rm); outaddress(&wtok); outseg(&itok,2); //fistp val op(0xdf); op(itok.rm+0x38); outaddress(&itok); outseg(&wtok,2); //fstp val op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); break; case tk_dwordvar: CheckInitBP(); op66(r32); //push 0L outword(0x6a); if(ESPloc&&am32&&itok.segm==SS)itok.number+=4; addESP+=4; CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); op66(r32); //push var outseg(&itok,2); op(0xFF); op(itok.rm+0x30); outaddress(&itok); if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=4; addESP+=4; fildq_stack(); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9+addop); op(wtok.rm); outaddress(&wtok); if(optimizespeed||am32==FALSE){ outword(0xC483); op(8); } else{ op(0x58); // pop EAX op(0x58); // pop EAX } addESP-=8; outseg(&itok,2);//fistp var op(0xDB); op(itok.rm+0x18); outaddress(&itok); outseg(&wtok,2); //fstp val op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); RestoreBP(); break; case tk_floatvar: if(rettype==tk_double){ CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fld val op(0xd9); op(itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,8,&wstr,&wtok); outseg(&wtok,2); //fstp val op(0xdd); op(wtok.rm); outaddress(&wtok); outseg(&itok,2); //fstp val op(0xd9); op(itok.rm+0x18); outaddress(&itok); outseg(&wtok,2); //fstp val op(0xdd); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } else{ getinto_e_ax(0,tk_dwordvar,&wtok,wbuf,&wstr,r32); CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); op66(r32); outseg(&itok,2);// XCHG EAX,[dword] op(0x87); op(itok.rm); outaddress(&itok); goto getfromeax; } break; case tk_doublevar: if(rettype==tk_float){ CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); outseg(&itok,2); //fldq val op(0xdd); op(itok.rm); outaddress(&itok); CheckAllMassiv(wbuf,8,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9); op(wtok.rm); outaddress(&wtok); outseg(&itok,2); //fstp val op(0xdd); op(itok.rm+0x18); outaddress(&itok); outseg(&wtok,2); //fstp val op(0xd9); op(wtok.rm+0x18); outaddress(&wtok); fwait3(); } else{ getinto_e_ax(0,tk_dwordvar,&wtok,wbuf,&wstr,r32); CheckAllMassiv(rbuf,4,&strinf,&itok,regdi==FALSE?idxregs[2]:idxregs[1],idxregs[3]); op66(r32); outseg(&itok,2);// XCHG EAX,[dword] op(0x87); op(itok.rm); outaddress(&itok); goto getfromeax; } break; case tk_fpust: if(itok.number>6)fpustdestroed(); CheckAllMassiv(wbuf,razr,&wstr,&wtok); outseg(&wtok,2); //fld val op(0xd9+addop); op(wtok.rm); outaddress(&wtok); op(0xD9); op(0xC8+itok.number+1); outseg(&wtok,2); //fstp val op(0xd9+addop); op(wtok.rm+0x18); outaddress(&wtok); break; default: swaperror(); break; } break; default: operatorexpected(); break; } if(next)nexttok(); if(terminater==tk_semicolon)seminext(); if(cpu<3)cpu=3; return retrez; } void fildq2_stack(int size) { op(0xdf); if(am32)outword(0x242c); //fildq ssdword[bp-8]/ssdword[esp] else{ if(short_ok(size,FALSE)==0){ op(0xAE); outword(-size); } else{ op(0x6E); op(-size); } } } void fildq_stack() { fildq2_stack(localsize+8); } void fistp2_stack(int size) { if(am32)outword(0x241c); //fistp ssdword[ebp+2]/ssdword[esp] else{ if(short_ok(size,FALSE)==0){ op(0x9E); outword(-size); } else{ op(0x5E); op(-size); } } } void fistp_stack(int addop) { op(0xDB+addop); fistp2_stack(localsize+4+addop); } void fld_stack(int size) { if(am32)outword(0x2404); //fld ssdword[ebp+2]/ssdword[esp] else{ if(short_ok(size,FALSE)==0){ op(0x86); outword(-size); } else{ op(0x46); op(-size); } } } void FloatToNumer(int addop) //конвертация float в число { CheckInitBP(); op(0xD9+addop); fld_stack(4+localsize+addop); fistp_stack(); RestoreBP(); fwait3(); op66(r32); op(0x58); //pop reg if(cpu<3)cpu=3; } void Float2reg32(int reg,int addop,int reg1,int reg2) { CheckInitBP(); op66(r32); op(0x50); //push AX if(ESPloc&&am32&&itok.segm==SS)itok.number+=4; addESP+=4; CheckAllMassiv(bufrm,4+addop,&strinf,&itok,reg1,reg2); outseg(&itok,2); //fld floatvar op(0xd9+addop); op(itok.rm); outaddress(&itok); fistp_stack(); fwait3(); op66(r32); op(0x58+reg); //pop reg addESP-=4; if(cpu<3)cpu=3; RestoreBP(); } void byteinstack(int *numstak,int *nums) { CheckInitBP(); CheckAllMassiv(bufrm,1,&strinf); op66(r16); if(tok==tk_bytevar&&optimizespeed&&chip>3&&chip<7){ outword(0xC031); //xor ax,ax outseg(&itok,2); op(0x8A); } else{ outseg(&itok,3); op(0xf); if(tok==tk_bytevar)op(0xb6); else op(0xbe); } op(itok.rm); outaddress(&itok); op66(r16); outword(0xDF50); //push ax *numstak+=2; addESP+=2; fld_stack(*nums+*numstak); } void reginstack(int *numstak,int *nums) { CheckInitBP(); op66(tok==tk_reg32?r32:r16); if(tok==tk_beg){ if(optimizespeed&&chip>3&&chip<7&&itok.number!=AL&&itok.number!=AH){ xorAXAX(); op(0x88); op(0xC0+itok.number*8); //mov al,beg } else if(itok.number==AL)xorAHAH(); else{ outword(0xB60F); /* MOVZX AX,beg */ op(0xC0+itok.number); } itok.number=0; } else outword(0x6a); //push 0 op66(tok==tk_reg32?r32:r16); op(0x50+itok.number); //push AX if(tok==tk_reg){ op(0xDB); *numstak+=4; addESP+=4; fld_stack(*nums+*numstak); } else if(tok==tk_beg){ op(0xdf); *numstak+=2; addESP+=2; fld_stack(*nums+*numstak); } else{ *numstak+=8; addESP+=8; fildq2_stack(*nums+*numstak); } } void wordinstack(int *numstak,int *nums) { CheckInitBP(); op66(tok==tk_wordvar?r16:r32); outword(0x6a); //push 0 if(ESPloc&&am32&&itok.segm==SS)itok.number+=4; CheckAllMassiv(bufrm,tok==tk_wordvar?2:4,&strinf); op66(tok==tk_wordvar?r16:r32); outseg(&itok,2); //push var op(0xFF); op(itok.rm+0x30); outaddress(&itok); if(tok==tk_wordvar){ op(0xDB); addESP+=4; *numstak+=4; fld_stack(*nums+*numstak); } else{ addESP+=8; *numstak+=8; fildq2_stack(*nums+*numstak); } } void intinstack(int addop) { CheckAllMassiv(bufrm,tok==tk_intvar?2:4+addop,&strinf); outseg(&itok,2); //fild intvar if(tok==tk_intvar||tok==tk_qwordvar)op(0xDF); else if(tok==tk_floatvar||tok==tk_doublevar)op(0xd9+addop); else op(0xDB); op(itok.rm+(tok==tk_qwordvar?0x28:0)); outaddress(&itok); } int doeaxfloatmath(int itreturn,int reg,int addop) { int vop,negflag=0,next,numstak=0; static int nums=0; int i=0; long long lnumber; int ols; ols=localsize; nums+=localsize; next=1; if(tok==tk_minus){ if(CheckMinusNum()==FALSE){ negflag=1; getoperand(am32==TRUE?EAX:BX); } } if(tok==tk_number){ // printf("rm=%d %e %e %08X\n",itok.rm,itok.fnumber,itok.dnumber,itok.number); if(addop==0/*itok.rm==tk_float*/){ itok.number=doconstfloatmath(); itok.rm=tk_float; } else{ itok.lnumber=doconstdoublemath(); itok.rm=tk_double; } next=0; if(itok.type==tp_stopper){ // if(itok.rm==tk_float&&addop==4)itok.dnumber=itok.fnumber; // if(itok.rm==tk_double&&addop==0)itok.fnumber=itok.dnumber; if(itreturn==tk_stackstart){ if(itok.rm==tk_double){ lnumber=itok.lnumber; itok.lnumber=lnumber>>32; } for(i=0;i<2;i++){ op66(r32); if(short_ok(itok.number,TRUE)){ //PUSH number op(0x6A); op(itok.number); } else{ op(0x68); outdword(itok.number); } if(itok.rm!=tk_double)break; if(i==1)break; itok.number=lnumber; } return itreturn; } if(itreturn==tk_reg32){ MovRegNum(r32,0,itok.number,reg); return itreturn; } if(itreturn==tk_reg64){ MovRegNum(r32,0,itok.number,reg&255); MovRegNum(r32,0,itok.lnumber>>=32,reg/256); return itreturn; } } } if(itreturn==tk_stackstart&&(!am32)){ op66(r32); op(0x50); //push eax if(addop){ op66(r32); op(0x50); //push eax } op(0x55); //push bp outword(0xe589);//mov bp,sp if(initBP>1)initBP++; localsize=-6-addop; } if(next==0)goto casenumber; switch(tok){ case tk_number: casenumber: // printf("rm=%d %e %e %08X\n",itok.rm,itok.fnumber,itok.dnumber,itok.number); if((itok.rm==tk_float&&itok.fnumber==1.0)|| (itok.rm==tk_double&&itok.dnumber==1.0)|| (itok.rm!=tk_float&&itok.rm!=tk_double&&itok.lnumber==1)){ outword(0xE8D9); //FLD1 break; } if((itok.rm==tk_float&&itok.fnumber==0.0)|| (itok.rm==tk_double&&itok.dnumber==0.0)||itok.lnumber==0){ outword(0xEED9); //FLDZ break; } op(0xD9+(itok.rm==tk_float?0:4)); op((am32==FALSE?0x06:0x05)); //fld AddFloatConst(itok.lnumber,itok.rm); outword(0); if(am32)outword(0); break; case tk_at: getoperand(am32==TRUE?EAX:BX); macros(tk_fpust); break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_declare: case tk_undefproc: int onums; onums=nums; nums=-(int)localsize; vop=procdo(tk_fpust); //возвр из процедур nums=onums; if(tok2==tk_semicolon&&vop!=tk_fpust&&vop!=tk_double){ nexttok(); return tk_assign; } break; case tk_qwordvar: case tk_doublevar: i=4; case tk_floatvar: case tk_longvar: case tk_intvar: intinstack(i); break; case tk_dwordvar: case tk_wordvar: wordinstack(&numstak,&nums); break; case tk_charvar: case tk_bytevar: byteinstack(&numstak,&nums); break; case tk_beg: case tk_reg32: case tk_reg: reginstack(&numstak,&nums); break; case tk_fpust: if(itok.number){ op(0xD9); op(0xC8+itok.number); } break; default: valueexpected(); break; } if(negflag){ outword(0xe0d9); //fchs negflag=0; } if(next==1)nexttok(); while(itok.type!=tp_stopper&&tok!=tk_eof&&itok.type!=tp_compare){ next=1; vop=0; i=0; switch(tok){ case tk_multminus: negflag=1; goto mult; case tk_divminus: negflag=1; case tk_div: vop+=0x10; case tk_minus: vop+=0x20; mult: case tk_mult: vop+=8; case tk_plus: getoperand(); switch(tok){ case tk_number: if(itok.rm!=tk_float&&itok.rm!=tk_double){ itok.dnumber=itok.lnumber; itok.rm=tk_double; } if((itok.rm==tk_float&&itok.fnumber==1.0)|| (itok.rm==tk_double&&itok.dnumber==1.0)){ num1: if(vop==0||vop==0x28){ // + - outword(0xE8D9); //FLD1 op(0xDE); op(0xC1+vop); } break; } op(0xd8+(itok.rm==tk_float?0:4)); if(vop==0x38){ // div 22.12.05 22:10 vop=8; //mult if(itok.rm==tk_float)itok.fnumber=1/itok.fnumber; else itok.dnumber=1/itok.dnumber; } if(/*vop==0x38||*/vop==0x28)vop-=8; op((am32==FALSE?0x06:0x05)+vop); AddFloatConst(itok.lnumber,itok.rm); outword(0); if(am32)outword(0); break; case tk_doublevar: i=4; case tk_floatvar: if(vop==0x38||vop==0x28)vop-=8; CheckAllMassiv(bufrm,4+i,&strinf); outseg(&itok,2); //fsubr var op(0xd8+i); op(itok.rm+vop); outaddress(&itok); break; case tk_longvar: case tk_intvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,2); //fsubr var op(tok==tk_intvar?0xDE:0xDA); if(vop==0x38||vop==0x28)vop-=8; op(itok.rm+vop); outaddress(&itok); break; case tk_qwordvar: intinstack(4); op(0xde); op(0xC1+vop);//fsubpr st1 break; case tk_dwordvar: case tk_wordvar: wordinstack(&numstak,&nums); op(0xde); op(0xC1+vop);//fsubpr st1 break; case tk_beg: case tk_reg32: case tk_reg: reginstack(&numstak,&nums); op(0xde); op(0xC1+vop);//fsubpr st1 break; case tk_charvar: case tk_bytevar: byteinstack(&numstak,&nums); op(0xde); op(0xC1+vop);//fsubpr st1 break; case tk_fpust: if(vop==0x38||vop==0x28)vop-=8; op(0xd8); op(0xC0+vop+itok.number);//fsubpr st break; default: valueexpected(); break; } break; default: illegalfloat(); break; } if(negflag){ outword(0xe0d9); //fchs negflag=0; } if(next)nexttok(); } if(tok==tk_eof)unexpectedeof(); if(itreturn==tk_stackstart){ if(!am32){ op(0xD9+addop); outword(0x025e); //fstp ssdword[bp+2] numstak-=2; } else{ if(numstak<4){ op66(r32); op(0x50); //push eax addESP+=4; } else numstak-=4; if(addop){ if(numstak<4){ op66(r32); op(0x50); //push eax addESP+=4; } else numstak-=4; } op(0xD9+addop); if(numstak==0)outword(0x241C); //fstp ssdword[esp] else{ outword(0x245C); //fstp ssdword[esp+numstak] op(numstak); } } fwait3(); } else if(itreturn==tk_reg32||itreturn==tk_reg64){ i=4; if(itreturn==tk_reg64)i=8; if(numstak6)fpustdestroed(); // outword(0xf6d9); //fdecstp doeaxfloatmath(tk_fpust); if(num){ op(0xD9); op(0xC8+num); } } void dofloatstack(int num) { int vop=0; nexttok(); switch(tok){ case tk_assign: //= getoperand(am32==TRUE?EAX:BX); float2stack(num); break; case tk_divequals: vop+=0x10; case tk_minusequals: vop+=0x20; case tk_multequals: vop+=8; case tk_plusequals: getoperand(am32==TRUE?EAX:BX); float2stack(0); // doeaxfloatmath(tk_fpust); op(0xdc); op(0xC0+vop+num);//fsubpr st break; case tk_swap: getoperand(am32==TRUE?EAX:BX); switch(tok){ case tk_fpust: op(0xD9); op(0xC8+num); op(0xD9); op(0xC8+itok.number); op(0xD9); op(0xC8+num); break; case tk_doublevar: vop=4; case tk_floatvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,2); //fld val op(0xd9+vop); op(itok.rm); outaddress(&itok); op(0xD9); op(0xC8+num+1); outseg(&itok,2); //fstp val op(0xd9+vop); op(itok.rm+0x18); outaddress(&itok); break; default: swaperror(); break; } nexttok(); break; default: illegalfloat(); break; } } void RestoreBP() { if(am32==0&&initBP==2){ Leave(); initBP=0; } } void CheckInitBP() { if(am32==0&&initBP==0){ op(0x55); //push bp outword(0xe589);//mov bp,sp initBP=2; } } void AddReloc(int segm) { if(FixUp!=FALSE){ CheckPosts(); if(segm==DS){ (postbuf+posts)->type=(unsigned short)(am32==FALSE?FIX_VAR:FIX_VAR32); (postbuf+posts)->loc=outptrdata; } else{ (postbuf+posts)->type=(unsigned short)(am32==FALSE?FIX_CODE:FIX_CODE32); (postbuf+posts)->loc=outptr; } posts++; } postnumflag&=(~f_reloc); } void fwait3() { if(chip<4&&tok2!=tk_floatvar&&tok2!=tk_doublevar&&tok2!=tk_float&&tok2!=tk_double)op(0x9B); } void AddFloatConst(long long fnumber,int type) { unsigned int i; unsigned int ofs; for(i=0;itype){ ofs=(floatnum+i)->ofs; if(type==tk_float){ if(*(long *)&fnumber==(floatnum+i)->num[0])goto endp; } else if(*(double *)&fnumber==(floatnum+i)->dnum)goto endp; } } if(numfloatconst==0){ floatnum=(LISTFLOAT *)MALLOC(sizeof(LISTFLOAT)*STEPFLOATCONST); maxnumfloatconst=STEPFLOATCONST; // memset(floatnum,0,sizeof(LISTFLOAT)*STEPFLOATCONST); } else if((numfloatconst+1)==maxnumfloatconst){ floatnum=(LISTFLOAT *)REALLOC(floatnum,(maxnumfloatconst+STEPFLOATCONST)*sizeof(LISTFLOAT)); maxnumfloatconst+=STEPFLOATCONST; } numfloatconst++; (floatnum+i)->type=type; ofs=(floatnum+i)->ofs=ofsfloatlist; if(type==tk_float)(floatnum+i)->num[0]=*(unsigned long *)&fnumber; else (floatnum+i)->dnum=*(double *)&fnumber; ofsfloatlist+=(type==tk_float?4:8); endp: CheckPosts(); (postbuf+posts)->type=POST_FLOATNUM; (postbuf+posts)->loc=outptrdata; (postbuf+posts)->num=ofs; posts++; } void setwordext(long *id) { CheckPosts(); (postbuf+posts)->type=EXT_VAR; (postbuf+posts)->loc=outptr; (postbuf+posts)->num=*id&0xFFFF; //id номер внешней переменной *id>>=16; //ее значение posts++; } void setwordpost(ITOK *stok) /* for post word num setting */ { CheckPosts(); if(stok->post==USED_DIN_VAR){ (postbuf+posts)->type=(unsigned short)(am32==0?DIN_VAR:DIN_VAR32); // printf("Add tok=%d %s\n",stok->rec->rectok,stok->rec->recid); // printf("rec=%08X\n",stok->rec); if(stok->rec->rectok==tk_structvar&&stok->rec->recsib==tp_gvar){ (postbuf+posts)->num=(int)stok->rec;//02.09.05 17:11 ->right; } else (postbuf+posts)->num=(int)stok->rec; } else if(stok->post>=CODE_SIZE&&stok->post<=STACK_SIZE32)(postbuf+posts)->type=stok->post; else (postbuf+posts)->type=(unsigned short)(am32==FALSE?POST_VAR:POST_VAR32); (postbuf+posts)->loc=outptr; posts++; } void MovRegNum(int razr,int relocf,unsigned long number,int reg) { unsigned long num; int nreg; op66(razr); if(relocf==0){ if(number!=0&&GetRegNumber(reg,&num,razr)==reg){ ConstToReg(number,reg,razr); if(num==number)return; else if(num2||razr==r32)&&chip!=5&&chip!=6){ outdword(0x01d0ac0f); //shrd ax,dx,1 setzeroflag=TRUE; } else{ outword(0xead1); //shr dx,1 rcr ax,1 op66(razr); outword(0xd8d1); setzeroflag=FALSE; } ClearReg(AX); ClearReg(DX); break; } op66(razr); if(sign)outword(0xF8D1);// SAR AX,1 else outword(0xE8D1); // SHR AX,1 setzeroflag=TRUE; ClearReg(AX); break; default: vop=caselong(itok.number); if(vop!=NUMNUM){ if(expand==TRUE){ if(chip>2||razr==r32){ op66(razr); op(0x0f); outword(0xd0ac); //shrd ax,dx,vop op(vop); setzeroflag=TRUE; ClearReg(AX); ClearReg(DX); } else{ if(optimizespeed==FALSE)goto divin; op(0xB1); op(vop); /* MOV CL,num */ if(sign)outword(0xFad1); // SAR AX,1 else outword(0xEad1); // SHR AX,1 outdword(0xfae2d8d1); //rcr ax,1 LOOP -6 warningreg(begs[1]); setzeroflag=FALSE; ClearReg(AX); ConstToReg(vop,CL,r8); } } else{ if(chip<2&&razr==r16){ op(0xB1); op(vop); /* MOV CL,num */ if(sign)outword(0xF8D3); // SAR AX,CL else outword(0xE8D3); // SHR AX,CL warningreg(begs[1]); ClearReg(AX); ConstToReg(vop,CL,r8); } else{ op66(razr); if(sign)outword(0xF8C1); // SAR AX,num else outword(0xE8C1); // SHR AX,num op(vop); ClearReg(AX); } setzeroflag=TRUE; } } else{ if(expand==FALSE)DivNum(itok.number,razr,sign); else{ divin: if(!expand)ClearDX(razr,sign); DivNum2(itok.number,razr,sign); } } } } } else{ if(tok==tk_doublevar){ i=4; tok=tk_floatvar; } if(tok==tk_floatvar){ Float2reg32(ECX,i); warningreg(regs[razr/2-1][1]); itok.number=ECX; tok=(razr==r16?tk_reg:tk_reg32); sign=1; } switch(tok){ case tk_qwordvar: i=4; case tk_longvar: case tk_dwordvar: i+=2; case tk_intvar: case tk_wordvar: if(razr==r32&&(tok==tk_intvar||tok==tk_wordvar))goto defdiv; i+=2; CheckAllMassiv(bufrm,i,&strinf); if(expand==FALSE)ClearDX(razr,sign); op66(razr); outseg(&itok,2); op(0xF7); if(sign)op(0x38+itok.rm); /* IDIV word ptr [#] */ else op(0x30+itok.rm); /* DIV word ptr [#] */ outaddress(&itok); ClearReg(AX); break; case tk_reg: if(razr==r32){ i=itok.number; getintoreg_32(i,r32,0,&ofsstr,FALSE); if(expand==FALSE)ClearDX(razr,sign); op66(r32); op(0xF7); if(sign)op(0xF8+i); /* IDIV ECX */ else op(0xF0+i); /* DIV ECX */ next=0; warningreg(regs[1][2]); ClearReg(AX); ClearReg(CX); break; } case tk_reg32: if(expand==FALSE)ClearDX(razr,sign); op66(razr); op(0xF7); if(sign)op(0xF8+(unsigned int)itok.number); else op(0xF0+(unsigned int)itok.number); ClearReg(AX); break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: op66(razr); op(0x50); //push AX addESP+=razr==r16?2:4; unsigned char oaddstack; oaddstack=addstack; addstack=FALSE; procdo(razr==r16?(sign==0?tk_word:tk_int):(sign==0?tk_dword:tk_long)); addstack=oaddstack; addESP-=razr==r16?2:4; op66(razr); op(0x90+ECX); //xchg AX,CX op66(razr); op(0x58); //pop AX if(expand==FALSE)ClearDX(razr,sign); op66(razr); op(0xF7); if(sign)op(0xF8+ECX); /* IDIV ECX */ else op(0xF0+ECX); /* DIV ECX */ warningreg(regs[razr/2-1][ECX]); break; case tk_undefofs: case tk_seg: case tk_charvar: case tk_beg: case tk_bytevar: case tk_rmnumber: case tk_postnumber: case tk_apioffset: defdiv: getintoreg_32(CX,razr,0,&ofsstr,FALSE); if(expand==FALSE)ClearDX(razr,sign); op66(razr); if(sign)outword(0xF9F7); /* IDIV CX */ else outword(0xF1F7); /* DIV CX */ next=0; warningreg(regs[razr/2-1][ECX]); ClearReg(CX); ClearReg(AX); break; default: valueexpected(); break; } setzeroflag=FALSE; /* if(vop){ op66(razr); if(optimizespeed)outword(0xC28B); //mov ax,dx else op(0x92); //xchg ax,dx }*/ } if(next)nexttok(); } void DivNum(unsigned long num,int razr,int sign) { /*int i; unsigned long num2; if(num<65536&&optimizespeed&&(itok.flag&f_reloc)==0&&sign==0){ //for signed needed new algoritm if(razr==r16&&chip>2){ num2=65536/(unsigned int)num+1; if((65535/num2)!=num)goto stddiv; op66(r32); op(0x25); outdword(0xffff); //and EAX,ffff if(short_ok(num2,FALSE))i=2; //короткая форма op66(r32); op(0x69+i); //imul EAX,num op(0xc0); if(i==2)op(num2); else outdword(num2); op66(r32); outword(0xE8C1); op(0x10); //shr EAX,16 setzeroflag=TRUE; } else{ if(razr==r32)num=(unsigned long)0xFFFFFFFFL/num+1; else num=65536/(unsigned int)num+1; op66(razr); op(0xBA); //mov DX,num if(razr==r16)outword(num); else outdword(num); op66(razr); outword(0xE2F7); //mul DX op66(razr); outword(0xD089); //mov AX,DX setzeroflag=FALSE; warningreg(regs[razr/2-1][2]); } return; } stddiv:*/ ClearDX(razr,sign); DivNum2(num,razr,sign); } void ClearDX(int razr,int sign) { if(sign)cwdq(razr); else{ op66(razr); outword(0xD231); } warningreg(regs[razr/2-1][EDX]); ClearReg(DX); } void DivNum2(unsigned long num,int razr,int sign) { MovRegNum(razr,itok.flag&f_reloc,num,ECX); op66(razr); if(sign)outword(0xF9F7); /* IDIV CX */ else outword(0xF1F7); /* DIV CX */ warningreg(regs[razr/2-1][ECX]); ClearReg(CX); ClearReg(AX); } int getintoreg(int reg,int razr,int sign,char **ofsstr) { ITOK oitok,oitok2; int oline,oendinptr; int oinptr,otok,otok2; unsigned char *oinput; unsigned char ocha; int useeax=FALSE; int operand=tk_plus; int rettype=tk_reg; char *obuf; SINFO ostr; int i=0; int j=0; int onlynum=FALSE; COM_MOD *bmod; switch(tok){ case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: break; default: // if(cur_mod)break; //10.08.04 22:50 из-за define прекратить obuf=bufrm; bufrm=NULL; ostr=strinf; strinf.bufstr=NULL; oitok=itok; oitok2=itok2; otok=tok; otok2=tok2; oline=linenum2; oinptr=inptr2; oinput=input; oendinptr=endinptr; bmod=cur_mod; while(bmod){ bmod->freze=TRUE; bmod=bmod->next; } bmod=cur_mod; ocha=cha2; // printf("input=%08X inptr=%08X %s\n",input,inptr2,input+inptr2); if(tok==tk_number)onlynum=TRUE; while((!useeax)&&itok.type!=tp_stopper&&tok!=tk_eof){ nexttok(); if(itok.type==tp_stopper)break; if(itok.type==tp_opperand)operand=tok; else{ i++; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr)free(strinf.bufstr); switch(operand){ case tk_div: case tk_mod: case tk_divminus: case tk_modminus: if(j==0)j=1; if((tok==tk_reg||tok==tk_reg32)&&itok.number==reg)useeax=TRUE; if(j==1){ if(tok==tk_number){ if(onlynum==FALSE&&caselong(itok.number)==NUMNUM)j++; } else{ j++; onlynum=FALSE; } } break; } } } if(bmod!=cur_mod){ if(bmod&&bmod->freze){ cur_mod=bmod; while(bmod){ bmod->freze=FALSE; bmod=bmod->next; } } else{ do{ COM_MOD *temp=cur_mod; cur_mod=cur_mod->next; // printf("bmod=%08X cur_mod=%08X\n",bmod,cur_mod); if(temp->paramdef)free(temp->paramdef); free(temp); }while(bmod!=cur_mod); while(bmod){ bmod->freze=FALSE; bmod=bmod->next; } } input=oinput; } endinptr=oendinptr; itok=oitok; itok2=oitok2; tok=otok; tok2=otok2; linenum2=oline; inptr2=oinptr; cha2=ocha; endoffile=0; // printf("input=%08X inptr=%08X %s\n",input,inptr2,input+inptr2); // if(bufrm) { free(bufrm); bufrm=NULL; } // if(strinf.bufstr)free(strinf.bufstr); bufrm=obuf; strinf=ostr; break; } if(useeax){ op66(razr); op(0x50); addESP+=razr==r16?2:4; do_e_axmath(0,razr,ofsstr); op66(razr); if(optimizespeed){ op(0x89); op(0xC0+reg); } else op(0x90+reg); op66(razr); addESP-=razr==r16?2:4; op(0x58); } else{ if(i==1&&j>=2){ i=EAX; j=1; } else i=reg; rettype=getintoreg_32(i,razr,sign,ofsstr); if(itok.type!=tp_stopper&&itok.type!=tp_compare&&tok!=tk_eof){ doregmath_32(reg,razr,sign,ofsstr,j); rettype=tk_reg; } } return rettype; } void dobits() { ITOK wtok; char *wbuf; SINFO wstr; int razr,i,sign=0,posiblret,pointr=0; unsigned int rettype; int numpointr=0; char *ofsstr=NULL; posiblret=rettype=tk_dword; razr=r32; i=itok.bit.siz+itok.bit.ofs; if(i<9){ razr=r8; posiblret=rettype=tk_byte; } else if(i<17){ posiblret=rettype=tk_word; razr=r16; } else if(i>32)razr=r64; if(tok2==tk_assign){ wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; nexttok(); nexttok(); convert_type(&sign,(int *)&rettype,&pointr); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr)unuseableinput(); if(tok2==tk_assign){ MultiAssign(razr,EAX,numpointr); goto axtobit; } if(tok==tk_pointer)cpointr(am32==TRUE?EAX:BX,numpointr); CheckMinusNum(); if(tok==tk_number){ if(itok2.type==tp_opperand){ //сложное выражение if(!OnlyNumber(0))goto labl1; itok.flag=(unsigned char)postnumflag; } else{ unsigned long num=itok.number; nexttok(); itok.number=num; } CheckAllMassiv(wbuf,razr,&wstr,&wtok); if(razr!=r64)num2bits(&wtok,itok.number,razr); else{ int siz=wtok.bit.siz; wtok.bit.siz=32-wtok.bit.ofs; num2bits(&wtok,itok.number,r32); wtok.bit.siz=siz+wtok.bit.ofs-32; wtok.bit.ofs=0; itok.number=itok.number>>(32-wtok.bit.siz); wtok.number+=4; num2bits(&wtok,itok.number,r8); } } else{ labl1: if(rettype==tk_char||rettype==tk_byte)doalmath(sign,&ofsstr); else if(rettype==tk_int||rettype==tk_word)do_e_axmath(sign,r16,&ofsstr); else if(rettype==tk_float)doeaxfloatmath(tk_reg32,AX); else do_e_axmath(sign,r32,&ofsstr); convert_returnvalue(posiblret,rettype); CheckAllMassiv(wbuf,razr,&wstr,&wtok); axtobit: if(razr!=r64)reg2bits(&wtok,razr); else{ int siz=wtok.bit.siz; op66(r32); op(0x50); //push eax if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=4; addESP+=4; wtok.bit.siz=32-wtok.bit.ofs; reg2bits(&wtok,r32); op66(r32); op(0x58); //pop eax addESP-=4; op66(r32); //shr eax,size outword(0xE8C1); op(wtok.bit.siz); wtok.bit.siz=siz+wtok.bit.ofs-32; wtok.bit.ofs=0; wtok.number+=4; reg2bits(&wtok,r8); } return; } } else{ bits2reg(AX,razr); wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; switch(razr){ case r8: dobeg(AL); break; case r16: case r32: doreg_32(AX,razr); break; case r64: doreg_32(AX,r32); break; } goto axtobit; } seminext(); } void bits2reg(int reg,int razr) { int i,j,skip66=FALSE; i=itok.bit.siz+itok.bit.ofs; j=~GetBitMask(itok.bit.ofs,itok.bit.siz); ITOK wtok; char *wbuf; wbuf=bufrm; bufrm=NULL; wtok=itok; SINFO wstr; wstr=strinf; strinf.bufstr=NULL; switch(razr){ case r8: if(reg==AL){ getintoal(tk_bytevar,&wtok,wbuf,&wstr); if(i!=8){ op(4+0x20); //and al,j op(j); } } else{ CheckAllMassiv(bufrm,1,&strinf); outseg(&itok,2); op(0x8A); op(reg*8+itok.rm); outaddress(&itok); if(i!=8){ op(128); op(128+64+reg+0x20); op(j); } } if(itok.bit.ofs){ //shr al,ofs if(itok.bit.ofs==1){ op(0xD0); op(0xE8+reg); } else{ op(0xC0); op(0xE8+reg); op(itok.bit.ofs); } } break; case r16: case r32: if(reg==AX){ getinto_e_ax(0,(razr==r16?tk_wordvar:tk_dwordvar),&wtok,wbuf,&wstr,razr); if(razr==r16&&i!=16){ op66(razr); //and (e)ax,j op(4+1+0x20); outword(j); } else if(razr==r32&&i!=32){ op66(razr); //and (e)ax,j if(short_ok(j,TRUE)){ op(128+2+1); op(128+64+0x20); op((int)j); } else{ op(4+1+0x20); outdword(j); } } if(j<65536&&razr==r32)skip66=TRUE; if(itok.bit.ofs){ //shr (e)ax,ofs if(!skip66)op66(razr); if(itok.bit.ofs==1)outword(0xE8D1); else{ outword(0xE8C1); op(itok.bit.ofs); } } } else{ int reg1=idxregs[0],reg2=idxregs[1]; if(!am32){ if(reg==idxregs[2]||reg==idxregs[1]){ reg1=reg; if(reg==idxregs[1])reg2=idxregs[0]; } } else{ reg1=reg; if(reg==idxregs[1])reg2=idxregs[0]; } CheckAllMassiv(bufrm,razr==r32?4:2,&strinf,&itok,reg1,reg2); op66(razr); outseg(&itok,2); op(0x8B); op(reg*8+itok.rm); outaddress(&itok); if((razr==r16&&i!=16)||(razr==r32&&i!=32)){ op66(razr); //and reg,j if(short_ok(j,razr==r16?FALSE:TRUE)){ op(128+2+1); op(128+64+reg+0x20); op(j); } else{ op(128+1); op(128+64+reg+0x20); if(razr==r16)outword(j); else outdword(j); } } if(itok.bit.ofs){ //shr reg,ofs op66(razr); if(itok.bit.ofs==1){ op(0xD1); op(0xE8+reg); } else{ op(0xC1); op(0xE8+reg); op(itok.bit.ofs); } } } break; case r64: if(reg==AX){ getinto_e_ax(0,tk_dwordvar,&wtok,wbuf,&wstr,r32); itok.number+=4; outseg(&itok,2); op(0x8B); op(DX*8+itok.rm); outaddress(&itok); if(itok.bit.siz!=32){ op(128); op(128+64+DL+0x20); op(li[itok.bit.siz+itok.bit.ofs-32]-1); } op66(r32); outword(0xAC0F); //shrd edx,eax,ofs op(0xC2); op(itok.bit.ofs); itok.number-=4; warningreg(regs[1][EDX]); } else{ int reg1=DX; if(reg==DX)reg1=CX; CheckAllMassiv(bufrm,4,&strinf,&itok); op66(r32); outseg(&itok,2); op(0x8B); op(reg*8+itok.rm); outaddress(&itok); itok.number+=4; outseg(&itok,2); op(0x8B); op(reg1*8+itok.rm); outaddress(&itok); if(itok.bit.siz!=32){ op(128+(reg1<4?0:3)); op(128+64+reg1+0x20); op(li[itok.bit.siz+itok.bit.ofs-32]-1); } itok.number-=4; op66(r32); outword(0xAC0F); //shrd edx,eax,ofs op(0xc0+reg1+reg*8); op(itok.bit.ofs); warningreg(regs[1][reg1]); } ClearReg(DX); break; } ClearReg(AX); ClearReg(reg); } void num2bits(ITOK *gtok,unsigned long num,int razr) { unsigned int j,mask; mask=GetBitMask(gtok->bit.ofs,gtok->bit.siz); j=li[gtok->bit.siz]-1; if((num&j)!=j){ if(razr!=r8){ op66(razr); //and bits,mask outseg(gtok,2); if((postnumflag&f_reloc)==0&&short_ok(mask,razr/2-1)){ op(128+2+1); op(gtok->rm+0x20); outaddress(gtok); op(mask); } else{ op(128+1); op(gtok->rm+0x20); outaddress(gtok); if((postnumflag&f_reloc)!=0)AddReloc(); if(razr==r16)outword(mask); else outdword(mask); } } else{ outseg(gtok,2); //and bits,mask op(128); op(gtok->rm+0x20); outaddress(gtok); op(mask); } } num=(num&j)<bit.ofs; //or bits,mask if(num<65536&&razr==r32)razr=r16; if(num<256&&razr==r16)razr=r8; if(razr!=r8){ op66(razr); outseg(gtok,2); if((postnumflag&f_reloc)==0&&short_ok(num,razr/2-1)){ op(128+2+1); op(gtok->rm+8); outaddress(gtok); op(num); } else{ op(128+1); op(gtok->rm+8); outaddress(gtok); if((postnumflag&f_reloc)!=0)AddReloc(); if(razr==r16)outword(num); else outdword(num); } } else{ if((unsigned char)num!=0){ outseg(gtok,2); op(128); op(gtok->rm+8); outaddress(gtok); op(num); } } } void reg2bits(ITOK *gtok,int razr) { int i,j,mask; j=li[gtok->bit.siz]-1; mask=GetBitMask(gtok->bit.ofs,gtok->bit.siz); i=gtok->bit.ofs+gtok->bit.siz; switch(razr){ case r8: if(i!=8){ op(4+0x20); //and al,size op(j); } outseg(gtok,2); //and bits,mask op(128); op(gtok->rm+0x20); outaddress(gtok); op(mask); if(gtok->bit.ofs)lshiftmul(gtok->bit.ofs,razr); outseg(gtok,2); op(8); op(gtok->rm); outaddress(gtok); break; case r16: case r32: if(razr==r16&&i!=16){ op66(razr); //and (e)ax,size op(4+1+0x20); outword(j); } else if(razr==r32&&i!=32){ op66(razr); //and (e)ax,size if(short_ok(j,TRUE)){ op(128+2+1); op(128+64+0x20); op((int)j); } else{ op(4+1+0x20); outdword(j); } } op66(razr); //and bits,mask outseg(gtok,2); if(short_ok(mask,razr/2-1)){ op(128+2+1); op(gtok->rm+0x20); outaddress(gtok); op(mask); } else{ op(128+1); op(gtok->rm+0x20); outaddress(gtok); if(razr==r16)outword(mask); else outdword(mask); } if(gtok->bit.ofs)lshiftmul(gtok->bit.ofs,razr); op66(razr); outseg(gtok,2); op(1+8); op(gtok->rm); outaddress(gtok); break; } } void getoperand(int reg) { unsigned int numpointr=0; nexttok(); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr){ unuseableinput(); } if(tok==tk_pointer){ cpointr(reg,numpointr); } CheckMinusNum(); } void cpointr(int reg,int numpointr) { if(itok.type==tk_proc){ if(tok2==tk_openbracket){ tok=tk_proc; } else{ itok.rm=itok.sib; if(am32){ itok.sib=CODE32; tok=tk_dwordvar; } else{ itok.sib=CODE16; tok=tk_wordvar; } compressoffset(&itok); } return; } int razr=typesize(itok.type); if(numpointr==itok.npointr){ getpointeradr(&itok,bufrm,&strinf,numpointr-1,razr,reg); if(itok.type>=tk_char&&itok.type<=tk_float)tok=tk_charvar+itok.type-tk_char; else tok=(am32==FALSE?tk_wordvar:tk_dwordvar); } else if(numpointrtype==tk_proc){ wtok->rm=wtok->sib; if(am32){ wtok->sib=CODE32; *otok=tk_dwordvar; } else{ wtok->sib=CODE16; *otok=tk_wordvar; } compressoffset(wtok); } else{ int razr=typesize(wtok->type); int reg=idxregs[2]; if(reg==ureg)reg=idxregs[1]; if(npointr==wtok->npointr){ getpointeradr(wtok,wbuf,wstr,npointr-1,razr,reg); if(wtok->type>=tk_char&&wtok->type<=tk_float)*otok=tk_charvar+wtok->type-tk_char; else *otok=(am32==FALSE?tk_wordvar:tk_dwordvar); } else if(npointrnpointr){ *otok=(am32==FALSE?tk_wordvar:tk_dwordvar); if(npointr)getpointeradr(wtok,wbuf,wstr,npointr-1,razr,reg); else return; } else unuseableinput(); memcpy(wtok,&itok,sizeof(ITOK)); } } int CheckAddOnly() { ITOK oitok,oitok2; int oline; int oinptr,otok,otok2; unsigned char ocha; char *obuf; SINFO ostr; int retval=TRUE; int j=3; int changesign=0; if(tok==tk_minusequals)changesign++; else if(tok!=tk_plusequals)return FALSE; if(itok2.type==tp_stopper)return FALSE; newloop: obuf=bufrm; bufrm=NULL; ostr=strinf; strinf.bufstr=NULL; oitok=itok; oitok2=itok2; otok=tok; otok2=tok2; oline=linenum2; oinptr=inptr2; ocha=cha2; while(tok2==tk_minus||tok2==tk_mult)nexttok(); while(itok.type!=tp_stopper&&tok!=tk_eof){ nexttok(); switch(tok){ case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: retval=FALSE; itok.type=tp_stopper; break; } if(itok.type==tp_stopper)break; if(itok.type==tp_opperand){ if(tok!=tk_plus&&tok!=tk_minus){ retval=FALSE; break; } else if(changesign==2){ int i=inptr2-1; char c; do{ i--; c=input[i]; i--; }while(c!='-'&&c!='+'); i++; if(c=='-')c='+'; else c='-'; input[i]=c; } while(itok2.type==tp_opperand&&tok!=tk_eof)nexttok(); } else{ if(tok!=tk_number&&tok!=tk_postnumber&&tok!=tk_undefofs){ if(j>1)j=0; if(bufrm){ free(bufrm); bufrm=NULL; } if(strinf.bufstr)free(strinf.bufstr); } else if(j>1)j--; } } itok=oitok; itok2=oitok2; tok=otok; tok2=otok2; linenum2=oline; inptr2=oinptr; cha2=ocha; endoffile=0; bufrm=obuf; strinf=ostr; if(j==1)retval=FALSE; else if(changesign==1){ changesign++; goto newloop; } return retval; } int doqwordvar(int terminater) //64 bit memory variable { unsigned char next=1,getfromAX=0; unsigned int vop=0,otok,rettype; int sign,i; ITOK wtok; char *wbuf,*rbuf; SINFO wstr; int retrez=0,pointr=0; int numpointr=0; int reg; char *ofsstr=NULL; int reg1=idxregs[0],reg2=idxregs[1]; rettype=tk_qword; sign=0; wstr=strinf; strinf.bufstr=NULL; wtok=itok; wbuf=bufrm; bufrm=NULL; otok=tok; nexttok(); switch(tok){ case tk_assign: //= nexttok(); convert_type(&sign,(int *)&rettype,&pointr); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr){ unuseableinput(); } CheckMinusNum(); if(itok2.type==tp_opperand){ //сложное выражение if(tok==tk_number){ //проверка и суммирование чисел switch(rettype){ case tk_float: sign=2; break; case tk_double: sign=3; break; case tk_qword: sign=4; break; } if(OnlyNumber(sign)){ next=0; itok.flag=(unsigned char)postnumflag; goto numbertovar; } } goto labl1; } else{ switch(tok){ case tk_number: if((itok.flag&f_reloc)==0){ if(itok.lnumber==0){ CheckAllMassiv(wbuf,8,&wstr,&wtok); for(i=0;i<2;i++){ op66(r32); outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); if(i==1)break; wtok.number+=4; compressoffset(&wtok); } break; } if(itok.lnumber==0xFFFFFFFFFFFFFFFFLL){ CheckAllMassiv(wbuf,8,&wstr,&wtok); for(i=0;i<2;i++){ op66(r32); outseg(&wtok,2); op(0x83); op(wtok.rm+0x8); outaddress(&wtok); op(0xFF); if(i==1)break; wtok.number+=4; compressoffset(&wtok); } break; } } numbertovar: CheckAllMassiv(wbuf,8,&wstr,&wtok); for(i=0;i<2;i++){ op66(r32); if(regoverstack&&short_ok(itok.number,TRUE)&&(itok.flag&f_reloc)==0){ op(0x6A); op(itok.number); //push short number op66(r32); outseg(&wtok,2); op(0x8f); op(wtok.rm); outaddress(&wtok); } else{ outseg(&wtok,2); op(0xC7); //mov word[],number op(wtok.rm); outaddress(&wtok); if((itok.flag&f_reloc)!=0)AddReloc(); outdword(itok.number); } if(i==1)break; itok.lnumber>>=32; wtok.number+=4; compressoffset(&wtok); } break; case tk_apioffset: case tk_postnumber: case tk_undefofs: CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0xC7); //mov word[],number op(wtok.rm); outaddress(&wtok); if(tok==tk_apioffset)AddApiToPost(itok.number); else{ if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); // else if((itok.flag&f_reloc)!=0)AddReloc(); outdword(itok.number); } wtok.number+=4; compressoffset(&wtok); op66(r32); outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); break; case tk_reg64: goto getfromreg; case tk_reg32: if(itok.number==AX&&wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA3); // MOV [word],AX if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x89); op((unsigned int)itok.number*8+wtok.rm); outaddress(&wtok); } wtok.number+=4; compressoffset(&wtok); op66(r32); outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); break; case tk_string: CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0xC7); op(wtok.rm); outaddress(&wtok); outdword(addpoststring()); wtok.number+=4; compressoffset(&wtok); op66(r32); outseg(&wtok,2); op(0x83); op(wtok.rm+0x20); outaddress(&wtok); op(0); break; default: labl1: reg=EAX|(EDX*256); getintoreg64(reg); doregmath64(reg); getfromAX=1; next=0; break; } } if(getfromAX){ getfromax: itok.number=EAX|(EDX*256); getfromreg: reg=itok.number&255; for(i=0;i<2;i++){ if(reg==AX&&wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA3); // MOV [word],AX if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x89); op((unsigned int)reg*8+wtok.rm); outaddress(&wtok); } if(i==1)break; wtok.number+=4; compressoffset(&wtok); reg=itok.number/256; } warningreg(regs[1][EAX]); warningreg(regs[1][EDX]); ClearReg(AX); ClearReg(DX); retrez=tk_reg64; } break; case tk_minusminus: vop=0x8; case tk_plusplus: CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); incdec: op(0xFF); op(vop+wtok.rm); outaddress(&wtok); wtok.number+=4; compressoffset(&wtok); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0x83); op(0x10+vop+wtok.rm); outaddress(&wtok); op(0); break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_opperand){ if(tok==tk_number){ if(OnlyNumber(4)){ next=0; otok=tok; tok=tk_number; goto num; } } goto defxor; } else{ switch(tok){ case tk_number: case tk_postnumber: case tk_undefofs: case tk_apioffset: num: for(i=0;i<2;i++){ CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); if(tok==tk_number&&(itok.flag&f_reloc)==0&&(vop==0||vop==0x28)){ if(i==0&&itok.lnumber==1){ if(vop)vop=8; if(next==0)tok=otok; goto incdec; } if(itok.number==1){ op(0xFF); op((vop!=0?8:0)+wtok.rm); outaddress(&wtok); goto conl; } } if(i==1){ if(vop==0)vop+=0x10; else if(vop==0x28)vop-=0x10; } if(tok!=tk_apioffset&&tok!=tk_undefofs&&tok!=tk_postnumber&&(itok.flag&f_reloc)==0&& short_ok(itok.number,TRUE)){ op(0x83); op(vop+wtok.rm); outaddress(&wtok); op((unsigned int)itok.number); } else{ op(0x81); op(vop+wtok.rm); outaddress(&wtok); if(tok==tk_apioffset)AddApiToPost(itok.number); else{ if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); else if((itok.flag&f_reloc)!=0)AddReloc(); outdword(itok.number); } } conl: wtok.number+=4; compressoffset(&wtok); itok.lnumber>>=32; } if(next==0)tok=otok; break; case tk_reg64: reg=itok.number&255; for(i=0;i<2;i++){ if(i==1){ if(vop==0)vop+=0x10; else if(vop==0x28)vop-=0x10; } CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0x01+vop); op((unsigned int)reg*8+wtok.rm); outaddress(&wtok); if(i==1)break; wtok.number+=4; compressoffset(&wtok); reg=itok.number/256; } break; default: defxor: reg=EAX|(EDX*256); getintoreg64(reg); doregmath64(reg); CheckAllMassiv(wbuf,8,&wstr,&wtok); reg=EAX; for(i=0;i<2;i++){ op66(r32); op(0x01+vop); op(wtok.rm+reg*8); outaddress(&wtok); if(i==1)break; if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; reg=EDX; wtok.number+=4; compressoffset(&wtok); } next=0; retrez=tk_reg64; warningreg(regs[1][EAX]); warningreg(regs[1][EDX]); break; } } break; case tk_multequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper&&tok==tk_number&&(itok.flag&f_reloc)==0){ if(itok.lnumber==1)break; if(itok.lnumber==0){ ZeroReg(EAX,r32); ZeroReg(EDX,r32); goto getfromax; } if((i=caselong(itok.number))!=NUMNUM){ if(wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA1); // MOV EAX,[dword] if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x8B); op(wtok.rm); outaddress(&wtok); } wtok.number+=4; compressoffset(&wtok); ClearReg(AX); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,3); op(0x0F); op(0xA4+vop); op(wtok.rm); // SHLD [rmword],CL outaddress(&wtok); op(i); wtok.number-=4; compressoffset(&wtok); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0xC1); op(0x20+wtok.rm); outaddress(&wtok); op(i); break; } } CheckAllMassiv(wbuf,8,&wstr,&wtok); wtok.number+=4; compressoffset(&wtok); for(i=0;i<2;i++){ op66(r32); outseg(&wtok,2); op(0xFF); op(0x30+wtok.rm); outaddress(&wtok); if(i==1)break; wtok.number-=4; compressoffset(&wtok); } reg=ECX|(EAX*256); getintoreg64(reg); doregmath64(reg); CallExternProc("__llmul"); next=0; goto getfromax; case tk_divequals: getoperand(am32==TRUE?EAX:BX); if(itok2.type==tp_stopper&&tok==tk_number&&(itok.flag&f_reloc)==0){ if(itok.number==0){ DevideZero(); break; } if(itok.number==1)break; if((i=caselong(itok.number))!=NUMNUM){ wtok.number+=4; compressoffset(&wtok); if(wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA1); // MOV EAX,[dword] if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x8B); op(wtok.rm); outaddress(&wtok); } wtok.number-=4; compressoffset(&wtok); ClearReg(AX); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,3); op(0x0F); op(0xAC); op(wtok.rm); // SHLD [rmword],CL outaddress(&wtok); op(i); wtok.number+=4; compressoffset(&wtok); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(0xC1); op(0x28+wtok.rm); outaddress(&wtok); op(i); break; } unsigned long number; number=itok.lnumber>>32; for(i=0;i<2;i++){ op66(r32); if((itok.flag&f_reloc)==0&&short_ok(number,1)){ op(0x6A); op(number); } else{ op(0x68); if(i==0&&(itok.flag&f_reloc)!=0)AddReloc(); outdword(number); } if(i==1)break; number=itok.number; } goto divcont; } reg=EAX|(EDX*256); getintoreg64(reg); doregmath64(reg); op66(r32); op(0x50+EDX); op66(r32); op(0x50+EAX); next=0; divcont: addESP+=8; if(ESPloc&&am32&&wtok.segm==SS)wtok.number+=8; reg=EAX; for(i=0;i<2;i++){ if(reg==AX&&wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA1); if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x8B); op(reg*8+wtok.rm); outaddress(&wtok); } if(i==1)break; wtok.number+=4; compressoffset(&wtok); reg=EDX; } CallExternProc("__lludiv"); addESP-=8; wtok.number-=4; compressoffset(&wtok); goto getfromax; case tk_swap: int regdi; regdi=TRUE; getoperand(); rbuf=bufrm; bufrm=NULL; if(am32!=FALSE&&wbuf!=NULL&&wstr.bufstr!=NULL)regdi=FALSE; switch(tok){ case tk_reg64: CheckAllMassiv(wbuf,8,&wstr,&wtok); reg=itok.number&255; for(i=0;i<2;i++){ op66(r32); outseg(&wtok,2); op(0x87); op(reg*8+wtok.rm); outaddress(&wtok); ClearReg(reg); if(i==1)break; reg=itok.number/256; wtok.number+=4; compressoffset(&wtok); } break; case tk_qwordvar: for(i=0;i<2;i++){ getinto_e_ax(0,tk_dwordvar,&wtok,wbuf,&wstr,r32,TRUE); CheckAllMassiv(rbuf,8,&strinf,&itok,regdi==FALSE?BX:DI,DX); op66(r32); outseg(&itok,2); op(0x87); // XCHG AX,[wloc] op(itok.rm); outaddress(&itok); KillVar(itok.name); if(wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA3); /* MOV [word],AX */ if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); //???? else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x89); op(wtok.rm); /* MOV [rmword],AX */ outaddress(&wtok); } if(i==1)break; itok.number+=4; compressoffset(&itok); wtok.number+=4; compressoffset(&wtok); } warningreg(regs[1][EAX]); ClearReg(EAX); break; default: swaperror(); break; } break; case tk_rrequals: vop=8; wtok.number+=4; compressoffset(&wtok); case tk_llequals: getoperand(am32==TRUE?ECX:BX); if(itok2.type!=tp_stopper){ getintobeg(CL,&ofsstr); ClearReg(CX); warningreg(begs[1]); next=0; i=1; } else if(tok==tk_number){ i=0; } else{ if(tok!=tk_beg||(unsigned int)itok.number!=CL){ getintobeg(CL,&ofsstr); ClearReg(CX); warningreg(begs[1]); next=0; } i=1; } if(wbuf==NULL&&wstr.bufstr==NULL&& ((wtok.rm==rm_d16&&wtok.sib==CODE16)|| (wtok.rm==rm_d32&&(wtok.sib==CODE32||wtok.sib==0)))){ op66(r32); outseg(&wtok,1); op(0xA1); // MOV EAX,[dword] if(wtok.post==UNDEF_OFSET){ AddUndefOff(2,wtok.name); wtok.post=0; } if(am32==FALSE)outword(wtok.number); else outdword(wtok.number); } else{ CheckAllMassiv(wbuf,8,&wstr,&wtok,reg1,reg2); op66(r32); outseg(&wtok,2); op(0x8B); op(wtok.rm); outaddress(&wtok); } if(vop)wtok.number-=4; else wtok.number+=4; compressoffset(&wtok); ClearReg(AX); warningreg(regs[1][EAX]); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,3); op(0x0F); op(0xA4+vop+i); op(wtok.rm); // SHLD [rmword],CL outaddress(&wtok); if(i==0)op((unsigned int)itok.number); if(vop)wtok.number+=4; else wtok.number-=4; compressoffset(&wtok); CheckAllMassiv(wbuf,8,&wstr,&wtok); op66(r32); outseg(&wtok,2); op(i==0?0xC1:0xD3); op(0x20+vop+wtok.rm); outaddress(&wtok); if(i==0)op(itok.number); break; default: operatorexpected(); break; } KillVar(wtok.name); if(next)nexttok(); if(terminater==tk_semicolon)seminext(); if(cpu<3)cpu=3; return retrez; } void Select2FreeReg(int r1,int r2,int *reg1,int *reg2) { *reg1=idxregs[0]; *reg2=idxregs[1]; if(r1==idxregs[0]){ if(r2==idxregs[1]){ *reg1=idxregs[2]; *reg2=idxregs[3]; } else{ *reg1=idxregs[1]; if(r2==idxregs[2])*reg2=idxregs[3]; else *reg2=idxregs[2]; } } if(r1==idxregs[1]){ if(r2==idxregs[0]){ *reg1=idxregs[2]; *reg2=idxregs[3]; } else{ *reg1=idxregs[0]; if(r2==idxregs[2])*reg2=idxregs[3]; else *reg2=idxregs[2]; } } } void doreg64(int reg,int terminater) { unsigned char next=1; int vop=0,sign=0; int i; int reg1,reg2; unsigned long long ii; int r1,r2; char *ofsstr=NULL; int rettype; int pointr=0; int numpointr=0; rettype=tk_qword; r1=reg&255; r2=reg/256; Select2FreeReg(r1,r2,®1,®2); if(r1==ESP||r2==ESP)RestoreStack(); nexttok(); switch(tok){ case tk_assign://= nexttok(); /*-----------------31.08.05 18:39------------------- --------------------------------------------------*/ convert_type(&sign,(int *)&rettype,&pointr); while(tok==tk_mult){ nexttok(); numpointr++; } if(numpointr>itok.npointr){ unuseableinput(); } CheckMinusNum(); if(tok==tk_number){ //проверка и суммирование чисел switch(rettype){ case tk_float: sign=2; break; case tk_double: sign=3; break; case tk_qword: sign=4; break; } if(OnlyNumber(sign)){ MovRegNum(r32,postnumflag&f_reloc,itok.number,r1); MovRegNum(r32,0,itok.lnumber>>32,r2); next=0; break; } } if(rettype==tk_float||rettype==tk_double){ doeaxfloatmath(tk_stackstart,0,rettype==tk_float?0:4); op66(r32); op(0x58+r1); op66(r32); if(rettype==tk_float){ op(0x31); op(0xC0+r2*9); } else op(0x58+r2); next=0; break; } /*-----------------31.08.05 18:39------------------- --------------------------------------------------*/ getintoreg64(reg); doregmath64(reg); next=0; break; case tk_plusplus: op66(r32); op(0x40+r1); op66(r32); op(0x83); op(0xD0+r2); op(0); break; case tk_minusminus: op66(r32); op(0x48+r1); op66(r32); op(0x83); op(0xD8+r2); op(0); break; case tk_swap: getoperand(reg1); switch(tok){ case tk_qwordvar: reg=r1; for(i=0;i<2;i++){ CheckAllMassiv(bufrm,8,&strinf,&itok,reg1,reg2); op66(r32); outseg(&itok,2); op(0x87); op(reg*8+itok.rm); outaddress(&itok); itok.number+=4; compressoffset(&itok); reg=r2; } break; case tk_reg64: reg=r1; vop=itok.number; itok.number&=255; for(i=0;i<2;i++){ if(reg!=(int)itok.number){ if(RegSwapReg(reg,itok.number,r32)==NOINREG){; op66(r32); if(reg==AX)op(0x90+(unsigned int)itok.number); else if((unsigned int)itok.number==AX)op(0x90+reg); else{ op(0x87); op(0xC0+(unsigned int)itok.number+reg*8); } } else waralreadinitreg(regs[1][reg],regs[1][itok.number]); } reg=r2; itok.number=vop/256; } break; default: swaperror(); break; } break; case tk_xorequals: vop+=0x08; case tk_minusequals: vop+=0x08; case tk_andequals: vop+=0x18; case tk_orequals: vop+=0x08; case tk_plusequals: if(CheckAddOnly()){ inptr2--; cha2=' '; if(tok==tk_plusequals)tok=tk_plus; else tok=tk_minus; doregmath64(reg); next=0; break; } getoperand(reg1); if(itok2.type==tp_opperand&&tok!=tk_number&&tok!=tk_undefofs&& tok!=tk_postnumber)goto defadd; CheckMinusNum(); idrec *rrec; int opost; i=tok; switch(tok){ case tk_postnumber: case tk_undefofs: ii=itok.number; rrec=itok.rec; opost=itok.post; char uname[IDLENGTH]; strcpy(uname,itok.name); if(itok.flag&f_extern)goto addnum; tok=tk_number; case tk_number: ii=doconstqwordmath(); next=0; if(itok.type==tp_opperand){ sign=reg1|(reg2*256); if(i==tk_postnumber||i==tk_undefofs){ op66(r32); op(0xB8+r1); // MOV reg,# if(i==tk_postnumber)(postnumflag&f_extern)==0?setwordpost(&itok):setwordext((long *)&ii); else{ if((postnumflag&f_reloc)!=0)AddReloc(); if(i==tk_undefofs)AddUndefOff(2,uname); } outdword(ii); ZeroReg(r2,r32); } else{ MovRegNum(r32,postnumflag&f_reloc,ii,reg1); MovRegNum(r32,postnumflag&f_reloc,ii>>=32,reg2); } doregmath64(sign); itok.number=sign; goto addreg; } if((postnumflag&f_reloc)==0&&i!=tk_undefofs&&i!=tk_postnumber){ optnumadd64(ii,r1,r2,vop); break; } addnum: op66(r32); if(r1==AX)op(0x05+vop); else{ op(0x81); op(0xC0+vop+r1); } itok.rec=rrec; itok.post=opost; if(i==tk_postnumber)(postnumflag&f_extern)==0?setwordpost(&itok):setwordext((long *)&ii); else{ if((postnumflag&f_reloc)!=0)AddReloc(); if(i==tk_undefofs)AddUndefOff(2,uname); } outdword(ii); ii>>=32; if(vop==0)vop=0x10; else if(vop==0x28)vop=0x18; op66(r32); if(r2==AX)op(0x05+vop); else{ op(0x81); op(0xC0+vop+r2); } outdword(ii); break; case tk_longvar: case tk_dwordvar: CheckAllMassiv(bufrm,4,&strinf,&itok,reg1,reg2); op66(r32); outseg(&itok,2); op(0x03+vop); op(r1*8+itok.rm); outaddress(&itok); if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } break; case tk_qword: CheckAllMassiv(bufrm,4,&strinf,&itok,reg1,reg2); reg=r1; for(i=0;i<2;i++){ op66(r32); outseg(&itok,2); op(0x03+vop); op(reg*8+itok.rm); outaddress(&itok); if(i==1)break; reg=r2; itok.number+=4; compressoffset(&itok); } break; case tk_reg64: addreg: reg=r1; reg2=itok.number&255; for(i=0;i<2;i++){ op66(r32); op(0x01+vop); op(0xC0+reg+reg2*8); if(i==1)break; if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; reg2=itok.number/256; reg=r2; } break; case tk_reg32: op66(r32); op(0x01+vop); op(0xC0+reg+(unsigned int)itok.number*8); if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: unsigned char oaddstack; oaddstack=addstack; if(r1==EAX||r2==EAX){ op66(r32); op(0x50); //push AX warningreg(regs[1][EAX]); addESP+=4; ClearReg(EAX); addstack=FALSE; } if(r1==EDX||r2==EDX){ op66(r32); op(0x50+EDX); //push DX addESP+=4; warningreg(regs[1][EDX]); ClearReg(EDX); addstack=FALSE; } procdo(tk_qword); addstack=oaddstack; if(itok2.type==tp_opperand){ nexttok(); doregmath64(EAX|(EDX*256)); next=0; } if(r1==EDX||r2==EDX){ op66(r32); op(0x89); op(0xC0+reg2+EDX*8); //mov reg,EDX op66(r32); op(0x58+EDX); //pop dx addESP-=4; } else reg2=EDX; if(r1==EAX||r2==EAX){ op66(r32); op(0x89); op(0xC0+reg1+EAX*8); //mov reg,EAX op66(r32); op(0x58); //pop ax addESP-=4; } else reg1=EAX; op66(r32); op(0x01+vop); op(0xc0+r1+reg1*8); //add reg,ax if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; op66(r32); op(0x01+vop); op(0xc0+r2+reg2*8); //add reg,ax break; case tk_bytevar: case tk_charvar: case tk_beg: case tk_reg: case tk_intvar: case tk_wordvar: defadd: sign=reg1|(reg2*256); getintoreg64(sign); doregmath64(sign); warningreg(regs[1][reg1]); warningreg(regs[1][reg2]); ClearReg(reg1); ClearReg(reg2); op66(r32); op(0x01+vop); op(0xc0+r1+reg1*8); //add reg,ax if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; op66(r32); op(0x01+vop); op(0xc0+r2+reg2*8); //add reg,ax next=0; break; default: valueexpected(); break; } break; case tk_rrequals: vop+=0x08; case tk_llequals: getoperand(reg1); CheckMinusNum(); if(tok==tk_number){ ii=doconstqwordmath(); next=0; if(itok.type==tp_opperand){ if(r1==ECX||r2==ECX)regshifterror(); op(0xB0+CL); op(ii); //mov CL,num ConstToReg(ii,CL,r8); dobegmath(CL); warningreg(begs[1]); ClearReg(CL); goto shiftcl; } if(vop){ reg=r1; r1=r2; r2=reg; } if(ii<32){ op66(r32); op(0x0F); op(0xA4+vop); op(0xC0+r2+r1*8); op(ii); op66(r32); if(ii==1){ op(0xD1); op(0xE0+r1+vop); } else{ op(0xC1); op(0xE0+r1+vop); //shl ax,num op(ii); } } else{ op66(r32); op(0x89); op(0xC0+r2+r1*8); ii-=32; if(ii!=0){ op66(r32); if(ii==1){ op(0xD1); op(0xE0+vop+r1); //shr ax,1 } else{ op(0xC1); op(0xE0+r2+vop); //shl ax,num op(ii); } } ZeroReg(r1,r32); } } else if(reg!=CX){ if(!(itok2.type==tp_stopper&&(tok==tk_beg||tok==reg||tok==tk_reg32)&&itok.number==CL)){ getintobeg(CL,&ofsstr); dobegmath(CL); warningreg(begs[1]); ClearReg(CL); next=0; } shiftcl: op66(r32); op(0x0F); op(0xA5+vop); if(vop){ reg=r1; r1=r2; r2=reg; } op(0xC0+r2+r1*8); op66(r32); op(0xD3); op(0xE0+vop+r1); // SHL xXX,CL } else regshifterror(); break; case tk_multequals: getoperand(reg1); CheckMinusNum(); if(tok==tk_number){ ii=doconstqwordmath(); next=0; if(itok.type==tp_opperand){ op66(r32); op(0x50+r2); op66(r32); op(0x50+r1); addESP+=8; MovRegNum(r32,postnumflag&f_reloc,ii,reg1); MovRegNum(r32,0,ii>>32,reg2); ConstToReg(ii,reg1,r32); ConstToReg(ii>>32,reg2,r32); doregmath64(reg1|(reg2*256)); goto mul; } i=0; if((postnumflag&f_reloc)==0){ if(ii==0){ ZeroReg(r1,r32); ZeroReg(r2,r32); break; } if(ii==1)break; if(ii==2){ op66(r32); op(1); op(0xC0+9*r1); // ADD r1,r1 op66(r32); op(0x83); op(0xC2+r2*8); //adc r2,0 op(0); break; } if((i=caselonglong(ii))!=NUMNUM64){ if(i<32){ op66(r32); outword(0xA40F); op(0xC0+r2+r1*8); op(i); op66(r32); op(0xC1); op(0xE0+r1); //shl ax,num op(i); } else{ op66(r32); op(0x89); op(0xC0+r2+r1*8); i-=32; if(i!=0){ op66(r32); if(i==1){ op(1); op(0xC0+r2*9); //add reg,reg } else{ op(0xC1); op(0xE0+r2); //shl ax,num op(i); } } ZeroReg(r1,r32); } break; } } op66(r32); op(0x50+r2); op66(r32); op(0x50+r1); addESP+=8; MovRegNum(r32,postnumflag&f_reloc,ii,ECX); MovRegNum(r32,0,ii>>32,EAX); goto mul; } op66(r32); op(0x50+r2); op66(r32); op(0x50+r1); addESP+=8; reg=ECX|(EAX*256); warningreg(regs[1][ECX]); getintoreg64(reg); doregmath64(reg); mul: CallExternProc("__llmul"); addESP-=8; endmul: ClearReg(EAX); warningreg(regs[1][EAX]); ClearReg(EDX); warningreg(regs[1][EDX]); next=0; if(r1!=EAX){ if(r1==EDX){ if(r2==EAX){ op66(r32); op(0x90+EDX); break; } op66(r32); op(0x89); op(0xC0+r2+EDX*8); //mov reg,EDX op66(r32); op(0x89); op(0xC0+r1+EAX*8); //mov reg,EAX break; } op66(r32); op(0x89); op(0xC0+r1+EAX*8); //mov reg,EAX } if(r2!=EDX){ op66(r32); op(0x89); op(0xC0+r2+EDX*8); //mov reg,EDX } break; case tk_divequals: getoperand(reg1); CheckMinusNum(); if(tok==tk_number){ ii=doconstqwordmath(); next=0; if(itok.type==tp_opperand){ MovRegNum(r32,postnumflag&f_reloc,ii,reg1); MovRegNum(r32,0,ii>>32,reg2); ConstToReg(ii,reg1,r32); ConstToReg(ii>>32,reg2,r32); doregmath64(reg1|(reg2*256)); op66(r32); op(0x50+reg2); op66(r32); op(0x50+reg1); addESP+=8; warningreg(regs[1][reg1]); warningreg(regs[1][reg2]); goto divcont; } if((postnumflag&f_reloc)==0){ if(ii==0){ DevideZero(); break; } if(ii==1)break; if((i=caselonglong(ii))!=NUMNUM64){ if(i<32){ op66(r32); outword(0xAC0F); op(0xC0+r1+r2*8); op(i); op66(r32); op(0xc1); op(0xe8+r2); // SHR reg,imm8 op(i); } else{ op66(r32); op(0x89); op(0xC0+r1+r2*8); i-=32; if(i!=0){ op66(r32); if(i==1){ op(0xD1); op(0xE8+r1); //shr ax,1 } else{ op(0xC1); op(0xE8+r1); //shr ax,num op(i); } } ZeroReg(r2,r32); } break; } } unsigned long number; number=ii>>32; for(i=0;i<2;i++){ op66(r32); if((postnumflag&f_reloc)==0&&short_ok(number,1)){ op(0x6A); op(number); } else{ op(0x68); if(i==0&&(postnumflag&f_reloc)!=0)AddReloc(); outdword(number); } if(i==1)break; number=ii; } addESP+=8; goto divcont; } reg=reg1|(reg2*256); getintoreg64(reg); doregmath64(reg); op66(r32); op(0x50+reg2); op66(r32); op(0x50+reg1); addESP+=8; warningreg(regs[1][reg1]); warningreg(regs[1][reg2]); next=0; divcont: if(r1!=EAX){ if(r2==EAX){ if(r1==EDX){ op66(r32); op(0x90+EDX); goto sdiv; } op66(r32); op(0x89); op(0xC0+EDX+r2*8); //mov EDX,r2 op66(r32); op(0x89); op(0xC0+EAX+r1*8); //mov EAX,r1 goto sdiv; } op66(r32); op(0x89); op(0xC0+EAX+r1*8); //mov EAX,r1 } if(r2!=EDX){ op66(r32); op(0x89); op(0xC0+EDX+r2*8); //mov EDX,r2 } sdiv: CallExternProc("__lludiv"); addESP-=8; goto endmul; default: operatorexpected(); break; } ClearReg(r1); ClearReg(r2); if(next)nexttok(); if(terminater==tk_semicolon)seminext(); if(cpu<3)cpu=3; } void optnumadd64(unsigned long long num,int r1,int r2,int vop) { int i,reg; if(num==0){ if(vop==0x20){ //&= reg=r1; for(i=0;i<2;i++){ ZeroReg(reg,r32); reg=r2; } setzeroflag=TRUE; } return; //+= -= |= ^= } if(num==1){ if(vop==0x28){ //-= op66(r32); op(0x48+r1); op66(r32); op(0x83); op(0xD8+r2); op(0); setzeroflag=TRUE; return; } if(vop==0){ //+= op66(r32); op(0x40+r1); op66(r32); op(0x83); op(0xD0+r2); op(0); setzeroflag=TRUE; return; } } if(vop==8){ //|= if(num<65536){ if((unsigned short)num<256&&r1<4){ if(r1==AX)op(0x0C); else{ op(0x80); op(0xc8+r1); } op(num); return; } op66(r16); if(r1==AX)op(0x0D); else{ op(0x81); op(0xc8+r1); } outword(num); return; } if(num<0x100000000LL){ op66(r32); if(r1==AX)op(0x0D); else{ op(0x81); op(0xc8+r1); } outdword(num); return; } } if(vop==0x20){ //&= if(num>=0xFFFFFFFF00000000LL){ if((unsigned long)num>=0xFFFF0000){ if((unsigned short)num>=0xFF00&&r1<4){ if(r1==AL)op(0x24); else{ op(128); op(0xE0+r1); } op(num); return; } op66(r16); if(r1==AX)op(0x25); else{ op(129); op(0xE0+r1); } outword(num); return; } op66(r32); if(r1==AX)op(0x25); else{ op(129); op(0xE0+r1); } outdword(num); return; } } reg=r1; int j=0; for(i=0;i<2;i++){ if((unsigned long)num==0)j++; if(optnumadd(num,reg,r32,vop)==FALSE){ op66(r32); if(short_ok((unsigned long)num,TRUE)){ op(0x83); op(0xC0+vop+reg); op(num); } else{ if(reg==EAX)op(5+vop); else{ op(0x81); op(0xC0+vop+reg); } outdword(num); } } num>>=32; if(j==0&&(vop==0||vop==0x28)){ if(vop)vop=8; op66(r32); if(short_ok((unsigned long)num,TRUE)){ op(0x83); op(0xD0+vop+r2); op(num); } else{ if(r2==EAX)op(0x15+vop); else{ op(0x81); op(0xD3+vop+r2); } outdword(num); } break; } reg=r2; } setzeroflag=TRUE; } void doregmath64(int reg) { int vop,i,optnum,negflag=FALSE; int r1,r2,next=1; int reg1,reg2; char *ofsstr=NULL; r1=reg&255; r2=reg/256; Select2FreeReg(r1,r2,®1,®2); while(itok.type!=tp_stopper&&tok!=tk_eof){ if(negflag){ op66(r32); op(0xF7); op(0xD8+r2); // NEG reg op66(r32); op(0xF7); op(0xD8+r1); // NEG reg op66(r32); op(0x83); op(0xD8+r2); op(0); ClearReg(r1); ClearReg(r2); negflag=FALSE; } vop=0; next=1; optnum=FALSE; if(tok2==tk_number)optnum=OptimNum(); switch(tok){ case tk_xor: vop+=0x08; case tk_minus: vop+=0x08; case tk_and: vop+=0x18; case tk_or: vop+=0x08; case tk_plus: if(optnum==FALSE)getoperand(reg1); else tok=tk_number; switch(tok){ case tk_number: if((itok.flag&f_reloc)==0){ optnumadd64(itok.lnumber,r1,r2,vop); break; } case tk_postnumber: case tk_undefofs: case tk_apioffset: op66(r32); op(0x81); op(0xC0+vop+r1); if(tok==tk_apioffset)AddApiToPost(itok.number); else{ if(tok==tk_postnumber)(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); else if(tok==tk_undefofs)AddUndefOff(0,itok.name); else if((itok.flag&f_reloc)!=0)AddReloc(); outdword(itok.number); } if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } break; case tk_rmnumber: case tk_charvar: case tk_beg: case tk_bytevar: getintoreg_32(reg2,r32,0,&ofsstr,FALSE); op66(r32); op(0x01+vop); op(0xC0+r1+reg2*8); /* OPT AX,CX */ if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } warningreg(regs[r32/2-1][reg2]); next=0; break; case tk_reg: op66(r32); outword(0xB70F); if(itok.number==r1||itok.number==r2)itok.number=reg1; op(0xC0+itok.number*9); warningreg(regs[1][itok.number]); case tk_reg32: defreg32: op66(r32); op(0x01+vop); op(0xC0+r1+(unsigned int)itok.number*8); if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } break; case tk_reg64: int reg2; reg=r1; reg2=itok.number&255; for(i=0;i<2;i++){ op66(r32); op(0x01+vop); op(0xC0+reg+reg2*8); if(i==1)break; if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; reg2=itok.number/256; reg=r2; } break; case tk_longvar: case tk_dwordvar: CheckAllMassiv(bufrm,4,&strinf); op66(r32); outseg(&itok,2); op(0x03+vop); op(r1*8+itok.rm); outaddress(&itok); if(vop==0x20){ //&= ZeroReg(r2,r32); } else{ if(vop==0||vop==0x28){ if(vop)vop=8; op66(r32); op(0x83); op(0xD0+vop+r2); op(0); } } break; case tk_qwordvar: reg=r1; for(i=0;i<2;i++){ CheckAllMassiv(bufrm,8,&strinf); op66(r32); outseg(&itok,2); op(0x03+vop); op(reg*8+itok.rm); outaddress(&itok); if(i==1)break; if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; itok.number+=4; compressoffset(&itok); reg=r2; } break; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: procdo(tk_qword); op66(r32); op(0x01+vop); op(0xc0+r1); warningreg(regs[1][0]); if(vop==0)vop=0x10; if(vop==0x28)vop=0x18; op66(r32); op(0x01+vop); op(0xc0+r2+EDX*8); warningreg(regs[1][EDX]); break; default: valueexpected(); break; } break; case tk_rrminus: if(r1==ECX||r2==ECX){ regshifterror(); break; } tok=tk_minus; goto rshift2; case tk_rr: getoperand(ECX); if(tok==tk_number){ op66(r32); outword(0xAC0F); op(0xC0+r1+r2*8); op(itok.number); op66(r32); if((unsigned int)itok.number==1){ op(0xD1); op(0xE8+r2); // SHR reg,1 } else if((unsigned int)itok.number!=0){ op(0xc1); op(0xe8+r2); // SHR reg,imm8 op((unsigned int)itok.number); } } else if(r1==ECX||r2==ECX)regshifterror(); else if((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&itok.number==CL)goto rshift; else{ rshift2: getintobeg(CL,&ofsstr); next=0; warningreg(begs[1]); rshift: op66(r32); outword(0xAD0F); op(0xC0+r1+r2*8); op66(r32); op(0xD3); op(0xE8+r2); // SHL xXX,CL } break; case tk_llminus: if(r1==ECX||r2==ECX){ regshifterror(); break; } tok=tk_minus; goto llshift; case tk_ll: getoperand(ECX); if(tok==tk_number){ op66(r32); outword(0xA40F); op(0xC0+r2+r1*8); op(itok.number); op66(r32); if((unsigned int)itok.number==1){ op(1); op(0xC0+r1*9); //add reg,reg } else{ op(0xC1); op(0xE0+r1); //shl ax,num op(itok.number); } } else if(r1==ECX||r2==ECX)regshifterror(); else if((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&itok.number==CL)goto lshift; else{ llshift: getintobeg(CL,&ofsstr); next=0; warningreg(begs[1]); lshift: op66(r32); outword(0xA50F); op(0xC0+r2+r1*8); op66(r32); op(0xD3); op(0xE0+r1); // SHL xXX,CL } break; case tk_multminus: negflag=TRUE; case tk_mult: getoperand(reg1); if(negflag&&tok==tk_number){ itok.lnumber=-itok.lnumber; negflag=FALSE; } if(tok==tk_number&&((itok.number&f_reloc)==0)){ if(itok.lnumber==0){ ZeroReg(r1,r32); ZeroReg(r2,r32); break; } if(itok.lnumber==1)break; if(itok.lnumber==2){ op66(r32); op(1); op(0xC0+9*r1); // ADD r1,r1 op66(r32); op(0x83); op(0xC2+r2*8); //adc r2,0 op(0); break; } if((i=caselonglong(itok.lnumber))!=NUMNUM64){ if(i<32){ op66(r32); outword(0xA40F); op(0xC0+r2+r1*8); op(i); op66(r32); op(0xC1); op(0xE0+r1); //shl ax,num op(i); } else{ op66(r32); op(0x89); op(0xC0+r2+r1*8); i-=32; if(i!=0){ op66(r32); if(i==1){ op(1); op(0xC0+r2*9); //add reg,reg } else{ op(0xC1); op(0xE0+r2); //shl ax,num op(i); } } ZeroReg(r1,r32); } break; } op66(r32); op(0x50+r2); op66(r32); op(0x50+r1); addESP+=8; MovRegNum(r32,postnumflag&f_reloc,itok.number,ECX); MovRegNum(r32,0,itok.lnumber>>32,EAX); goto mul; } //вызов процедуры __llmul op66(r32); op(0x50+r2); op66(r32); op(0x50+r1); addESP+=8; reg=ECX|(EAX*256); getintoreg64(reg); // doregmath64(reg); next=0; mul: CallExternProc("__llmul"); addESP-=8; endmul: if(r1!=EAX){ if(r1==EDX){ if(r2==EAX){ op66(r32); op(0x90+EDX); break; } op66(r32); op(0x89); op(0xC0+r2+EDX*8); //mov reg,EDX op66(r32); op(0x89); op(0xC0+r1+EAX*8); //mov reg,EAX break; } op66(r32); op(0x89); op(0xC0+r1+EAX*8); //mov reg,EAX } if(r2!=EDX){ op66(r32); op(0x89); op(0xC0+r2+EDX*8); //mov reg,EDX } break; case tk_modminus: negflag=TRUE; case tk_mod: vop=1; goto divcalc;; case tk_divminus: negflag=TRUE; case tk_div: divcalc: getoperand(reg1); if(negflag&&tok==tk_number){ itok.lnumber=-itok.lnumber; negflag=FALSE; } if(tok==tk_number&&((itok.flag&f_reloc)==0)){ if(itok.lnumber==0){ DevideZero(); break; } if(itok.lnumber==1){ if(vop){ //mod ZeroReg(r1,r32); ZeroReg(r2,r32); } break; } if((i=caselonglong(itok.lnumber))!=NUMNUM64){ if(vop){ //mod optnumadd64(itok.lnumber-1,r1,r2,0x20); } else{ if(i<32){ op66(r32); outword(0xAC0F); op(0xC0+r1+r2*8); op(i); op66(r32); op(0xc1); op(0xe8+r2); // SHR reg,imm8 op(i); } else{ op66(r32); op(0x89); op(0xC0+r1+r2*8); i-=32; if(i!=0){ op66(r32); if(i==1){ op(0xD1); op(0xE8+r1); //shr ax,1 } else{ op(0xC1); op(0xE8+r1); //shr ax,num op(i); } } ZeroReg(r2,r32); } } break; } unsigned long number; number=itok.lnumber>>32; for(i=0;i<2;i++){ op66(r32); if((itok.flag&f_reloc)==0&&short_ok(number,1)){ op(0x6A); op(number); } else{ op(0x68); if(i==0&&(itok.flag&f_reloc)!=0)AddReloc(); outdword(number); } if(i==1)break; number=itok.number; } addESP+=8; goto divcont; } reg=reg1|(reg2*256); getintoreg64(reg); op66(r32); op(0x50+reg2); op66(r32); op(0x50+reg1); addESP+=8; next=0; divcont: if(r1!=EAX){ if(r2==EAX){ if(r1==EDX){ op66(r32); op(0x90+EDX); goto sdiv; } op66(r32); op(0x89); op(0xC0+EDX+r2*8); //mov EDX,r2 op66(r32); op(0x89); op(0xC0+EAX+r1*8); //mov EAX,r1 goto sdiv; } op66(r32); op(0x89); op(0xC0+EAX+r1*8); //mov EAX,r1 } if(r2!=EDX){ op66(r32); op(0x89); op(0xC0+EDX+r2*8); //mov EDX,r2 } sdiv: CallExternProc((char*)(vop==0?"__lludiv":"__llumod")); addESP-=8; goto endmul; default: operatorexpected(); break; } if(next)nexttok(); } ClearReg(r1); ClearReg(r2); if(cpu<3)cpu=3; } void getintoreg64(int reg) { int negflag=0,next=1,i=0; unsigned long long holdnumber=0; int r1,r2; int reg1,reg2; r1=reg&255; r2=reg/256; Select2FreeReg(r1,r2,®1,®2); if(tok==tk_minus){ if(CheckMinusNum()==FALSE){ negflag=1; getoperand(am32==FALSE?BX:r1); } } switch(tok){ case tk_number: holdnumber=CalcNumber(4); MovRegNum(r32,postnumflag&f_reloc,holdnumber,r1); MovRegNum(r32,0,holdnumber>>32,r2); next=0; break; case tk_postnumber: case tk_undefofs: case tk_apioffset: op66(r32); op(0xB8+r1); /* MOV AX,# */ if(tok==tk_apioffset)AddApiToPost(itok.number); else{ if(tok==tk_undefofs)AddUndefOff(0,itok.name); else (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); tok=tk_number; holdnumber+=doconstdwordmath(); outdword(holdnumber); MovRegNum(r32,0,holdnumber>>32,r2); next=0; } ClearReg(r1); ClearReg(r2); break; case tk_rmnumber: CheckAllMassiv(bufrm,8,&strinf,&itok,reg1,reg2); if(!(am32&&itok.rm==r1&&r1!=EBP&&r1!=ESP)){ op66(r32); op67(itok.sib==CODE16?r16:r32); if(itok.post==0)outseg(&itok,2); op(0x8D); // LEA reg,[rm] op(r1*8+itok.rm); if(itok.post!=0&&itok.post!=UNDEF_OFSET){ if((itok.flag&f_extern)==0){ unsigned int ooutptr=outptr; if(am32&&itok.rm==rm_sib)outptr++; setwordpost(&itok); outptr=ooutptr; } else setwordext(&itok.number); } outaddress(&itok); ClearReg(r1); } ZeroReg(r2,r32); break; case tk_qwordvar: reg=r1; for(i=0;i<2;i++){ if(reg==EAX&&((itok.rm==rm_d16&&itok.sib==CODE16)||(itok.rm==rm_d32&&(itok.sib==CODE32||itok.sib==0)))){ op66(r32); outseg(&itok,1); op(0xA1); if(itok.post==UNDEF_OFSET)AddUndefOff(2,itok.name); if(am32==FALSE)outword((unsigned int)itok.number); else outdword(itok.number); } else{ CheckAllMassiv(bufrm,8,&strinf,&itok,reg1,reg2); op66(r32); outseg(&itok,2); op(0x8B); op(reg*8+itok.rm); outaddress(&itok); } ClearReg(reg); if(i==1)break; itok.number+=4; compressoffset(&itok); reg=r2; } break; case tk_longvar: case tk_dwordvar: if(reg==EAX&&((itok.rm==rm_d16&&itok.sib==CODE16)||(itok.rm==rm_d32&&(itok.sib==CODE32||itok.sib==0)))){ op66(r32); outseg(&itok,1); op(0xA1); if(itok.post==UNDEF_OFSET)AddUndefOff(2,itok.name); if(am32==FALSE)outword((unsigned int)itok.number); else outdword(itok.number); } else{ CheckAllMassiv(bufrm,4,&strinf,&itok,reg1,reg2); op66(r32); outseg(&itok,2); op(0x8B); op(r1*8+itok.rm); outaddress(&itok); } ZeroReg(r2,r32); ClearReg(r1); break; case tk_intvar: case tk_wordvar: CheckAllMassiv(bufrm,2,&strinf,&itok,reg1,reg2); if(tok==tk_wordvar&&optimizespeed&&chip>3&&chip<7&&RmEqualReg(reg,itok.rm,itok.sib)==FALSE){ ZeroReg(r1,r32); op66(r16); outseg(&itok,2); //mov reg,var op(0x8B); } else{ op66(r32); outseg(&itok,3); //movxx reg,var op(0x0F); op(tok==tk_wordvar?0xB7:0xBF); } op(r1*8+itok.rm); outaddress(&itok); ClearReg(r1); ZeroReg(r2,r32); break; case tk_bytevar: case tk_charvar: CheckAllMassiv(bufrm,1,&strinf,&itok,reg1,reg2); if(reg<=EBX&&tok==tk_bytevar&&optimizespeed&&chip>3&&chip<7&&RmEqualReg(reg,itok.rm,itok.sib)==FALSE){ ZeroReg(r1,r32); outseg(&itok,2); op(0x8A); } else{ op66(r32); outseg(&itok,3); op(0xf); if(tok==tk_bytevar)op(0xb6); else op(0xbe); } op(r1*8+itok.rm); // MOVZX regL,[byte] outaddress(&itok); ClearReg(r1); ZeroReg(r2,r32); break; case tk_reg: if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=itok.number; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(r16); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ itok.number=0; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif } if(optimizespeed&&chip>3&&chip<7&®!=(int)itok.number){ ZeroReg(r1,r32); op(0x89); op(0xC0+r1+(unsigned int)itok.number*8); } else{ op66(r32); outword(0xB70F); op(0xC0+r1*8+(unsigned int)itok.number); } RegToReg(r1,itok.number,r32); ZeroReg(r2,r32); break; case tk_reg32: if(tok2==tk_openbracket){ //вызов процедуры по адресу в регистре reg1=itok.number; nexttok(); param[0]=0; if(comfile==file_w32)swapparam(); else doparams(); op66(r32); op(0xFF); op(0xD0+reg1); /* CALL reg with stack params */ itok.number=0; clearregstat(); #ifdef OPTVARCONST FreeGlobalConst(); #endif } if(r1!=(int)itok.number){ op66(r32); op(0x89); op(0xC0+r1+(unsigned int)itok.number*8); RegToReg(r1,itok.number,r32); } ZeroReg(r2,r32); break; case tk_reg64: reg1=itok.number&255; reg2=itok.number/256; movreg64: if(r1==reg2){ if(r2==reg1){ op66(r32); if(r1==AX)op(0x90+r2); else if(r2==AX)op(0x90+r1); else{ op(0x87); op(0xC0+r1+r2*8); } break; } int temp; temp=r2; r2=r1; r1=temp; temp=reg2; reg2=reg1; reg1=temp; } if(r2==reg1){ int temp; temp=r2; r2=r1; r1=temp; temp=reg2; reg2=reg1; reg1=temp; } if(r1!=reg1){ op66(r32); op(0x89); op(0xC0+r1+reg1*8); RegToReg(r1,reg1,r32); } if(r2!=reg2){ op66(r32); op(0x89); op(0xC0+r2+reg2*8); RegToReg(r2,reg2,r32); } break; case tk_bits: int vops; i=itok.bit.siz+itok.bit.ofs; if(i<=64)vops=r64; if(i<=32)vops=r32; if(i<=16)vops=r16; bits2reg(r1,(r323&&chip<7&®<4&®!=(int)(itok.number%4)){ ZeroReg(r1,r32); op(0x88); op(0xC0+r1+(unsigned int)itok.number*8); // MOV regL,beg } else{ op66(r32); outword(0xb60f); op(0xC0+r1*8+(unsigned int)itok.number); // MOVZX regL,beg } ClearReg(reg); ZeroReg(r2,r32); break; case tk_at: getoperand(am32==FALSE?BX:reg); i++; case tk_ID: case tk_id: case tk_proc: case tk_apiproc: case tk_undefproc: case tk_declare: if((!i)||macros(tk_qword)==0)procdo(tk_qword); reg1=EAX; reg2=EDX; goto movreg64; case tk_string: op66(r32); op(0xB8+r1); outdword(addpoststring()); ClearReg(r1); ZeroReg(r2,r32); break; default: valueexpected(); break; } if(negflag){ op66(r32); op(0xF7); op(0xD8+r2); // NEG reg op66(r32); op(0xF7); op(0xD8+r1); // NEG reg op66(r32); op(0x83); op(0xD8+r2); op(0); ClearReg(r1); ClearReg(r2); } if(next)nexttok(); } void CallExternProc(char *name) { ITOK itok4; int tok4=tk_id; char string4[256]; struct idrec *ptrs; memset(&itok4,0,sizeof(ITOK)); strcpy(string4,name); searchtree(&itok4,&tok4,(unsigned char *)string4); ptrs=itok4.rec; switch(tok4){ case tk_id: tok4=tok; itok4=itok; strcpy((char *)itok.name,string4); string[0]=0; itok.flag=tp_stdcall; tok=tk_undefproc; itok.number=secondcallnum; itok.segm=NOT_DYNAMIC; itok.rm=tk_qword; itok.post=0; addtotree(itok.name); addacall(secondcallnum++,CALL_NEAR); tok=tok4; itok=itok4; callloc0(); break; case tk_declare: ptrs->rectok=tk_undefproc; case tk_undefproc: addacall(itok4.number,(unsigned char)(am32!=FALSE?CALL_32:CALL_NEAR)); callloc0(); /* produce CALL [#] */ break; case tk_proc: if(itok4.segm==DYNAMIC)itok4.segm=ptrs->recsegm=DYNAMIC_USED; if(itok4.segm