#define _TOKR_ #include "tok.h" char useasm=FALSE; char asmparam=FALSE; #include "asmnemon.h" void asmtwo1(int basecode); // used for ADD ADC SUB SBB CMP AND OR XOR. void asmregmem(int out1,int out2); // used for LEA LDS LES LFS LGS LSS. void Scanbit(int basecode); void CheckBit(int code); void asmone1(int basecode); // used for INC and DEC. void asmone2(int basecode); // used for NEG NOT MUL IMUL DIV IDIV. void asmshortjump(int shortcode,int nearcode); void lar_lsl(int code); unsigned char tabldeckr(int code); void protectinstr(int code,int code2); void doasmmov(); // do MOV void asmextend(int basecode); // procedure MOVSX and MOVZX void movd(); void movq(); void packMMX(int code,int code1,int code2); void asmshift(int basecode); // used for ROL ROR RCL RCR SHL SAL SHR SAR. void Shxd(int code); void FpuType1(unsigned int addrm); void FpuType2(unsigned int addrm,unsigned int addrm2); void FpuType3(unsigned int opcode,unsigned int addrm); void FpuType4(unsigned int opcode,unsigned int addrm); void FpuType5(unsigned int opcode,unsigned int addrm); void FpuType6(unsigned int opcode,unsigned int addrm); void FpuType7(unsigned int addrm); void FpuType8(unsigned int opcode,unsigned int addrm); void addlocaljump(int callkind); unsigned long SaveNumber(int type,int tok4,char *name); void cmov(int num); void mmxiii(int type); void prefetch(int code, int type); void pextrw(); void pinsrw(); void pshufw(); void xmminstr(int type,int sec,int op1=tk_xmmreg,int op2=tk_xmmreg); void xmm3instr(int type,int sec); void xmm2xmm(int code,int code2=0,int type=tk_xmmreg); void movxmm(int code,int code2,int addc=1); void movxmm2(int code,int code2=0); void movxmm3(int code,int code2=0,int type=tk_xmmreg); void movxmm4(int code,int code2); void shiftxmm(int rm); //rxmm,i8 void DDDW(int faradd); void AADM(int code); extern void shortjumperror(); extern void invalidfarjumpitem(); extern void invalidfarcallitem(); extern void bytedxexpected(); extern void axalexpected(); extern void clornumberexpected(); extern void reg32regexpected(int type); extern void begexpected(int type); extern void regexpected(int type); extern void invalidoperand(int type); extern void mmxregexpected(int type=0); extern void mmxregordwordexpected(int type); extern void mmxormem(int type); extern void reg32orword(int type); extern void xmmregorvarexpected(int type); extern void xmmregexpected(int type); extern void fpustakexpected(int type); extern void fpuvarexpected(int type); void doasm(int nexta) { unsigned char possiblecpu=0,next=1; int htok; ITOK hstok; char *hbuf; SINFO hstr; unsigned int i=0; int razr=r16; unsigned long hnumber; int faradd=0; if(nexta==FALSE){ useasm=TRUE; nexttok(); useasm=FALSE; } if(tok==tk_idasm){ htok=itok.rm; goto sw_asm; } if(tok==tk_ID||tok==tk_id||tok==tk_undefproc){ if(tok2==tk_colon){ //Ź„âȘ  if(tok==tk_undefproc)doanyundefproc(); else doid((char)(tok==tk_ID?1:0),tk_void); return; } strupr((char *)string); htok=FastSearch((unsigned char *)asmMnem,ofsmnem,0,(char *)string); sw_asm: asmparam=TRUE; switch(htok){ case a_add: //ADD case a_or: //OR case a_adc: //ADC case a_sbb: //SBB case a_and: //AND case a_sub: //SUB case a_xor: //XOR case a_cmp: //CMP asmtwo1(htok*8); next=0; break; case a_not: //NOT case a_neg: //NEG case a_mul: //MUL case a_div: //DIV case a_idiv: //IDIV asmone2((htok-a_not)*8+16); break; case a_rol: //ROL case a_ror: //ROR case a_rcl: //RCL case a_rcr: //RCR case a_shl: //SHL case a_shr: //SHR case a_sar: //SAR asmshift((htok-a_rol)*8); next=0; break; case a_btc: //BTC case a_btr: //BTR case a_bts: //BTS case a_bt: //BT CheckBit((htok-a_bt)*8); next=0; break; case a_dec: //DEC case a_inc: //INC asmone1((htok-a_inc)*8); break; case a_shrd: //SHRD case a_shld: //SHLD Shxd((htok-a_shld)*8+0xa4); next=0; break; case a_aaa: ClearReg(AX); op(0x37); //AAA break; case a_aad: ClearReg(AX); AADM(0xD5); //AAD break; case a_aam: ClearReg(AX); AADM(0xD4); //AAM break; case a_aas: ClearReg(AX); op(0x3F); //AAS break; case a_adrsiz: op(0x67); possiblecpu=3; break; case a_arpl: //ARPL nexttok(); htok=tok; hstok=itok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); if(tok!=tk_reg)regexpected(2); switch(htok){ case tk_intvar: case tk_wordvar: #ifdef OPTVARCONST ClearVarByNum(&hstok); #endif CheckAllMassiv(hbuf,2,&hstr,&hstok); KillVar(hstok.name); outseg(&hstok,2); op(0x63); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); break; case tk_reg: ClearReg(hstok.number); op(0x63); op(192+(unsigned int)itok.number*8+hstok.number); break; default: wordvalexpected(); } possiblecpu=2; break; case a_bound: //BOUND asmregmem(0x62,0); possiblecpu=2; break; case a_lea: asmregmem(0x8D,0); //LEA break; case a_lds: //LDS case a_les: //LES asmregmem(htok-a_les+0xC4,0); break; case a_lss: //LSS asmregmem(0xF,0xB2); possiblecpu=3; break; case a_lgs: //LGS case a_lfs: //LFS asmregmem(0xF,htok-a_lfs+0xB4); possiblecpu=3; break; case a_bswap: //BSWAP nexttok(); ClearReg(itok.number); if(tok==tk_reg32||tok==tk_reg){ op66(tok==tk_reg?r16:r32); op(0x0F); op(0xC8+(unsigned int)itok.number); } else preerror("Expecting 32 bit Register for BSWAP"); possiblecpu=4; break; case a_bsf: //BSF case a_bsr: //BSR Scanbit(htok-a_bsf+0xbc); break; case a_call: //CALL nexttok(); htok=0; if(tok==tk_ID||tok==tk_id){ if(stricmp("FAR",(char *)string)==0){ nexttok(); faradd=8; htok=1; } else if(stricmp("NEAR",(char *)string)==0){ nexttok(); htok=1; } } else if(tok==tk_far){ nexttok(); faradd=8; htok=1; } // printf("call %d\n",tok); switch(tok){ case tk_proc: if(faradd==0){ if(itok.segm==DYNAMIC){ itok.segm=DYNAMIC_USED; updatetree(); } int flag=itok.flag; if(itok.segm255)bytedxexpected(); op(hnumber); next = 0; } else if(tok==tk_reg&&(unsigned int)itok.number==DX)op(0xED); else bytedxexpected(); } else if(tok==tk_beg&&(unsigned int)itok.number==AL){ nexttok(); expecting(tk_camma); if(tok==tk_number){ op(0xE4); asmparam=FALSE; if((hnumber=doconstdwordmath())>255)bytedxexpected(); op(hnumber); next=0; } else if(tok==tk_reg&&(unsigned int)itok.number==DX)op(0xEC); else bytedxexpected(); } else axalexpected(); break; case a_insb: //INSB ClearReg(AX); ClearReg(DI); op(0x6C); possiblecpu=2; break; case a_insw: //INSW op66(r16); possiblecpu=2; goto insd; break; case a_insd: //INSD op66(r32); possiblecpu=3; insd: op(0x6D); ClearReg(AX); ClearReg(DI); break; case a_int: //INT clearregstat(); nexttok(); if(tok==tk_number){ asmparam=FALSE; htok=doconstlongmath(); if(htok==3)op(0xCC); else{ op(0xCD); op(htok); } next=0; } else numexpected(); break; case a_into: op(0xCE); //INTO break; case a_invd: //INVD outword(0x080F); possiblecpu=4; break; case a_invlpg: //INVLPG nexttok(); switch(tok){ case tk_longvar: case tk_dwordvar: CheckAllMassiv(bufrm,4,&strinf); goto invlgp; case tk_intvar: case tk_wordvar: CheckAllMassiv(bufrm,2,&strinf); invlgp: outseg(&itok,3); outword(0x010F); op(itok.rm+0x38); outaddress(&itok); break; case tk_undefofs: strcpy(hstok.name,itok.name); tok=tk_number; case tk_number: hnumber=doconstdwordmath(); outword(0x010f); op((am32==FALSE?rm_d16:rm_d32)+0x38); if(postnumflag&f_reloc)AddReloc(); if(htok==tk_undefofs)AddUndefOff(2,hstok.name); if(am32)outdword(hnumber); else outword(hnumber); next=0; break; case tk_postnumber: outword(0x010F); op((am32==FALSE?rm_d16:rm_d32)+0x38); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(am32==FALSE)outword(itok.number); //Ąë«ź 0 outdword(itok.number); break; default: varexpected(0); break; } possiblecpu=4; break; case a_iret: #ifdef OPTVARCONST ClearLVIC(); #endif RestoreStack(); clearregstat(); op66(r16); op(0xCF); //IRET break; case a_iretd: #ifdef OPTVARCONST ClearLVIC(); #endif RestoreStack(); clearregstat(); op66(r32); op(0xCF); //IRETD break; case a_jo: case a_jno: case a_jc: case a_jnc: case a_jz: case a_jnz: case a_jna: case a_ja: case a_js: case a_jns: case a_jp: case a_jnp: case a_jl: case a_jnl: case a_jng: case a_jg: RestoreStack(); asmshortjump((htok-a_jo)+0x70,(htok-a_jo)+0x80); next=0; break; case a_jecxz: //JECXZ RestoreStack(); op67(r32); asmshortjump(0xE3,0); next=0; break; case a_jcxz: //JCXZ RestoreStack(); op67(r16); asmshortjump(0xE3,0); next=0; break; case a_jmp: //JMP RestoreStack(); nexttok(); faradd=0; lastcommand=tk_goto; if(stricmp("FAR",itok.name)==0){ nexttok(); faradd=8; } else if(stricmp("NEAR",itok.name)==0)nexttok(); else if(stricmp("SHORT",itok.name)==0){ // case insensitive nexttok(); next=(unsigned char)GOTO(); break; } next=gotol(faradd); break; case a_lahf: ClearReg(AX); op(0x9F); //LAHF break; case a_lar: //LAR case a_lsl: //LSL lar_lsl(htok-a_lar+2); break; case a_leave: //LEAVE RestoreStack(); op(0xC9); ClearReg(BP); possiblecpu = 2; break; case a_lmsw: protectinstr(1,0x30); //LMSW break; case a_loadall: // LOADALL 80286 only outword(0x050F); possiblecpu=2; break; case a_lodsb: ClearReg(SI); ClearReg(AX); op(0xAC); //LODSB break; case a_lodsw: op66(r16); ClearReg(SI); ClearReg(AX); op(0xAD); //LODSW break; case a_lodsd: op66(r32); ClearReg(SI); ClearReg(AX); op(0xAD); possiblecpu =3; //LODSD break; case a_lock: op(0xF0); //LOCK break; case a_loop: ConstToReg(0,CX,(am32+1)*2); op67(r16); asmshortjump(0xE2,0); next=0; break; case a_loopd: ConstToReg(0,CX,r32); possiblecpu=3; op67(r32); asmshortjump(0xE2,0); next=0; break; case a_loopz: //LOOPE LOOPZ ClearReg(CX); asmshortjump(0xE1,0); next=0; break; case a_loopnz: //LOOPNZ LOOPNE ClearReg(CX); asmshortjump(0xE0,0); next=0; break; case a_ltr: protectinstr(0,0x18); //LTR break; case a_str: protectinstr(0,0x08); //STR break; case a_lgdt: next=tabldeckr(0x10); break; case a_lidt: //LIDT next=tabldeckr(0x18); break; case a_lldt: protectinstr(0,0x10); //LLDT break; case a_mov: doasmmov(); next=0; break; case a_movsb: movsb(); //MOVSB break; case a_movsd: if(ScanTok3()==tk_camma&&(tok2==tk_xmmreg||(tok2>=tk_charvar&&tok2255)bytedxexpected(); expecting2(tk_camma); if((tok==tk_reg||tok==tk_reg32)&&(unsigned int)itok.number==AX){ op66(tok==tk_reg?r16:r32); if(tok==tk_reg32)possiblecpu=3; op(0xE7); op(hnumber); } else if(tok==tk_beg&&(unsigned int)itok.number==AL){ op(0xE6); op(hnumber); } else axalexpected(); } else if(tok==tk_reg&&(unsigned int)itok.number==DX){ nextexpecting2(tk_camma); if((tok==tk_reg||tok==tk_reg32)&&(unsigned int)itok.number==AX){ op66(tok==tk_reg?r16:r32); if(tok==tk_reg32)possiblecpu=3; op(0xEF); } else if(tok==tk_beg&&(unsigned int)itok.number==AL)op(0xEE); else axalexpected(); } else bytedxexpected(); break; case a_outsb: //OUTSB ClearReg(SI); op(0x6E); possiblecpu=2; break; case a_outsw: //OUTSW ClearReg(SI); op66(r16); op(0x6F); possiblecpu=2; break; case a_outsd: //OUTSD ClearReg(SI); op66(r32); op(0x6F); possiblecpu=3; break; case a_pop: //POP RestoreStack(); do{ possiblecpu=0; asmparam=TRUE; nexttok(); razr=r16; switch(tok){ case tk_reg32: possiblecpu=3; razr=r32; case tk_reg: ClearReg(itok.number); op66(razr); op(0x58+(unsigned int)itok.number); break; case tk_dwordvar: tok--; case tk_longvar: CheckAllMassiv(bufrm,4,&strinf); possiblecpu=3; razr=r32; goto pop; case tk_wordvar: tok--; case tk_intvar: CheckAllMassiv(bufrm,2,&strinf); pop: #ifdef OPTVARCONST ClearVarByNum(&itok); #endif KillVar(itok.name); op66(razr); outseg(&itok,2); op(0x8F); op(itok.rm); outaddress(&itok); break; case tk_seg: if(itok.number!=CS){ PopSeg((unsigned int)itok.number); break; } default: preerror("Invalid operand for POP"); break; } if(cpu3?hstok.number-4:hstok.number); switch(tok){ case tk_minus: if(tok2!=tk_number){ bytevalexpected(2); break; } case tk_number: asmparam=FALSE; holdnumber2=doconstlongmath(); next=0; if(hstok.number==AL)op(4+basecode); else{ op(128); op(128+64+hstok.number+basecode); } op(holdnumber2); break; case tk_beg: op(2+basecode); op(128+64+(unsigned int)itok.number+hstok.number*8); break; case tk_bytevar: case tk_charvar: CheckAllMassiv(bufrm,1,&strinf); outseg(&itok,2); op(2+basecode); op(itok.rm+hstok.number*8); outaddress(&itok); break; default: bytevalexpected(2); break; } break; case tk_dwordvar: case tk_longvar: typet=r32; if(cpu<3)cpu=3; case tk_intvar: case tk_wordvar: if((basecode/8)!=a_cmp)KillVar(hstok.name); CheckAllMassiv(hbuf,typet,&hstr,&hstok); op66(typet); outseg(&hstok,2); switch(tok){ case tk_undefofs: strcpy(hstok.name,itok.name); tok=tk_number; goto vnum; case tk_minus: if(tok2!=tk_number)goto erval; case tk_number: vnum: asmparam=FALSE; holdnumber2=doconstlongmath(); #ifdef OPTVARCONST if(i==tk_number&&(postnumflag&f_reloc)==0){ initconst=UpdVarConst(&hstok,holdnumber2,tk_dword,operand); } #endif next=0; if(i!=tk_undefofs&&(postnumflag&f_reloc)==0&&short_ok(holdnumber2,typet/2-1)){ op(128+2+1); op(hstok.rm+basecode); outaddress(&hstok); op(holdnumber2); } else{ op(128+1); op(hstok.rm+basecode); outaddress(&hstok); if((postnumflag&f_reloc)!=0)AddReloc(); if(i==tk_undefofs)AddUndefOff(2,hstok.name); if(typet==r16)outword(holdnumber2); else outdword(holdnumber2); } break; case tk_postnumber: if(typet==r32)goto erval; op(128+1); op(hstok.rm+basecode); outaddress(&hstok); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(typet==r16)outword(itok.number); else outdword(itok.number); break; case tk_reg32: if(typet==r16)goto erval; case tk_reg: op(1+basecode); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); break; default: erval: if(typet==r16)wordvalexpected(); else dwordvalexpected(); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&hstok); #endif break; case tk_bytevar: case tk_charvar: if((basecode/8)!=a_cmp)KillVar(hstok.name); CheckAllMassiv(hbuf,1,&hstr,&hstok); switch(tok){ case tk_minus: if(tok2!=tk_number){ bytevalexpected(2); break; } case tk_number: asmparam=FALSE; holdnumber2=doconstlongmath(); #ifdef OPTVARCONST if((postnumflag&f_reloc)==0){ initconst=UpdVarConst(&hstok,holdnumber2,tk_byte,operand); } #endif next=0; outseg(&hstok,2); op(128); op(hstok.rm+basecode); outaddress(&hstok); op(holdnumber2); break; case tk_beg: outseg(&hstok,2); op(basecode); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); break; default: bytevalexpected(2); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&hstok); #endif break; default: varexpected(1); break; } if(next)nexttok(); } int GOTO() { unsigned char next=1; CheckIP(); #ifdef OPTVARCONST ClearLVIC(); #endif clearregstat(); switch(tok){ case tk_proc: case tk_interruptproc: if(itok.segm!=NOT_DYNAMIC){ idrec *ptr=itok.rec; itok.segm=ptr->recsegm=DYNAMIC_USED; itok.rm=tok=tk_undefofs; //Ꮔ鄭š„ „é„ ­„ š§ą„áâ­ź© Ź„âȘš goto undefproc; } jumploc(itok.number); //­  Żàźæ„€ăàë źŻà à ­„„„ break; case tk_number: asmparam=FALSE; jumploc(doconstlongmath());//­  Șź­Șà„â­ë©  €à„á next=0; break; case tk_ID: addlocaljump(CALL_SHORT); //ąź§ŹźŠ­ăî «źȘ «ì­ăî Ź„âȘă outword(0x00EB); // JMP SHORT break; case tk_id: tobedefined(CALL_SHORT,tk_void);//ąź§ŹźŠ­ź źĄìïą«„­ăî Ź„âȘă outword(0x00EB); // JMP SHORT break; case tk_declare: tok=tk_undefproc; updatetree(); case tk_locallabel: case tk_undefproc: //­„źĄêïą«„­ăî Żàźæ undefproc: addacall((unsigned int)itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:CALL_SHORT)); outword(0x00EB); // JMP SHORT break; default: shortjumperror(); break; } return next; } unsigned char gotol(int faradd) { unsigned char next=1; unsigned long hnumber; unsigned int i=0; CheckIP(); #ifdef OPTVARCONST ClearLVIC(); #endif clearregstat(); switch(tok){ case tk_declare: if(tok2!=tk_openbracket){ tok=tk_undefproc; updatetree(); } case tk_locallabel: case tk_undefproc: if(tok2==tk_openbracket){ asmparam=FALSE; if(doanyundefproc(TRUE)==tokens)next=0; break; } if(faradd==0){ addacall((unsigned int)itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:(am32==FALSE?JMP_NEAR:JMP_32))); jumploc0(); } /* JMP num */ else invalidfarjumpitem(); break; case tk_proc: if(tok2==tk_openbracket){ doanyproc(TRUE); break; } if(itok.segm!=NOT_DYNAMIC){ idrec *ptr=itok.rec; itok.segm=ptr->recsegm=DYNAMIC_USED; itok.rm=tok=tk_undefofs; //Ꮔ鄭š„ „é„ ­„ š§ą„áâ­ź© Ź„âȘš if(faradd==0){ addacall((unsigned int)itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:(am32==FALSE?JMP_NEAR:JMP_32))); jumploc0(); break; } /* JMP num */ } case tk_interruptproc: if(faradd==0)jumploc(itok.number); else invalidfarjumpitem(); break; case tk_apiproc: asmparam=FALSE; if(tok2==tk_openbracket){ if(doanyundefproc(TRUE)==tokens)next=0; } else{ if(FastCallApi==TRUE){ outword(0x25ff); AddApiToPost(itok.number); } else{ addacall(itok.number,(unsigned char)CALL_32); jumploc0(); } } break; case tk_minus: if(tok2!=tk_number)goto err; case tk_number: asmparam=FALSE; hnumber=doconstdwordmath(); if(faradd==0)jumploc(hnumber); else{ op(0xEA); expecting2(tk_colon); int htok=tok; char name[IDLENGTH]; if(tok==tk_undefofs){ tok=tk_number; strcpy(name,itok.name); } unsigned long tempi=doconstdwordmath(); if(postnumflag&f_reloc)AddReloc(); if(htok==tk_undefofs)AddUndefOff(2,name); if(am32==FALSE)outword((unsigned int)tempi); else outdword(tempi); outword((unsigned int)hnumber); } next=0; break; /* JMP num */ case tk_postnumber: if(faradd==0){ op(0xE9); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(am32==FALSE)outword((unsigned int)itok.number); else outdword(itok.number); } else invalidfarjumpitem(); break; case tk_reg32: op66(r32); goto jmpreg; case tk_reg: op66(r16); jmpreg: if(faradd==0){ op(0xFF); op(0xE0+(unsigned int)itok.number); } /* JMP reg */ else invalidfarjumpitem(); break; case tk_ID: if(faradd==0){ addlocaljump(am32==FALSE?JMP_NEAR:JMP_32); jumploc0(); } /* JMP num */ else invalidfarjumpitem(); break; case tk_id: if(faradd==0){ tobedefined(am32==FALSE?JMP_NEAR:JMP_32,tk_void); jumploc0(); } /* JMP num */ else invalidfarjumpitem(); break; case tk_dwordvar: case tk_longvar: i=2; case tk_intvar: case tk_wordvar: i+=2; CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,2); op(0xFF); op(0x20+itok.rm+(faradd==0?(i==4&&am32==0?8:0):8)); outaddress(&itok); break; default: err: preerror("Invalid item for JMP"); break; } return next; } void asmregmem(int out1,int out2) // used for LEA LDS LES LFS LGS LSS. { int holdreg; nexttok(); op66(tok==tk_reg?r16:r32); if(tok!=tk_reg32&&tok!=tk_reg)reg32regexpected(1); holdreg=(unsigned int)itok.number; ClearReg(itok.number); nextexpecting2(tk_camma); switch(tok){ case tk_intvar: case tk_wordvar: case tk_charvar: case tk_bytevar: case tk_longvar: case tk_dwordvar: break; default: varexpected(2); } CheckAllMassiv(bufrm,2,&strinf); if(out2==0)outseg(&itok,2); else outseg(&itok,3); op(out1); if(out2!=0)op(out2); op(itok.rm+holdreg*8); outaddress(&itok); } void Scanbit(int basecode) { unsigned long hnumber; int htok,typet=r16; nexttok(); hnumber=itok.number; ClearReg(itok.number); htok=tok; nextexpecting2(tk_camma); switch(htok){ case tk_reg32: typet=r32; if(tok==tk_reg||tok==tk_wordvar||tok==tk_intvar)goto erval; case tk_reg: switch(tok){ case tk_reg32: if(typet==r16)goto erval; case tk_reg: op66(typet); op(0xf); op(basecode); op(0xc0+(unsigned int)itok.number+hnumber*8); break; case tk_dwordvar: case tk_longvar: if(typet==r16)goto erval; case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,typet,&strinf); op66(typet); outseg(&itok,3); op(0xf); op(basecode); op(itok.rm+hnumber*8); outaddress(&itok); break; default: erval: if(typet==r16)wordvalexpected(); else dwordvalexpected(); break; } break; default: reg32regexpected(1); } if(cpu<3)cpu=3; } void CheckBit(int code) { unsigned long holdnumber2; int htok; ITOK hstok; unsigned char next=1; char *hbuf; SINFO hstr; nexttok(); hstok=itok; htok=tok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); switch(htok){ case tk_reg32: case tk_reg: op66(htok==tk_reg?r16:r32); if(code)ClearReg(hstok.number); switch(tok){ case tk_number: asmparam=FALSE; holdnumber2=doconstlongmath(); next=0; outword(0xba0f); op(0xe0+code+hstok.number); op(holdnumber2); break; case tk_reg32: if(tok!=htok){ dwordvalexpected(); break; } case tk_reg: if(tok!=htok)wordvalexpected(); op(0xf); op(0xa3+code); op(0xc0+hstok.number+(unsigned int)itok.number*8); break; default: wordvalexpected(); break; } break; case tk_intvar: case tk_wordvar: CheckAllMassiv(hbuf,2,&hstr,&hstok); if(code)KillVar(hstok.name); op66(r16); switch(tok){ case tk_number: varc: asmparam=FALSE; holdnumber2=doconstlongmath(); next=0; outseg(&hstok,3); outword(0xba0f); op(hstok.rm+code+0x20); outaddress(&hstok); op(holdnumber2); break; case tk_reg: varreg: outseg(&hstok,3); op(0xf); op(0xa3+code); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); break; default: wordvalexpected(); break; } #ifdef OPTVARCONST if(code)ClearVarByNum(&hstok); #endif break; case tk_dwordvar: case tk_longvar: CheckAllMassiv(hbuf,4,&hstr,&hstok); if(code)KillVar(hstok.name); op66(r32); if(tok==tk_number)goto varc; if(tok==tk_reg32)goto varreg; dwordvalexpected(); break; default: varexpected(1); } if(cpu<3)cpu=3; if(next)nexttok(); } void asmone1(int basecode) // used for INC and DEC. { int razr=r16; #ifdef OPTVARCONST int operand=GetOperand(basecode/8+a_inc); #endif nexttok(); switch(tok){ case tk_reg32: if(cpu<3)cpu=3; razr=r32; case tk_reg: ClearReg(itok.number); op66(razr); op(64+basecode+(unsigned int)itok.number); break; case tk_beg: ClearReg(itok.number); op(254); op(128+64+basecode+(unsigned int)itok.number); break; case tk_charvar: case tk_bytevar: #ifdef OPTVARCONST UpdVarConst(&itok,1,tk_byte,operand); #endif CheckAllMassiv(bufrm,1,&strinf); KillVar(itok.name); outseg(&itok,2); op(254); op(itok.rm+basecode); outaddress(&itok); break; case tk_longvar: case tk_dwordvar: CheckAllMassiv(bufrm,4,&strinf); if(cpu<3)cpu=3; razr=r32; goto dec; case tk_intvar: case tk_wordvar: CheckAllMassiv(bufrm,2,&strinf); dec: #ifdef OPTVARCONST UpdVarConst(&itok,1,tk_dword,operand); #endif KillVar(itok.name); op66(razr); outseg(&itok,2); op(255); op(itok.rm+basecode); outaddress(&itok); break; default: varexpected(0); break; } } void asmone2(int basecode) // used for NEG NOT MUL IMUL DIV IDIV. { int razr=r16; #ifdef OPTVARCONST int operand=GetOperand((basecode-16)/8+a_not); #endif nexttok(); switch(tok){ case tk_reg32: if(cpu<3)cpu=3; razr=r32; case tk_reg: ClearReg(itok.number); op66(razr); op(246+1); op(128+64+basecode+(unsigned int)itok.number); break; case tk_beg: ClearReg(itok.number); op(246); op(128+64+basecode+(unsigned int)itok.number); break; razr=r8; case tk_charvar: case tk_bytevar: #ifdef OPTVARCONST UpdVarConst(&itok,0,tk_dword,operand); #endif CheckAllMassiv(bufrm,1,&strinf); KillVar(itok.name); outseg(&itok,2); op(246); op(itok.rm+basecode); outaddress(&itok); razr=r8; break; case tk_longvar: case tk_dwordvar: CheckAllMassiv(bufrm,4,&strinf); if(cpu<3)cpu=3; razr=r32; goto neg; case tk_intvar: case tk_wordvar: CheckAllMassiv(bufrm,2,&strinf); neg: #ifdef OPTVARCONST UpdVarConst(&itok,0,tk_dword,operand); #endif KillVar(itok.name); op66(razr); outseg(&itok,2); op(247); op(itok.rm+basecode); outaddress(&itok); break; default: varexpected(0); break; } if(basecode!=16&&basecode!=24){ ClearReg(AX); if(razr!=r8)ClearReg(DX); } } void asmshortjump(int shortcode,int nearcode) { unsigned char next=1,shortjump=1; unsigned int address; #ifdef OPTVARCONST ClearLVIC(); #endif nexttok(); if(stricmp("FAR",itok.name)==0){ // case insensitive preerror("FAR jump not available for this instruction"); nexttok(); } else if(stricmp("NEAR",itok.name)==0){ // case insensitive shortjump=0; nexttok(); } else if(stricmp("SHORT",itok.name)==0)nexttok(); // case insensitive if(shortjump){ CheckIP(); switch(tok){ case tk_proc: *(unsigned int *)&itok.number-=outptr+2; if(short_ok(itok.number)){ op(shortcode); op((unsigned int)itok.number); } else shortjumptoolarge(); break; case tk_number: asmparam=FALSE; address=doconstdwordmath()-(outptr+2); if(short_ok(address)){ op(shortcode); op(address); } else shortjumptoolarge(); next=0; break; case tk_ID: addlocaljump(CALL_SHORT); op(shortcode); op(0x00); /* JXX SHORT */ break; case tk_id: tobedefined(CALL_SHORT,tk_void); op(shortcode); op(0x00); /* JXX SHORT */ break; case tk_declare: tok=tk_undefproc; updatetree(); case tk_locallabel: case tk_undefproc: addacall((unsigned int)itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:CALL_SHORT)); op(shortcode); op(0x00); /* JXX SHORT */ break; default: shortjumperror(); break; } } else if(nearcode!=0){ unsigned long numlong; asmparam=FALSE; switch(tok){ case tk_proc: op(0xF); op(nearcode); numlong=itok.number-outptr-2; if(am32==FALSE)outword((unsigned int)numlong); else outdword(numlong-2); break; case tk_number: op(0xF); op(nearcode); numlong=doconstdwordmath()-outptr-2; if(am32==FALSE)outword((unsigned int)numlong); else outdword(numlong-2); next=0; break; case tk_undefofs: // ???? 32 Ąšâ­ë© à„ŠšŹ op(0xF); op(nearcode); AddUndefOff(2,itok.name); outword(-(int)(outptr-2)); if(am32!=FALSE)outword(0x0000); break; case tk_postnumber: op(0xF); op(nearcode); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); numlong=itok.number-outptr-2; if(am32==FALSE)outword((unsigned int)numlong); else outdword(numlong-2); break; case tk_ID: op(0xF); // must go before tobedefined() addlocaljump(am32==FALSE?CALL_NEAR:CALL_32); op(nearcode); outword(0x0000); /* JXX NEAR */ if(am32!=FALSE)outword(0x0000); break; case tk_id: op(0xF); // must go before tobedefined() tobedefined(am32==FALSE?CALL_NEAR:CALL_32,tk_void); op(nearcode); outword(0x0000); /* JXX NEAR */ if(am32!=FALSE)outword(0x0000); break; case tk_declare: tok=tk_undefproc; updatetree(); case tk_locallabel: case tk_undefproc: op(0xF); // must go before addacall() addacall((unsigned int)itok.number,(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:(am32==FALSE?CALL_NEAR:CALL_32))); op(nearcode); outword(0x0000); /* JXX NEAR */ if(am32!=FALSE)outword(0x0000); break; default: preerror("Invalid operand for NEAR jump"); break; } if(cpu<3)cpu=3; } else preerror("NEAR jump not available for this instruction"); if(next)nexttok(); } void lar_lsl(int code) { unsigned char possiblecpu=0; int razr=r16; nexttok(); if(tok!=tk_reg&&tok!=tk_reg32)reg32regexpected(1); int htok=tok; int hnumber=(unsigned int)itok.number; ClearReg(itok.number); nextexpecting2(tk_camma); switch(tok){ case tk_reg32: if(htok==tk_reg)reg32expected(1); possiblecpu=3; razr=r32; goto lar; case tk_reg: if(htok==tk_reg32)regexpected(1); possiblecpu=2; lar: op66(razr); op(0x0f); op(code); op(0xc0+(unsigned int)itok.number+hnumber*8); break; case tk_longvar: case tk_dwordvar: if(htok==tk_reg)reg32expected(1); CheckAllMassiv(bufrm,4,&strinf); possiblecpu=3; razr=r32; goto lar1; case tk_intvar: case tk_wordvar: if(htok==tk_reg32)regexpected(1); possiblecpu=2; CheckAllMassiv(bufrm,2,&strinf); lar1: op66(razr); outseg(&itok,3); op(0x0f); op(code); op(itok.rm+hnumber*8); outaddress(&itok); break; default: invalidoperand(2); break; } if(possiblecpu>cpu)cpu=possiblecpu; } unsigned char tabldeckr(int code) { unsigned int i=0; int htok; unsigned char next=1; char name[IDLENGTH]; nexttok(); htok=tok; KillVar(itok.name); switch(tok){ 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,3); outword(0x010f); op(itok.rm+code); outaddress(&itok); break; case tk_undefofs: strcpy(name,itok.name); tok=tk_number; case tk_number: i=doconstdwordmath(); outword(0x010f); op((am32==FALSE?rm_d16:rm_d32)+code); if(postnumflag&f_reloc)AddReloc(); if(htok==tk_undefofs)AddUndefOff(2,name); if(am32)outdword(i); else outword(i); next=0; break; default: varexpected(0); } if(cpu<2)cpu=2; return next; } void protectinstr(int code,int code2) { int i=0; nexttok(); switch(tok){ case tk_longvar: case tk_dwordvar: i=2; case tk_intvar: case tk_wordvar: i++; case tk_charvar: case tk_bytevar: i++; #ifdef OPTVARCONST ClearVarByNum(&itok); #endif CheckAllMassiv(bufrm,i,&strinf); KillVar(itok.name); outseg(&itok,3); op(0x0f); op(code); op(itok.rm+code2); outaddress(&itok); break; case tk_reg32: case tk_reg: ClearReg(itok.number); op(0x0f); op(code); op(0xc0+code2+(unsigned int)itok.number); break; default: wordvalexpected(); } if(cpu<2)cpu=2; } void doasmmov() // do MOV { unsigned char next=1,possiblecpu=0; int htok,typet; ITOK hstok; char *hbuf; SINFO hstr; #ifdef OPTVARCONST int initconst=FALSE; #endif nexttok(); hstok=itok; htok=tok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); typet=r16; int i=tok; switch(htok){ case tk_reg32: possiblecpu=3; typet=r32; case tk_reg: switch(tok){ case tk_debugreg: ClearReg(hstok.number); if(typet==r16)goto erreg; outword(0x210F); op(128+64+(unsigned int)itok.number*8+hstok.number); possiblecpu=4; if((unsigned int)itok.number<=DR3||(unsigned int)itok.number==DR6 ||(unsigned int)itok.number==DR7)possiblecpu=3; break; case tk_controlreg: ClearReg(hstok.number); if(typet==r16)goto erreg; outword(0x200F); op(128+64+(unsigned int)itok.number*8+hstok.number); possiblecpu=4; if((unsigned int)itok.number<=CR3)possiblecpu=3; break; case tk_testreg: ClearReg(hstok.number); if(typet==r16)goto erreg; outword(0x240F); op(128+64+(unsigned int)itok.number*8+hstok.number); possiblecpu=4; if((unsigned int)itok.number==TR6||(unsigned int)itok.number==TR7)possiblecpu=3; break; case tk_reg32: if(typet==r16)goto erreg; case tk_reg: RegToReg(hstok.number,itok.number,typet); op66(typet); op(0x89); op(128+64+(unsigned int)itok.number*8+hstok.number); break; case tk_undefofs: strcpy(hstok.name,itok.name); tok=tk_number; goto wnum; case tk_minus: if(tok2!=tk_number){ wordvalexpected(); break; } case tk_number: wnum: op66(typet); op(0xB8+hstok.number); ClearReg(hstok.number); asmparam=FALSE; SaveNumber(typet,i,hstok.name); next=0; break; case tk_postnumber: ClearReg(hstok.number); op66(typet); op(0xB8+hstok.number); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(typet==r32)outdword(itok.number); else outword((unsigned int)itok.number); break; case tk_dwordvar: case tk_longvar: if(typet==r16)goto erreg; case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,typet,&strinf); IDZToReg(itok.name,hstok.number,typet); op66(typet); if(hstok.number==0&&((itok.rm==rm_d16&&itok.sib==CODE16)||(itok.rm==rm_d32&&(itok.sib==CODE32||itok.sib==0)))){ outseg(&itok,1); op(0xA1); } else{ outseg(&itok,2); op(0x8B); op(itok.rm+hstok.number*8); } outaddress(&itok); break; case tk_seg: if(typet==r32)goto erreg; IDZToReg(itok.name,hstok.number,typet); op66(r16); op(0x8C); op(128+64+(unsigned int)itok.number*8+hstok.number); if((unsigned int)itok.number==FS||(unsigned int)itok.number==GS)possiblecpu=3; break; default: erreg: invalidoperand(2); break; } break; case tk_beg: ClearReg(hstok.number%4); switch(tok){ case tk_beg: op(0x88); op(128+64+(unsigned int)itok.number*8+hstok.number); break; case tk_number: op(0xB0+hstok.number); asmparam=FALSE; op((int)doconstlongmath()); next=0; break; case tk_bytevar: case tk_charvar: CheckAllMassiv(bufrm,1,&strinf); if(hstok.number==0&&((itok.rm==rm_d16&&itok.sib==CODE16)||(itok.rm==rm_d32&&(itok.sib==CODE32||itok.sib==0)))){ outseg(&itok,1); op(0xA0); } else{ outseg(&itok,2); op(0x8A); op(itok.rm+hstok.number*8); } outaddress(&itok); break; default: invalidoperand(2); break; } break; case tk_seg: if(hstok.number==CS){ invalidoperand(1); break; } switch(tok){ case tk_reg: op66(r16); op(0x8E); op(128+64+hstok.number*8+(unsigned int)itok.number); if(hstok.number==FS||hstok.number==GS)possiblecpu=3; break; case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,2,&strinf); op66(r16); outseg(&itok,2); op(0x8E); op(itok.rm+hstok.number*8); outaddress(&itok); if(hstok.number==FS||hstok.number==GS)possiblecpu=3; break; default: invalidoperand(2); break; } break; case tk_dwordvar: case tk_longvar: possiblecpu=3; typet=r32; case tk_wordvar: case tk_intvar: KillVar(itok.name); CheckAllMassiv(hbuf,typet,&hstr,&hstok); op66(typet); switch(tok){ case tk_reg32: if(typet==r16)goto ervar; case tk_reg: /*if((tok==tk_reg||tok==tk_reg32)&&hbuf==NULL&&hstr.bufstr==NULL)*/ AddRegVar(itok.number,typet,&hstok); if(itok.number==0&&((hstok.rm==rm_d16&&hstok.sib==CODE16)||(hstok.rm==rm_d32&&(hstok.sib==CODE32||hstok.sib==0)))){ outseg(&hstok,1); op(0xA3); outaddress(&hstok); } else{ outseg(&hstok,2); op(0x89); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); } break; case tk_undefofs: strcpy(hstok.name,itok.name); tok=tk_number; goto vnum; case tk_minus: if(tok2!=tk_number){ wordvalexpected(); break; } case tk_number: vnum: outseg(&hstok,2); op(0xC7); op(hstok.rm); outaddress(&hstok); asmparam=FALSE; #ifdef OPTVARCONST unsigned long t; t=SaveNumber(typet,i,hstok.name); if(typet==r16)t&=0xffff; else t&=0xffffffff; if((i==tk_number||i==tk_minus)&&(postnumflag&f_reloc)){ Const2Var(&hstok,t,tk_dword); initconst=TRUE; } #else SaveNumber(typet,i,hstok.name); #endif next=0; break; case tk_postnumber: outseg(&hstok,2); op(0xC7); op(hstok.rm); outaddress(&hstok); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); if(typet==r16)outword((unsigned int)itok.number); else outdword(itok.number); break; case tk_seg: outseg(&hstok,2); if(typet==r32)goto ervar; op(0x8C); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); if(hstok.number==FS||hstok.number==GS)possiblecpu=3; break; default: ervar: invalidoperand(2); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&hstok); #endif break; case tk_charvar: case tk_bytevar: KillVar(itok.name); CheckAllMassiv(hbuf,1,&hstr,&hstok); switch(tok){ case tk_beg: /*if(tok==tk_beg&&hbuf==NULL&&hstr.bufstr==NULL)*/ AddRegVar(itok.number,r8,&hstok); if(itok.number==0&&((hstok.rm==rm_d16&&hstok.sib==CODE16)||(hstok.rm==rm_d32&&(hstok.sib==CODE32||hstok.sib==0)))){ outseg(&hstok,1); op(0xA2); outaddress(&hstok); } else{ outseg(&hstok,2); op(0x88); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); } break; case tk_number: outseg(&hstok,2); op(0xC6); op(hstok.rm); outaddress(&hstok); asmparam=FALSE; #ifdef OPTVARCONST long t; t=doconstlongmath()&0xff; op(t); if((postnumflag&f_reloc)){ initconst=TRUE; Const2Var(&hstok,t,tk_byte); } #else op((int)doconstlongmath()); #endif next=0; break; default: invalidoperand(2); break; } #ifdef OPTVARCONST if(initconst==FALSE)ClearVarByNum(&hstok); #endif break; case tk_debugreg: if(tok==tk_reg32){ outword(0x230F); op(128+64+hstok.number*8+(unsigned int)itok.number); possiblecpu=4; if(hstok.number<=DR3||hstok.number==DR6||hstok.number==DR7)possiblecpu=3; } else invalidoperand(2); break; case tk_controlreg: if(tok==tk_reg32){ outword(0x220F); op(128+64+hstok.number*8+(unsigned int)itok.number); possiblecpu=4; if(hstok.number<=CR3)possiblecpu=3; } else invalidoperand(2); break; case tk_testreg: if(tok==tk_reg32){ outword(0x260F); op(128+64+hstok.number*8+(unsigned int)itok.number); possiblecpu=4; if(hstok.number==TR6||hstok.number==TR7)possiblecpu=3; } else invalidoperand(2); break; default: invalidoperand(1); break; } asmparam=FALSE; if(possiblecpu>cpu)cpu=possiblecpu; if(next)nexttok(); } void asmextend(int basecode) // procedure MOVSX and MOVZX { int regnum; int razr=r16; nexttok(); if(tok==tk_reg32)razr=r32; if(tok!=tk_reg32&&tok!=tk_reg)reg32regexpected(1); regnum=(unsigned int)itok.number*8; ClearReg(itok.number); nextexpecting2(tk_camma); switch(tok){ case tk_reg: op66(razr); op(0xF); op(basecode|1); op(128+64+regnum+(unsigned int)itok.number); break; case tk_beg: op66(razr); op(0xF); op(basecode); op(128+64+regnum+(unsigned int)itok.number); break; case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,2,&strinf); op66(razr); outseg(&itok,3); op(0xF); op(basecode|1); op(itok.rm+regnum); outaddress(&itok); break; case tk_bytevar: case tk_charvar: CheckAllMassiv(bufrm,1,&strinf); op66(razr); outseg(&itok,3); op(0xF); op(basecode); op(itok.rm+regnum); outaddress(&itok); break; default: varexpected(2); break; } if(cpu<3)cpu=3; } void movd() { ITOK hstok; int htok; char *hbuf; SINFO hstr; int i=0; nexttok(); hstok=itok; htok=tok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); if(tok==tk_xmmreg)i++; switch(htok){ case tk_reg32: ClearReg(hstok.number); if(tok==tk_mmxreg||i){ //MOVD EAX,MM0 if(i)op(0x66); outword(0x7E0F); op(0xc0+hstok.number+(unsigned int)itok.number*8); } else mmxregexpected(2); break; case tk_dwordvar: case tk_longvar: if(tok==tk_mmxreg||i){ //MOVD mem,MM0 #ifdef OPTVARCONST ClearVarByNum(&hstok); #endif CheckAllMassiv(hbuf,4,&hstr,&hstok); KillVar(hstok.name); outseg(&hstok,i==0?3:4); if(i)op(0x66); outword(0x7E0F); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); } else mmxregexpected(2); break; case tk_xmmreg: i++; case tk_mmxreg: switch(tok){ case tk_reg32: //MOVD MM0,EAX if(i)op(0x66); outword(0x6E0F); op(0xc0+hstok.number*8+(unsigned int)itok.number); break; case tk_dwordvar: //MOVD MMO,mem case tk_longvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,i==0?3:4); if(i)op(0x66); outword(0x6E0F); op(itok.rm+hstok.number*8); outaddress(&itok); break; default: dwordvalexpected(); } break; default: mmxregordwordexpected(1); } if(cpu<6)cpu=6; if(i&&cpu<9)cpu=9; } void movq() { int htok; ITOK hstok; char *hbuf; SINFO hstr; int i=1,xmm=0; nexttok(); hstok=itok; htok=tok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); if(tok==tk_xmmreg)xmm++; switch(htok){ case tk_qwordvar: case tk_doublevar: i+=4; case tk_longvar: case tk_dwordvar: case tk_floatvar: i+=2; case tk_wordvar: case tk_intvar: i++; case tk_charvar: case tk_bytevar: if(tok==tk_mmxreg||xmm){ //MOVQ mem,MM0 #ifdef OPTVARCONST ClearVarByNum(&hstok); #endif KillVar(hstok.name); CheckAllMassiv(hbuf,i,&hstr,&hstok); outseg(&hstok,xmm==0?3:4); if(xmm){ op(0x66); outword(0xD60f); } else outword(0x7F0F); op(hstok.rm+(unsigned int)itok.number*8); outaddress(&hstok); } else mmxregexpected(2); break; case tk_mmxreg: switch(tok){ case tk_mmxreg: //MOVQ MM0,MM1 outword(0x6F0F); op(0xc0+hstok.number*8+(unsigned int)itok.number); break; case tk_qwordvar: case tk_doublevar: i+=4; case tk_longvar: case tk_dwordvar: case tk_floatvar: i+=2; case tk_wordvar: case tk_intvar: i++; case tk_charvar: case tk_bytevar: CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,3); outword(0x6F0F); op(itok.rm+hstok.number*8); outaddress(&itok); break; default: mmxregordwordexpected(2); } break; case tk_xmmreg: switch(tok){ case tk_xmmreg: op(0xF3); outword(0x7e0F); op(0xc0+hstok.number*8+(unsigned int)itok.number); break; case tk_qwordvar: case tk_doublevar: i+=4; case tk_longvar: case tk_dwordvar: case tk_floatvar: i+=2; case tk_wordvar: case tk_intvar: i++; case tk_charvar: case tk_bytevar: CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,4); op(0xF3); outword(0x7E0F); op(itok.rm+hstok.number*8); outaddress(&itok); xmm++; break; default: xmmregorvarexpected(2); } break; default: mmxregordwordexpected(1); } if(cpu<6)cpu=6; if(xmm&&cpu<9)cpu=9; } void packMMX(int code,int code1,int code2) { unsigned int hnumber; int htok,next=TRUE; int i=1; int xmm=FALSE; nexttok(); hnumber=(unsigned int)itok.number; htok=tok; nextexpecting2(tk_camma); if(htok==tk_xmmreg)xmm=TRUE; else if(htok!=tk_mmxreg)mmxregexpected(1); switch(tok){ case tk_mmxreg: if(xmm)xmmregexpected(2); op(0x0f); op(code); op(0xc0+hnumber*8+(unsigned int)itok.number); break; case tk_xmmreg: if(!xmm)mmxregexpected(2); else op(0x66); op(0x0f); op(code); op(0xc0+hnumber*8+(unsigned int)itok.number); break; case tk_number: if(xmm)op(0x66); op(0x0f); op(code1); op(code2+hnumber); asmparam=FALSE; op((unsigned int)doconstlongmath()); next=FALSE; break; case tk_qwordvar: i+=4; case tk_longvar: case tk_dwordvar: case tk_floatvar: i+=2; case tk_wordvar: case tk_intvar: i++; case tk_charvar: case tk_bytevar: CheckAllMassiv(bufrm,i,&strinf); outseg(&itok,xmm==FALSE?3:4); if(xmm)op(0x66); op(0x0f); op(code); op(itok.rm+hnumber*8); outaddress(&itok); break; default: mmxregordwordexpected(2); break; } if(cpu<6)cpu=6; if(xmm&&cpu<9)cpu=9; if(next==TRUE)nexttok(); } void asmshift(int basecode) // used for ROL ROR RCL RCR SHL SAL SHR SAR. { int htok,precode; unsigned char holdbyte; int usenumsh=TRUE; ITOK hstok; char *hbuf; char next=1; SINFO hstr; int razr=r16; #ifdef OPTVARCONST int operand=GetOperand(basecode/8+a_rol); #endif nexttok(); htok=tok; hstok=itok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); if(tok==tk_beg&&(unsigned int)itok.number==CL){ precode=0xD2; usenumsh=FALSE; } else if(tok==tk_number){ asmparam=FALSE; holdbyte=(unsigned char)doconstlongmath(); if(holdbyte==1){ precode=0xD0; usenumsh=FALSE; } else /*if(holdbyte!=0)*/{ precode=0xC0; if(cpu<2)cpu=2; } next=0; } else clornumberexpected(); // if(precode!=0){ switch(htok){ case tk_reg32: if(cpu<3)cpu=3; razr=r32; case tk_reg: ClearReg(hstok.number); op66(razr); op(precode+1); op(128+64+basecode+hstok.number); break; case tk_beg: ClearReg(hstok.number); op(precode); op(128+64+basecode+hstok.number); break; case tk_charvar: case tk_bytevar: #ifdef OPTVARCONST if(precode==0xD0||precode==0xc0)UpdVarConst(&hstok,holdbyte,tk_byte,operand); else ClearVarByNum(&hstok); #endif CheckAllMassiv(hbuf,1,&hstr,&hstok); KillVar(hstok.name); outseg(&hstok,2); op(precode); op(hstok.rm+basecode); outaddress(&hstok); break; case tk_dwordvar: case tk_longvar: CheckAllMassiv(hbuf,4,&hstr,&hstok); if(cpu<3)cpu=3; razr=r32; goto rol; case tk_wordvar: case tk_intvar: CheckAllMassiv(hbuf,2,&hstr,&hstok); rol: #ifdef OPTVARCONST if(precode==0xD0||precode==0xc0)UpdVarConst(&hstok,holdbyte,tk_byte,operand); else ClearVarByNum(&hstok); #endif KillVar(hstok.name); op66(razr); outseg(&hstok,2); op(precode+1); op(hstok.rm+basecode); outaddress(&hstok); break; default: varexpected(1); break; } if(usenumsh)op(holdbyte); if(next)nexttok(); } void CheckCl(int code) { op(0xf); if(tok==tk_beg){ if(itok.number==CL)code++; else clornumberexpected(); } else if(tok!=tk_number)clornumberexpected(); op(code); } void Shxd(int code) { unsigned int h2number; int htok,h2tok; ITOK hstok; char *hbuf; unsigned char next=1; SINFO hstr; nexttok(); hstok=itok; htok=tok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; nextexpecting2(tk_camma); h2number=(unsigned int)itok.number; ClearReg(itok.number); h2tok=tok; nextexpecting2(tk_camma); switch(htok){ case tk_reg: if(h2tok==tk_reg){ op66(r16); regreg: ClearReg(hstok.number); CheckCl(code); op(0xc0+hstok.number+(unsigned int)h2number*8); if(tok==tk_number){ asmparam=FALSE; op(doconstlongmath()); next=0; } } else regexpected(2); break; case tk_reg32: if(h2tok==tk_reg32){ op66(r32); goto regreg; } else reg32expected(2); break; case tk_intvar: case tk_wordvar: if(h2tok==tk_reg){ CheckAllMassiv(hbuf,2,&hstr,&hstok); op66(r16); varreg: #ifdef OPTVARCONST ClearVarByNum(&hstok); #endif KillVar(hstok.name); outseg(&hstok,3); CheckCl(code); op(hstok.rm+h2number*8); outaddress(&hstok); if(tok==tk_number){ asmparam=FALSE; op(doconstlongmath()); next=0; } } else regexpected(2); break; case tk_dwordvar: case tk_longvar: if(h2tok==tk_reg32){ CheckAllMassiv(hbuf,4,&hstr,&hstok); op66(r32); goto varreg; } else reg32expected(2); break; default: valueexpected(); } if(cpu<3)cpu=3; if(next)nexttok(); } void FpuType1(unsigned int addrm) { int opcode=0xd8; int oscan=scanlexmode; scanlexmode=ASMLEX; nexttok(); retoldscanmode(oscan); if(tok==tk_endline||tok==tk_semicolon){ op(0xD8); op(0xC1+addrm); return; } if(tok==tk_double){ opcode=0xdc; nexttok(); } switch(tok){ case tk_fpust: op(0xD8); op(0xC0+(unsigned int)itok.number+addrm); break; case tk_longvar: case tk_dwordvar: case tk_floatvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,2); op(opcode); op(itok.rm+addrm); outaddress(&itok); break; case tk_doublevar: CheckAllMassiv(bufrm,8,&strinf); outseg(&itok,2); op(0xDC); op(itok.rm+addrm); outaddress(&itok); break; default: fpuvarexpected(0); } } void FpuType2(unsigned int addrm,unsigned int addrm2) { long hnum; int opcode=0xd8; int oscan=scanlexmode; scanlexmode=ASMLEX; nexttok(); retoldscanmode(oscan); if(tok==tk_endline||tok==tk_semicolon){ op(0xDE); op(0xC1+addrm); return; } if(tok==tk_double){ opcode=0xdc; nexttok(); } switch(tok){ case tk_fpust: hnum=itok.number; nextexpecting2(tk_camma); if(hnum==0){ if(tok==tk_fpust){ op(0xD8); op(0xC0+addrm2+(unsigned int)itok.number); } else fpustakexpected(2); } else{ if(tok==tk_fpust){ if(itok.number!=0)fpu0expected(); op(0xDC); op(0xC0+(unsigned int)hnum+addrm); } else fpustakexpected(2); } break; case tk_longvar: case tk_dwordvar: case tk_floatvar: CheckAllMassiv(bufrm,4,&strinf); outseg(&itok,2); op(opcode); op(addrm2+itok.rm); outaddress(&itok); break; case tk_doublevar: CheckAllMassiv(bufrm,8,&strinf); outseg(&itok,2); op(0xDC); op(addrm2+itok.rm); outaddress(&itok); break; default: fpuvarexpected(1); } } void FpuType3(unsigned int opcode,unsigned int addrm) { int oscan=scanlexmode; scanlexmode=ASMLEX; nexttok(); // scanlexmode=oscan; retoldscanmode(oscan); if((tok==tk_endline||tok==tk_semicolon)&&opcode!=0xDD){ op(opcode); op(0xC1+addrm); } else if(tok==tk_fpust){ op(opcode); op(0xC0+(unsigned int)itok.number+addrm); } else fpustakexpected(1); if(opcode==0xDE&&tok2==tk_camma){ nexttok(); nexttok(); if(tok!=tk_fpust||itok.number!=0)fpu0expected(); } } void FpuType4(unsigned int opcode,unsigned int addrm) { nexttok(); if(opcode==1&&(addrm==0x18||addrm==0)&&tok==tk_qwordvar){ if(addrm==0)addrm=0x28; else addrm=0x38; CheckAllMassiv(bufrm,8,&strinf); KillVar(itok.name); outseg(&itok,2); op(0xDF); op(itok.rm+addrm); outaddress(&itok); return; } switch(tok){ case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,2,&strinf); KillVar(itok.name); outseg(&itok,2); op(0xDE + opcode); op(itok.rm+addrm); outaddress(&itok); break; case tk_longvar: case tk_dwordvar: case tk_floatvar: CheckAllMassiv(bufrm,4,&strinf); KillVar(itok.name); outseg(&itok,2); op(0xDA+opcode); op(itok.rm+addrm); outaddress(&itok); break; default: fpuvarexpected(0); } } void FpuType5(unsigned int opcode,unsigned int addrm) { int opc=0xd9; int i=4; nexttok(); if(tok==tk_qword||tok==tk_double){ nexttok(); tok=tk_qwordvar; } else if((strcmp(itok.name,"tbyte")==0||strcmp(itok.name,"ldouble")==0)&&addrm!=0x10){ opc=0xdb; i=10; if(addrm==0)addrm=40; else addrm=56; nexttok(); if(tok>=tk_charvar&&tok<=tk_wordvar)tok=tk_dwordvar; } switch(tok){ case tk_fpust: op(opcode); op(0xC0+(unsigned int)itok.number+addrm); break; case tk_qwordvar: case tk_doublevar: opc=0xdd; i=8; case tk_longvar: case tk_dwordvar: case tk_floatvar: CheckAllMassiv(bufrm,i,&strinf); if(opcode!=0xD9)KillVar(itok.name); outseg(&itok,2); op(opc); op(itok.rm+addrm); outaddress(&itok); break; default: fpuvarexpected(0); } } void FpuType6(unsigned int opcode,unsigned int addrm) { int i=0; nexttok(); if(opcode==0xDF){ if(tok==tk_qword){ nexttok(); tok=tk_qwordvar; } if(strcmp(itok.name,"tbyte")==0){ i=2; nexttok(); tok=tk_qwordvar; } } switch(tok){ case tk_qwordvar: if(opcode!=0xDF)wordvalexpected(); i=+4; case tk_longvar: case tk_dwordvar: case tk_floatvar: i+=2; case tk_wordvar: case tk_intvar: i+=2; CheckAllMassiv(bufrm,i,&strinf); KillVar(itok.name); outseg(&itok,2); op(opcode); op(itok.rm+addrm); outaddress(&itok); break; default: wordvalexpected(); } } void FpuType7(unsigned int addrm) { nexttok(); switch(tok){ case tk_wordvar: case tk_intvar: CheckAllMassiv(bufrm,2,&strinf); if(addrm!=0x28)KillVar(itok.name); outseg(&itok,2); op(0xD9); op(itok.rm+addrm); outaddress(&itok); break; default: wordvalexpected(); } } void FpuType8(unsigned int opcode,unsigned int addrm) { nexttok(); if(tok==tk_fpust&&itok.number==0&&tok2==tk_camma){ nexttok(); nexttok(); } if(tok==tk_fpust){ op(opcode); op(0xC0+(unsigned int)itok.number+addrm); if(cpu<7)cpu=7; } else fpustakexpected(1); } /* ***************** start of some quick codes ****************** */ int short_ok(long thenumber,int reg32) { if(reg32==TRUE){ if(thenumber<=SHORTMAX&&thenumber>=SHORTMIN)return(1); } else{ if((short)thenumber<=SHORTMAX&&(short)thenumber>=SHORTMIN)return(1); } return(0); } void cbw() { if(optimizespeed&&(chip==5||chip==6)){ outdword(0xFCC0C488); //mov ah,al sar AH,7 op(7); } else{ op66(r16); op(0x98); } ClearReg(AX); } void stosb() { op(0xAA); ClearReg(DI); } void stosw() { op66(r16); op(0xAB); ClearReg(DI); } void stosd() { op66(r32); op(0xAB); if(cpu<3)cpu=3; ClearReg(DI); } void movsb() { op(0xA4); ClearReg(DI); ClearReg(SI); } void movsw() { op66(r16); op(0xA5); ClearReg(DI); ClearReg(SI); } void movsd() { op66(r32); op(0xA5); if(cpu<3)cpu=3; ClearReg(DI); ClearReg(SI); } void pushds() /* produce PUSH DS */ { RestoreStack(); op(0x1E); } void pushss() { RestoreStack(); op(0x16); /* PUSH SS */ } void popes() /* produce POP ES */ { RestoreStack(); op(0x07); } void ret() /* produce RET */ { RestoreStack(); op(0xC3); } void retf() /* produce RETF */ { RestoreStack(); op(0xCB); } void jumploc(long loc) /* produce JUMP # */ { loc=loc-outptr-3; if(loc>-130&&loc<127){ loc++; op(0xEB); op(loc); if(loc==0)notunreach=TRUE; } else{ if(am32==FALSE){ op(0xE9); outword(loc); } else{ if(!optimizespeed&&(loc>126&&loc<65533)){ outword(0xE966); outword(loc-1); } else{ op(0xE9); outdword(loc-2); } } } } void callloc(long loc) /* produce CALL # */ { loc=loc-outptr-3; op(0xE8); if(am32==FALSE) outword(loc); else outdword(loc-2); } void xorAHAH() /* produce XOR AH,AH */ { outword(0xE430); ConstToReg(0,AH,r8); } void xorAXAX() /* produce XOR AX,AX */ { op66(r16); outword(0xC031); ConstToReg(0,AX,r16); } void xorEAXEAX() /* produce XOR EAX,EAX */ { op66(r32); outword(0xC031); if(cpu<3)cpu=3; ConstToReg(0,AX,r32); } void ZeroReg(int reg, int razr) { op66(razr); op(0x31); op(0xc0+9*reg); //xor reg,reg ConstToReg(0,reg,razr); } void fwait() { op(0x9B); } void cwdq(int razr) { op66(razr); if(optimizespeed&&(chip==5||chip==6)){ outword(0xC289); //mov dx,ax op66(razr); outword(0xFAC1); //sar dx,15 op(razr==r16?15:31); } else op(0x99); ClearReg(DX); } void nextexpecting2(int want) { nexttok(); expecting2(want); } void expecting2(int want) { if(want!=tok)SwTok(want); nexttok(); } void CheckIP() { if(tok==tk_dollar){ tok=tk_number; itok.number=outptr; } } void jumploc0() { op(0xE9); outword(0); /* the large jump */ if(am32!=FALSE)outword(0); } void callloc0() { op(0xE8); outword(0); if(am32!=FALSE)outword(0); } void Leave() { if((optimizespeed&&chip>3&&chip<7)||chip==0){ outword(0xEC89); // MOV SP,BP op(0x5D); } else op(0xC9); } void tobedefined(int callkind,int expectedreturn) { // strcpy(itok.name,(char *)string); string[0]=0; itok.flag=(unsigned char)(tok==tk_ID?tp_fastcall:(comfile==file_w32?tp_stdcall:tp_pascal)); tok=tk_undefproc; itok.number=secondcallnum; itok.segm=NOT_DYNAMIC; itok.rm=expectedreturn; itok.post=0; addtotree(itok.name); addacall(secondcallnum++,(unsigned char)callkind); } void addlocaljump(int callkind) { addlocalvar((char *)string,tk_locallabel,secondcallnum,TRUE); addacall(secondcallnum++,(char)callkind); } unsigned long SaveNumber(int type,int tok4,char *name) { unsigned long t=doconstdwordmath(); if(tok4==tk_undefofs)AddUndefOff(0,name); else if((postnumflag&f_reloc)!=0)AddReloc(); if(type==r16)outword((unsigned int)t); else outdword(t); return t; } void Swap2tok(int *tok4, ITOK *itok4, char **buf4, SINFO *strinf4, int *tok6, ITOK *itok6, char **buf6, SINFO *strinf6) { int htok; ITOK hstok; char *hbuf; SINFO hstr; htok=*tok4; *tok4=*tok6; *tok6=htok; hstok=*itok4; *itok4=*itok6; *itok6=hstok; hbuf=*buf4; *buf4=*buf6; *buf6=hbuf; hstr=*strinf4; *strinf4=*strinf6; *strinf6=hstr; } int iTest(int mode) { int htok,i; ITOK hstok; char *hbuf; SINFO hstr; unsigned char possiblecpu=0,next=1; unsigned long num; asmparam=TRUE; nexttok(); htok=tok; hstok=itok; hbuf=bufrm; bufrm=NULL; hstr=strinf; strinf.bufstr=NULL; if(tok==tk_number)hstok.number=doconstlongmath(); else nexttok(); expecting2(tk_camma); i=r16; // printf("tok=%d itok.number=%u bufrm=%s htok=%d hstok.number=%u nbuf=%s\n", // tok,itok.number,bufrm,htok,hstok.number,hbuf); if(htok==tk_number||htok==tk_postnumber)Swap2tok(&tok,&itok,&bufrm,&strinf, &htok,&hstok,&hbuf,&hstr); // printf("tok=%d itok.number=%u bufrm=%s htok=%d hstok.number=%u nbuf=%s\n", // tok,itok.number,bufrm,htok,hstok.number,hbuf); switch(htok){ case tk_reg32: i=r32; possiblecpu=3; case tk_reg: switch(tok){ case tk_reg32: if(i==r16){ reg32expected(1); return FALSE; } op66(i); op(0x85); op(128+64+(unsigned int)itok.number*8+hstok.number); break; case tk_reg: if(i==r32){ reg32expected(2); return FALSE; } op66(i); op(0x85); op(128+64+(unsigned int)itok.number*8+hstok.number); break; case tk_number: asmparam=FALSE; num=doconstdwordmath(); if(mode){ if(num<256&&hstok.number<4)goto testal; if(num<65536)i=r16; } op66(i); if(hstok.number==AX)op(0xA9); else{ op(0xF7); op(128+64+hstok.number); } if(i==r16)outword((unsigned int)num); else outdword(num); next=0; break; case tk_postnumber: if(i==r32)return FALSE; op66(r16); if(hstok.number==AX)op(0xA9); else{ op(0xF7); op(128+64+hstok.number); } (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); outword(itok.number); //Ąë«ź 0 break; case tk_dwordvar: case tk_longvar: if(i==r16){ reg32expected(1); return FALSE; } CheckAllMassiv(bufrm,i,&strinf); op66(i); outseg(&itok,2); op(0x85); op(hstok.number*8+itok.rm); outaddress(&itok); break; case tk_wordvar: case tk_intvar: if(i==r32){ regexpected(1); return FALSE; } CheckAllMassiv(bufrm,i,&strinf); op66(i); outseg(&itok,2); op(0x85); op(hstok.number*8+itok.rm); outaddress(&itok); break; default: return FALSE; } break; case tk_beg: switch(tok){ case tk_beg: op(0x84); op(128+64+(unsigned int)itok.number*8+hstok.number); break; case tk_number: asmparam=FALSE; num=doconstdwordmath(); testal: if(hstok.number==AL)op(0xA8); else{ op(0xF6); op(128+64+hstok.number); } op(num); next=0; break; case tk_charvar: case tk_bytevar: CheckAllMassiv(bufrm,1,&strinf); outseg(&itok,2); op(0x84); op(hstok.number*8+itok.rm); outaddress(&itok); break; default: return FALSE; } break; case tk_dwordvar: case tk_longvar: i=r32; possiblecpu=3; case tk_wordvar: case tk_intvar: CheckAllMassiv(hbuf,i,&hstr,&hstok); switch(tok){ case tk_reg32: if(i==r16){ regexpected(2); return FALSE; } op66(i); outseg(&hstok,2); op(0x85); op((unsigned int)itok.number*8+hstok.rm); outaddress(&hstok); break; case tk_reg: if(i==r32){ reg32expected(2); return FALSE; } op66(i); outseg(&hstok,2); op(0x85); op((unsigned int)itok.number*8+hstok.rm); outaddress(&hstok); break; case tk_number: asmparam=FALSE; num=doconstdwordmath(); if(mode){ if(num<256)goto testbyte; if(num<65536)i=r16; } op66(i); outseg(&hstok,2); op(0xF7); op(hstok.rm); outaddress(&hstok); if(i==r32)outdword(num); else outword((unsigned int)num); next=0; break; case tk_postnumber: op66(i); outseg(&hstok,2); if(i==r32)return FALSE; op(0xF7); op(hstok.rm); outaddress(&hstok); (itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number); outword((unsigned int)itok.number); break; default: return FALSE; } break; case tk_charvar: case tk_bytevar: CheckAllMassiv(hbuf,1,&hstr,&hstok); switch(tok){ case tk_beg: outseg(&hstok,2); op(0x84); op((unsigned int)itok.number*8+hstok.rm); outaddress(&hstok); break; case tk_number: asmparam=FALSE; num=doconstdwordmath(); testbyte: outseg(&hstok,2); op(0xF6); op(hstok.rm); outaddress(&hstok); op(num); next=0; break; default: return FALSE; } break; default: return FALSE; } if(cpu