kolibrios/programs/develop/cmm/tokr.cpp

6136 lines
136 KiB
C++
Raw Permalink Normal View History

#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){ //<2F><>
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.segm<NOT_DYNAMIC){ //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><E6A5A4><EFBFBD>
addacall(itok.number,(unsigned char)(am32!=FALSE?CALL_32:CALL_NEAR));
callloc0();
}
else callloc(itok.number);
}
else invalidfarcallitem();
break;
case tk_number:
asmparam=FALSE;
hnumber=doconstdwordmath();
if(faradd==0)callloc(hnumber);
else{
op(0x9A);
expecting2(tk_colon);
unsigned long tempi=doconstdwordmath();
if(am32==FALSE)outword((unsigned int)tempi);
else outdword(tempi);
outword(hnumber);
}
next=0;
break; /* CALL num */
case tk_postnumber:
if(faradd==0){
itok.number=itok.number-outptr-3;
op(0xE8);
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
if(am32==FALSE)outword(itok.number);
else outdword(itok.number-2);
/* op(0xE8);
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
if(am32==FALSE)outword((unsigned int)itok.number);
else outdword(itok.number);*/
}
else invalidfarcallitem();
break;
case tk_reg32:
op66(r32);
goto callreg;
case tk_reg:
op66(r16);
callreg:
if(faradd==0){
op(0xFF);
op(0xD0+(unsigned int)itok.number);
} /* CALL reg */
else invalidfarcallitem();
break;
case tk_ID:
case tk_id:
if(faradd==0){
tobedefined(am32==FALSE?CALL_NEAR:CALL_32,tk_void);
callloc0();
} /* CALL NEAR */
else invalidfarcallitem();
break;
case tk_declare:
tok=tk_undefproc;
updatetree();
case tk_locallabel:
case tk_undefproc:
if(faradd==0){
addacall((unsigned int)itok.number,
(unsigned char)((itok.flag&f_extern)!=0?CALL_EXT:(am32==FALSE?CALL_NEAR:CALL_32)));
callloc0();
} /* CALL NEAR */
else invalidfarcallitem();
break;
case tk_dwordvar:
case tk_longvar:
i=2;
if(am32==FALSE&&htok==0)faradd=8;
case tk_intvar:
case tk_wordvar:
i+=2;
CheckAllMassiv(bufrm,i,&strinf);
outseg(&itok,2);
op(0xFF); op(0x10+itok.rm+faradd);
outaddress(&itok);
break;
default:
preerror("Invalid item for CALL");
break;
}
#ifdef OPTVARCONST
FreeGlobalConst();
#endif
clearregstat();
break;
case a_cbw:
ClearReg(AX);
if(am32)op(0x66);
op(0x98); //CBW
break;
case a_cdq:
ClearReg(DX);
op66(r32);
op(0x99);
possiblecpu=3; //CDQ
break;
case a_clc:
op(0xF8); //CLC
break;
case a_cld:
op(0xFC); //CLD
break;
case a_cli:
op(0xFA); //CLI
break;
case a_clts: //CLTS
outword(0x060F);
possiblecpu=2;
break;
case a_cmc:
op(0xF5); //CMC
break;
case a_cmpsb:
ClearReg(SI);
ClearReg(DI);
op(0xA6);
break;
case a_cmpsw:
ClearReg(SI);
ClearReg(DI);
op66(r16);
op(0xA7);
break;
case a_cmpsd:
if(ScanTok3()==tk_camma&&tok2==tk_xmmreg){
xmm3instr(0xC2,0xF2);
possiblecpu=9;
next=0;
}
else{
ClearReg(SI);
ClearReg(DI);
op66(r32);
op(0xA7);
possiblecpu=3;
}
break;
case a_cmpxchg: //CMPXCHG
nexttok();
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
i=r16;
ClearReg(AX);
switch(htok){
case tk_reg32:
i=r32;
case tk_reg:
ClearReg(hstok.number);
switch(tok){
case tk_reg32:
if(i==r16)goto erreg;
case tk_reg:
op66(i);
outword(0xB10F);
op(128+64+(unsigned int)itok.number*8+hstok.number);
break;
case tk_longvar:
case tk_dwordvar:
if(i==r16)goto erreg;
case tk_intvar:
case tk_wordvar:
#ifdef OPTVARCONST
ClearVarByNum(&itok);
#endif
CheckAllMassiv(bufrm,i,&strinf);
op66(i);
outseg(&itok,3);
outword(0xB10F);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default:
erreg:
if(i==r16)wordvalexpected();
else dwordvalexpected();
break;
}
break;
case tk_beg:
ClearReg(hstok.number);
switch(tok){
case tk_beg:
outword(0xB00F);
op(128+64+(unsigned int)itok.number*8+hstok.number);
break;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(bufrm,1,&strinf);
outseg(&itok,3);
outword(0xB00F);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default: bytevalexpected(2);
break;
}
break;
case tk_charvar:
case tk_bytevar:
#ifdef OPTVARCONST
ClearVarByNum(&hstok);
#endif
if(tok!=tk_beg)begexpected(2);
CheckAllMassiv(hbuf,1,&hstr,&hstok);
KillVar(hstok.name);
outseg(&hstok,3);
outword(0xB00F);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
case tk_longvar:
case tk_dwordvar:
if(tok!=tk_reg32)reg32expected(2);
i=r32;
goto noint;
case tk_intvar:
case tk_wordvar:
if(tok!=tk_reg)regexpected(2);
noint:
#ifdef OPTVARCONST
ClearVarByNum(&hstok);
#endif
CheckAllMassiv(hbuf,i,&hstr,&hstok);
KillVar(hstok.name);
op66(i);
outseg(&hstok,3);
outword(0xB10F);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
default:
varexpected(1);
break;
}
possiblecpu=4;
break;
case a_cmpxchg8b: //CMPXCHG8B
nexttok();
if(tok!=tk_qwordvar)qwordvalexpected();
#ifdef OPTVARCONST
ClearVarByNum(&itok);
#endif
CheckAllMassiv(bufrm,8,&strinf);
KillVar(itok.name);
outseg(&itok,3);
outword(0xc70f);
op(itok.rm+8);
outaddress(&itok);
possiblecpu=5;
break;
case a_cwd:
ClearReg(DX);
op66(r16);
op(0x99); //CWD
break;
case a_cwde:
ClearReg(AX);
if(!am32)op(0x66);
op(0x98);
possiblecpu=3;
break;
case a_cpuid:
ClearReg(AX);
ClearReg(BX);
ClearReg(CX);
ClearReg(DX);
outword(0xa20f); //CPUID
possiblecpu=5;
break;
case a_daa:
ClearReg(AX);
op(0x27); //DAA
break;
case a_das:
ClearReg(AX);
op(0x2F); //DAS
break;
case a_db: //DB
dbgact++;
asmparam=FALSE;
do{
i=1;
nexttok();
CheckIP();
if(tok==tk_number){
hnumber=doconstdwordmath();
if(tok==tk_id&&strcmp((char *)string,"dup")==0){
i=hnumber;
nexttok();
CheckMinusNum();
if(tok==tk_number)hnumber=doconstdwordmath();
else numexpected();
}
for(;i!=0;i--)op(hnumber);
}
else if(tok==tk_string){
for(i=0;i<(unsigned int)itok.number;i++)opd(string[i]);
switch(itok.flag&3){
case zero_term:
if(itok.flag&s_unicod)opd(0);
opd(0);
break;
case dos_term:
if(itok.flag&s_unicod)opd(0);
opd('$');
break;
}
nexttok();
}
else{
numexpected();
nexttok();
}
}while(tok==tk_camma);
dbgact--;
next=0;
break;
case a_dd: //DD
faradd++;
case a_dw: //DW
DDDW(faradd);
next=0;
break;
case a_enter: //ENTER
ClearReg(BP);
op(0xC8);
nexttok();
if(tok==tk_number)outword((unsigned int)doconstlongmath());
else{
numexpected(1);
nexttok();
}
expecting2(tk_camma);
if(tok==tk_number)op((int)doconstlongmath());
else{
numexpected(2);
nexttok();
}
next=0;
possiblecpu=2;
break;
case a_emms: //EMMS
outword(0x770f);
possiblecpu=6;
break;
case a_imul: //IMUL
nexttok();
if(tok2!=tk_camma){
ClearReg(AX);
switch(tok){
case tk_reg32:
possiblecpu=3;
razr=r32;
case tk_reg:
ClearReg(DX);
op66(razr);
op(246+1);
op(128+64+40+(unsigned int)itok.number);
break;
case tk_beg:
op(246);
op(128+64+40+(unsigned int)itok.number);
break;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(bufrm,1,&strinf);
outseg(&itok,2);
op(246);
op(itok.rm+40);
outaddress(&itok);
break;
case tk_longvar:
case tk_dwordvar:
CheckAllMassiv(bufrm,4,&strinf);
possiblecpu=3;
razr=r32;
case tk_intvar:
case tk_wordvar:
CheckAllMassiv(bufrm,2,&strinf);
ClearReg(DX);
op66(razr);
outseg(&itok,2);
op(247);
op(itok.rm+40);
outaddress(&itok);
break;
default: varexpected(1); break;
}
}
else{
htok=tok;
hnumber=itok.number;
ClearReg(hnumber);
nextexpecting2(tk_camma);
possiblecpu=2;
if(tok2!=tk_camma){
switch(tok){
case tk_number:
switch(htok){
case tk_reg32:
possiblecpu=3;
razr=r32;
case tk_reg:
op66(razr);
if(short_ok(itok.number,TRUE))i=2; //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><>
op(0x69+i);
op(0xc0+(unsigned int)hnumber+(unsigned int)hnumber*8);
if(i==2)op(itok.number);
else{
if(htok==tk_reg)outword(itok.number);
else outdword(itok.number);
}
break;
default: reg32regexpected(1);
}
break;
case tk_reg32:
razr=r32;
case tk_reg:
op66(razr);
possiblecpu=3;
if(htok!=tok)reg32regexpected(1);
outword(0xaf0f);
op(0xc0+(unsigned int)itok.number+(unsigned int)hnumber*8);
break;
case tk_longvar:
tok++;
case tk_dwordvar:
if(htok!=tk_reg32)reg32expected(1);
CheckAllMassiv(bufrm,4,&strinf);
razr=r32;
goto imul1;
case tk_intvar:
tok++;
case tk_wordvar:
imul1:
possiblecpu=3;
if(htok!=tk_reg&&(tok==tk_intvar||tok==tk_wordvar))regexpected(1);
CheckAllMassiv(bufrm,2,&strinf);
op66(razr);
outseg(&itok,3);
outword(0xaf0f);
op(itok.rm+hnumber*8);
outaddress(&itok);
break;
default: varexpected(2);
}
}
else{
int htok2=tok;
hstok=itok;
hbuf=bufrm;
hstr=strinf;
strinf.bufstr=NULL;
bufrm=NULL;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(3);
switch(htok2){
case tk_reg32:
possiblecpu=3;
razr=r32;
case tk_reg:
op66(razr);
if(htok!=htok2)reg32regexpected(2);
if(short_ok(itok.number,TRUE))i=2; //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><>
op(0x69+i);
op(0xc0+(unsigned int)hstok.number+(unsigned int)hnumber*8);
if(i==2)op(itok.number);
else{
if(htok==tk_reg)outword(itok.number);
else outdword(itok.number);
}
break;
case tk_longvar:
tok++;
case tk_dwordvar:
possiblecpu=3;
if(htok!=tk_reg32)reg32expected(2);
CheckAllMassiv(hbuf,4,&hstr,&hstok);
razr=r32;
goto imul2;
case tk_intvar:
tok++;
case tk_wordvar:
imul2:
if(htok!=tk_reg&&(htok2==tk_intvar||htok2==tk_wordvar))regexpected(1);
CheckAllMassiv(hbuf,2,&hstr,&hstok);
op66(razr);
if(short_ok(itok.number,TRUE))i=2; //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><>
outseg(&hstok,2);
op(0x69+i);
op(hstok.rm+hnumber*8);
outaddress(&hstok);
if(i==2)op(itok.number);
else{
if(htok==tk_reg)outword(itok.number);
else outdword(itok.number);
}
break;
default: varexpected(2);
}
}
}
break;
case a_in: //IN
ClearReg(AX);
nexttok();
if((tok==tk_reg||tok==tk_reg32)&&(unsigned int)itok.number==AX){
op66(tok==tk_reg?r16:r32);
if(tok==tk_reg32)possiblecpu=3;
nexttok();
expecting(tk_camma);
if(tok==tk_number){
op(0xE5);
asmparam=FALSE;
if((hnumber=doconstdwordmath())>255)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); //<2F>뫮 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&&tok2<tk_qwordvar))){
movxmm(0x10,0xf2);
possiblecpu=9;
}
else movsd(); //MOVSD
break;
case a_movsw:
movsw(); //MOVSW
break;
case a_movzx:
case a_movsx:
asmextend((htok-a_movzx)*8+0xB6);
break;
case a_movd:
movd(); //MOVD
break;
case a_movq:
movq(); //MOVQ
break;
case a_nop:
op(0x90); //NOP
break;
case a_opsiz: //OPSIZ OPSIZE
op(0x66);
possiblecpu=3;
break;
case a_out: //OUT
nexttok();
if(tok==tk_number){
if((hnumber=doconstdwordmath())>255)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(cpu<possiblecpu)cpu=possiblecpu;
asmparam=FALSE;
addESP-=razr==r16?2:4;
nexttok();
}while(tok==tk_camma);
next=0;
break;
case a_popa: //POPA
razr=r16;
possiblecpu=2;
goto POPAD;
case a_popad: //POPAD
razr=r32;
possiblecpu=3;
POPAD:
op66(razr);
addESP-=razr==r16?16:32;
RestoreStack();
clearregstat();
op(0x61);
break;
case a_popf:
razr=r16;
goto POPFD;
case a_popfd: //POPFD
razr=r32;
possiblecpu = 3;
POPFD:
op66(razr);
addESP-=razr==r16?2:4;
RestoreStack();
op(0x9D);
break;
case a_push: //PUSH
RestoreStack();
do{
asmparam=TRUE;
nexttok();
if((razr=Push())==FALSE)preerror("Invalid operand for PUSH");
asmparam=FALSE;
addESP+=razr==r16?2:4;
}while(tok==tk_camma);
next=0;
break;
case a_pusha: //PUSHA
razr=r16;
possiblecpu=2;
goto PUSHAD;
case a_pushad: //PUSHAD
razr=r32;
possiblecpu=3;
PUSHAD:
op66(razr);
addESP+=razr==r16?16:32;
RestoreStack();
op(0x60);
break;
case a_pushf:
razr=r16;
goto PUSHFD;
case a_pushfd: //PUSHFD
razr=r32;
possiblecpu=3;
PUSHFD:
op66(razr);
RestoreStack();
op(0x9C);
addESP+=razr==r16?2:4;
break;
case a_pcmpeqd:
case a_pcmpeqw:
case a_pcmpeqb:
case a_packssdw: //+xmm
case a_punpckhdq:
case a_punpckhwd:
case a_punpckhbw:
case a_packuswb: //+xmm
case a_pcmpgtd:
case a_pcmpgtw:
case a_pcmpgtb:
case a_packsswb: //+xmm
case a_punpckldq:
case a_punpcklwd:
case a_punpcklbw:
mmxiii(htok-a_punpcklbw+0x60);
break;
case a_pmullw:
mmxiii(0xD5); //PMULLW
break;
case a_pmuludq:
mmxiii(0xF4); //PMULUDQ
break;
case a_psubusb:
mmxiii(0xD8); //PSUBUSB
break;
case a_psubusw:
mmxiii(0xD9);//PSUBUSW
break;
case a_pand: //+xmm
mmxiii(0xDB); //PAND
break;
case a_paddusb: //+xmm
mmxiii(0xDC); //PADDUSB
break;
case a_paddusw: //+xmm
mmxiii(0xDD);//PADDUSW
break;
case a_pandn: //+xmm
mmxiii(0xDF);//PANDN
break;
case a_pause:
outword(0x90F3);
possiblecpu=9;
break;
case a_pmulhw:
mmxiii(0xE5); //PMULHW
break;
case a_psubsb:
mmxiii(0xE8); //PSUBSB
break;
case a_psubsw:
mmxiii(0xE9);//PSUBSW
break;
case a_por:
mmxiii(0xEB); //POR
break;
case a_paddsb: //+xmm
mmxiii(0xEC); //PADDSB
break;
case a_paddsw: //+xmm
mmxiii(0xED);//PADDSW
break;
case a_pxor:
mmxiii(0xEF); //PXOR
break;
case a_pmaddwd:
mmxiii(0xF5); //PMADDWD
break;
case a_psubb:
mmxiii(0xF8); //PSUBB
break;
case a_psubw:
mmxiii(0xF9);//PSUBW
break;
case a_psubd:
mmxiii(0xFA);//PSUBD
break;
case a_psubq:
mmxiii(0xFB);//PSUBQ
possiblecpu=9;
break;
case a_paddb: //+xmm
mmxiii(0xFC); //PADDB
break;
case a_paddw: //+xmm
mmxiii(0xFD);//PADDW
break;
case a_paddd: //+xmm
mmxiii(0xFE);//PADDD
break;
case a_paddq: //+xmm
mmxiii(0xD4);//PADDQ
possiblecpu=9;
break;
case a_psrlw:
packMMX(0xD1,0x71,0xd0); //PSRLW
next=0;
break;
case a_psrld:
packMMX(0xD2,0x72,0xd0);//PSRLD
next=0;
break;
case a_psrlq:
packMMX(0xD3,0x73,0xd0);//PSRLQ
next=0;
break;
case a_psraw:
packMMX(0xE1,0x71,0xe0); //PSRAW
next=0;
break;
case a_psrad:
packMMX(0xE2,0x72,0xe0);//PSRAD
next=0;
break;
case a_psllw:
packMMX(0xF1,0x71,0xf0); //PSLLW
next=0;
break;
case a_pslld:
packMMX(0xF2,0x72,0xf0);//PSLLD
next=0;
break;
case a_psllq:
packMMX(0xF3,0x73,0xf0);//PSLLQ
next=0;
break;
case a_pslldq:
shiftxmm(7);
next=0;
possiblecpu=9;
break;
case a_psrldq:
shiftxmm(3);
next=0;
possiblecpu=9;
break;
case a_rdmsr:
ClearReg(AX);
ClearReg(DX);
outword(0X320F);
possiblecpu=5;
break;
case a_rdtsc:
outword(0X310F);
possiblecpu=5;
break;
case a_rep:
op(0xF3);//REP REPE REPZ
ClearReg(CX);
break;
case a_repnz:
op(0xF2); //REPNE REPNZ
ClearReg(CX);
break;
case a_ret: //RET
#ifdef OPTVARCONST
ClearLVIC();
#endif
RestoreStack();
clearregstat();
next=0;
if(tok2==tk_number){
// usedirectiv=TRUE;
nexttok();
op(0xC2);
asmparam=FALSE;
outword((unsigned int)doconstlongmath());
// usedirectiv=FALSE;
}
else{
op(0xC3);
nexttok();
}
break;
case a_retf:
#ifdef OPTVARCONST
ClearLVIC();
#endif
RestoreStack();
clearregstat();
next=0;
if(tok2==tk_number){
nexttok();
op(0xCA);
asmparam=FALSE;
outword((unsigned int)doconstlongmath());
}
else{
op(0xCB);
nexttok();
}//RETF
break;
case a_rsm: //RSM
outword(0Xaa0F);
possiblecpu=5;
break;
case a_sahf:
op(0x9E); //SAHF
break;
case a_scasb:
op(0xAE); //SCASB
ClearReg(DI);
break;
case a_scasw:
op66(r16);
op(0xAF); //SCASW
ClearReg(DI);
break;
case a_scasd: //SCASD
op66(r32);
op(0xAF);
possiblecpu=3;
ClearReg(DI);
break;
case a_smsw:
protectinstr(1,0x20); //SMSW
break;
case a_stc:
op(0xF9); //STC
break;
case a_std:
op(0xFD); //STD
break;
case a_sti:
op(0xFB); //STI
break;
case a_stosb:
stosb(); //STOSB
break;
case a_stosw:
stosw(); //STOSW
break;
case a_stosd:
stosd(); //STOSD
break;
case a_seto:
case a_setno:
case a_setc:
case a_setnc:
case a_setz:
case a_setnz:
case a_setna:
case a_seta:
case a_sets:
case a_setns:
case a_setp:
case a_setnp:
case a_setl:
case a_setnl:
case a_setng:
case a_setg:
i=htok-a_seto;
nexttok();
switch(tok){
case tk_beg:
ClearReg(itok.number%4);
op(0xf);
op(0x90+i);
op(0xc0+(unsigned int)itok.number);
break;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(bufrm,1,&strinf);
KillVar(itok.name);
outseg(&itok,3);
op(0xf);
op(0x90+i);
op(itok.rm);
outaddress(&itok);
break;
default: bytevalexpected(0);
}
possiblecpu=3;
break;
case a_sgdt:
next=tabldeckr(0);
break;
case a_sidt:
next=tabldeckr(0x8);
break;
case a_sldt:
protectinstr(0,0); //SLDT
break;
case a_fwait: //FWAIT
case a_wait:
fwait();//WAIT
break;
case a_wbinvd: //WBINVD
outword(0x090F);
possiblecpu=4;
break;
case a_wrmsr: //WRMSR
outword(0x300F);
possiblecpu=5;
break;
case a_xadd: //XADD
nexttok();
hstok=itok;
htok=tok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
switch(htok){
case tk_reg32:
razr=r32;
case tk_reg:
switch(tok){
case tk_reg32:
if(razr==r16)goto erxreg;
case tk_reg:
RegToReg(itok.number,hstok.number,razr);
ClearReg(hstok.number);
op66(razr);
outword(0xC10F);
op(128+64+(unsigned int)itok.number*8+hstok.number);
break;
case tk_longvar:
case tk_dwordvar:
if(razr==r16)goto erxreg;
case tk_intvar:
case tk_wordvar:
KillVar(hstok.name);
/*if(bufrm==0&&strinf.bufstr==NULL)*/AddRegVar(hstok.number,razr,&itok);
CheckAllMassiv(bufrm,razr,&strinf);
op66(razr);
outseg(&itok,3);
outword(0xC10F);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default:
erxreg:
wordvalexpected(); break;
}
break;
case tk_beg:
switch(tok){
case tk_beg:
RegToReg(itok.number,hstok.number,r8);
ClearReg(hstok.number%4);
outword(0xC00F);
op(128+64+(unsigned int)itok.number*8+hstok.number);
break;
case tk_charvar:
case tk_bytevar:
KillVar(hstok.name);
/*if(bufrm==0&&strinf.bufstr==NULL)*/AddRegVar(hstok.number,r8,&itok);
CheckAllMassiv(bufrm,1,&strinf);
outseg(&itok,3);
outword(0xC00F);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default: bytevalexpected(2); break;
}
break;
case tk_charvar:
case tk_bytevar:
if(tok!=tk_beg)begexpected(2);
CheckAllMassiv(hbuf,1,&hstr,&hstok);
ClearReg(itok.number);
KillVar(hstok.name);
outseg(&hstok,3);
outword(0xC00F);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
case tk_longvar:
case tk_dwordvar:
if(tok!=tk_reg32)reg32expected(2);
razr=r32;
goto nointxadd;
case tk_intvar:
case tk_wordvar:
if(tok!=tk_reg)regexpected(1);
nointxadd:
CheckAllMassiv(hbuf,razr,&hstr,&hstok);
ClearReg(itok.number);
KillVar(hstok.name);
op66(razr);
outseg(&hstok,3);
outword(0xC10F);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
default: varexpected(1); break;
}
possiblecpu=4;
break;
case a_xchg: //XCHG
nexttok();
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
switch(htok){
case tk_reg32:
razr=r32;
possiblecpu=3;
case tk_reg:
switch(tok){
case tk_reg32:
if(razr==r16)goto erregx;
case tk_reg:
op66(razr);
RegSwapReg(hstok.number,itok.number,razr);
if(hstok.number==AX)op(0x90+(unsigned int)itok.number);
else if((unsigned int)itok.number==AX)op(0x90+hstok.number);
else{
op(0x87);
op(128+64+(unsigned int)itok.number*8+hstok.number);
}
break;
case tk_longvar:
case tk_dwordvar:
if(razr==r16)goto erregx;
case tk_intvar:
case tk_wordvar:
CheckAllMassiv(bufrm,razr,&strinf);
KillVar(itok.name);
IDZToReg(itok.name,hstok.number,razr);
op66(razr);
outseg(&itok,2);
op(0x87);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default:
erregx:
wordvalexpected(); break;
}
break;
case tk_beg:
switch(tok){
case tk_beg:
RegSwapReg(hstok.number,itok.number,r8);
op(0x86);
op(128+64+(unsigned int)itok.number*8+hstok.number);
break;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(bufrm,1,&strinf);
KillVar(itok.name);
IDZToReg(itok.name,hstok.number,r8);
outseg(&itok,2);
op(0x86);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default: bytevalexpected(2); break;
}
break;
case tk_charvar:
case tk_bytevar:
if(tok!=tk_beg)begexpected(2);
CheckAllMassiv(hbuf,1,&hstr,&hstok);
KillVar(hstok.name);
IDZToReg(hstok.name,itok.number,r8);
outseg(&hstok,2);
op(0x86);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
case tk_longvar:
case tk_dwordvar:
razr=r32;
possiblecpu=3;
if(tok!=tk_reg32)reg32expected(2);
goto nointx;
case tk_intvar:
case tk_wordvar:
if(tok!=tk_reg)regexpected(2);
nointx:
CheckAllMassiv(hbuf,razr,&hstr,&hstok);
KillVar(hstok.name);
IDZToReg(hstok.name,itok.number,razr);
op66(razr);
outseg(&hstok,2);
op(0x87);
op(hstok.rm+(unsigned int)itok.number*8);
outaddress(&hstok);
break;
default: varexpected(1); break;
}
break;
case a_xlat:
ClearReg(AX);
op(0xD7); //XLAT
break;
case a_hlt:
op(0xF4); //HLT
break;
case a_verr:
protectinstr(0,0x20); //VERR
break;
case a_verw:
protectinstr(0,0x28); //VERW
break;
case a_test: //TEST
if(iTest()==FALSE)invalidoperand(0);
next=0;
break;
case a_fcom: //FCOM
FpuType1(0x10);
break;
case a_fcomp: //FCOMP
FpuType1(0x18);
break;
case a_fadd: //FADD
FpuType2(0,0);
break;
case a_fdiv: //FDIV
FpuType2(0x38,0x30);
break;
case a_fdivr: //FDIVR
FpuType2(0x30,0x38);
break;
case a_fmul: //FMUL
FpuType2(0x8,0x8);
break;
case a_fsub: //FSUB
FpuType2(0x28,0x20);
break;
case a_fsubr: //FSUBR
FpuType2(0x20,0x28);
break;
case a_faddp: //FADDP
FpuType3(0xDE,0);
break;
case a_fdivp: //FDIVP
FpuType3(0xDE,0x38);
break;
case a_fdivrp: //FDIVRP
FpuType3(0xDE,0x30);
break;
case a_ffree: //FFREE
FpuType3(0xDD,0);
break;
case a_fmulp: //FMULP
FpuType3(0xDE,8);
break;
case a_fsubp: //FSUBP
FpuType3(0xDE,0x28);
break;
case a_fsubrp: //FSUBRP
FpuType3(0xDE,0x20);
break;
case a_fucom: //FUCOM
FpuType3(0xDD,0x20);
break;
case a_fucomp: //FUCOMP
FpuType3(0xDD,0x28);
break;
case a_fxch: //FXCH
FpuType3(0xD9,8);
break;
case a_fiadd: //FIADD
FpuType4(0,0);
break;
case a_ficom: //FICOM
FpuType4(0,0x10);
break;
case a_ficomp: //FICOMP
FpuType4(0,0x18);
break;
case a_fidiv: //FIDIV
FpuType4(0,0x30);
break;
case a_fidivr: //FIDIVR
FpuType4(0,0x38);
break;
case a_fild: //FILD
FpuType4(1,0);
break;
case a_fimul: //FIMUL
FpuType4(0,8);
break;
case a_fist: //FIST
FpuType4(1,0x10);
break;
case a_fistp: //FISTP
FpuType4(1,0x18);
break;
case a_fisub: //FISUB
FpuType4(0,0x20);
break;
case a_fisubr: //FISUBR
FpuType4(0,0x28);
break;
case a_fld: //FLD
FpuType5(0xD9,0);
break;
case a_fst: //FST
FpuType5(0xDD,0x10);
break;
case a_fstp: //FSTP
FpuType5(0xDD,0x18);
break;
case a_fbld: //FBLD
FpuType6(0xDF,0X20);
break;
case a_fbstp: //FBSTP
FpuType6(0xDF,0X30);
break;
case a_fildq: //FILDQ
FpuType6(0xDF,0x28);
break;
case a_fldenv: //FLDENV <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FpuType6(0xD9,0x20);
break;
case a_frstor: //FRSTOR <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FpuType6(0xDD,0x20);
break;
case a_fsave: //FSAVE <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
fwait();
case a_fnsave: //FNSAVE <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FpuType6(0xDD,0x30);
break;
case a_fstenv: //FSTENV <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
fwait();
case a_fnstenv: //FNSTENV <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
FpuType6(0xD9,0x30);
break;
case a_fldcw: //FLDCW
FpuType7(0x28);
break;
case a_fstcw: //FSTCW
fwait();
case a_fnstcw: //FNSTCW
FpuType7(0x38);
break;
case a_f2xm1:
outword(0xf0d9); //F2XM1
possiblecpu=2;
break;
case a_fabs:
outword(0xE1D9); //FABS
break;
case a_fchs:
outword(0xE0D9); //FCHS
break;
case a_fclex: //FCLEX
fwait();
// outword(0xE2DB);
// break;
case a_fnclex:
outword(0xE2DB); //FNCLEX
break;
case a_fcompp:
outword(0xD9DE); //FCOMPP
break;
case a_fcos: //FCOS
outword(0xFFD9);
possiblecpu=3;
break;
case a_fdecstr:
outword(0xF6D9); //FDECSTP
break;
case a_fdisi:
fwait();
case a_fndisi:
outword(0xE1DB); //FDISI
break;
case a_feni:
fwait();
case a_fneni:
outword(0xE0DB); //FENI
break;
case a_fincstr:
outword(0xF7D9); //FINCSTP
break;
case a_finit: //FINIT
fwait();
case a_fninit:
outword(0xE3DB); //FNINIT
break;
case a_fldlg2:
outword(0xECD9); //FLDLG2
break;
case a_fldln2:
outword(0xEDD9); //FLDLN2
break;
case a_fldl2e:
outword(0xEAD9); //FLDL2E
break;
case a_fldl2t:
outword(0xE9D9); //FLDL2T
break;
case a_fldpi:
outword(0xEBD9); //FLDPI
break;
case a_fldz:
outword(0xEED9); //FLDZ
break;
case a_fld1:
outword(0xE8D9); //FLD1
break;
case a_fnop:
outword(0xD0D9); //FNOP
break;
case a_fpatan:
outword(0xF3D9); //FPATAN
break;
case a_fprem:
outword(0xF8D9); //FPREM
break;
case a_fprem1:
outword(0xF5D9); //FPREM1
possiblecpu=3;
break;
case a_fptan:
outword(0xF2D9); //FPTAN
break;
case a_frndint:
outword(0xFCD9); //FRNDINT
break;
case a_fsetpm:
fwait();
case a_fnsetpm:
outword(0xE4DB); //FSETPM
possiblecpu=2;
break;
case a_fscale:
outword(0XFDD9); //FSCALE
break;
case a_fsin: //FSIN
outword(0xFED9);
possiblecpu=3;
break;
case a_fsincos: //FSINCOS
outword(0xFBD9);
possiblecpu=3;
break;
case a_fsqrt:
outword(0xFAD9); //FSQRT
break;
case a_fstsw: //FSTSW
fwait();
case a_fnstsw: //FNSTSW
nexttok();
switch(tok){
case tk_wordvar:
case tk_intvar:
CheckAllMassiv(bufrm,2,&strinf);
KillVar(itok.name);
outseg(&itok,2);
op(0xDD);
op(itok.rm+0x38);
outaddress(&itok);
break;
case tk_reg:
if(itok.number==0)outword(0xe0df);
else preerror("Use only AX");
ClearReg(AX);
break;
default: wordvalexpected();
}
break;
case a_ftst:
outword(0xE4D9); //FTST
break;
case a_fucompp: //FUCOMPP
outword(0xE9DA);
possiblecpu=3;
break;
case a_fxam:
outword(0xE5D9); //FXAM
break;
case a_fxtract:
outword(0xF4D9); //FXTRACT
break;
case a_fyl2x:
outword(0xF1D9); //FYL2X
break;
case a_fyl2xp1:
outword(0xF9D9); //FYL2XP1
break;
case a_ud2:
outword(0x0B0F); //UD2
possiblecpu=7;
break;
case a_sysenter:
outword(0x340F); //SYSENTER
possiblecpu=7;
break;
case a_sysexit:
outword(0x350F); //SYSEXIT
possiblecpu=7;
break;
case a_rdpmc:
outword(0x330F); //RDPMC
possiblecpu=7;
break;
case a_fcmovnu:
i+=8;
case a_fcmovnbe:
i+=8;
case a_fcmovne:
i+=8;
case a_fcmovnb:
FpuType8(0xDB,i);
break;
case a_fcmovu:
i+=8;
case a_fcmovbe:
i+=8;
case a_fcmove:
i+=8;
case a_fcmovb:
FpuType8(0xDA,i);
break;
case a_fcomi: //FCOMI
i+=8;
case a_fucomi:
FpuType8(0xDB,i+0x28);
break;
case a_fcomip:
i+=8;
case a_fucomip:
FpuType8(0xDF,i+0x28);
break;
case a_cmovo:
case a_cmovno:
case a_cmovc:
case a_cmovnc:
case a_cmovz:
case a_cmovnz:
case a_cmovna:
case a_cmova:
case a_cmovs:
case a_cmovns:
case a_cmovp:
case a_cmovnp:
case a_cmovl:
case a_cmovnl:
case a_cmovng:
case a_cmovg:
cmov(htok-a_cmovo);
possiblecpu=7;
break;
case a_lfence: //LFENCE
outword(0xAE0F);
op(0xE8);
possiblecpu=9;
break;
case a_mfence: //MFENCE
outword(0xAE0F);
op(0xF0);
possiblecpu=9;
break;
case a_sfence: //SFENCE
outword(0xAE0F);
op(0xF8);
possiblecpu=8;
break;
case a_maskmovq: //MASKMOVQ
nexttok();
hnumber=itok.number;
if(tok!=tk_mmxreg)mmxregexpected(1);
nextexpecting2(tk_camma);
if(tok!=tk_mmxreg)mmxregexpected(2);
outword(0xF70F);
op(0xC0+hnumber+itok.number*8);
possiblecpu=8;
break;
case a_movntq: //MOVNTQ
movxmm3(0xE7,0,tk_mmxreg);
possiblecpu=8;
break;
case a_pavgb:
mmxiii(0xE0);
break;
case a_pavgw:
mmxiii(0xE3);
break;
case a_pmaxub:
mmxiii(0xDE);
break;
case a_pmaxsw:
mmxiii(0xEE);
break;
case a_pminub:
mmxiii(0xDA);
break;
case a_pminsw:
mmxiii(0xEA);
break;
case a_pmulhuw:
mmxiii(0xE4);
break;
case a_psadbw:
mmxiii(0xF6);
break;
case a_prefetcht0:
prefetch(0x18,1);
possiblecpu=8;
break;
case a_prefetcht1:
prefetch(0x18,2);
possiblecpu=8;
break;
case a_prefetcht2:
prefetch(0x18,3);
possiblecpu=8;
break;
case a_prefetchnta:
prefetch(0x18,0);
possiblecpu=8;
break;
case a_pextrw:
pextrw();
next=0;
break;
case a_pinsrw:
pinsrw();
next=0;
break;
case a_pmovmskb:
nexttok();
if(tok!=tk_reg32)reg32expected(1);
htok=itok.number;
ClearReg(htok);
nextexpecting2(tk_camma);
if(tok==tk_xmmreg){
op(0x66);
possiblecpu=9;
}
else{
possiblecpu=8;
if(tok!=tk_mmxreg)mmxregexpected(2);
}
outword(0xD70F);
op(rm_mod11+htok*8+itok.number);
break;
case a_pshufw:
pshufw();
next=0;
possiblecpu=8;
break;
case a_pshufd:
xmm3instr(0x70,0x66);
possiblecpu=9;
next=0;
break;
case a_pshufhw:
xmm3instr(0x70,0xf3);
possiblecpu=9;
next=0;
break;
case a_pshuflw:
xmm3instr(0x70,0xf2);
possiblecpu=9;
next=0;
break;
case a_addpd:
xmminstr(0x58,0x66);
possiblecpu=9;
break;
case a_addps:
xmminstr(0x58,0);
possiblecpu=8;
break;
case a_addsd:
xmminstr(0x58,0xF2);
possiblecpu=9;
break;
case a_addss:
xmminstr(0x58,0xF3);
possiblecpu=8;
break;
case a_addsubpd:
xmminstr(0xD0,0x66);
possiblecpu=9;
break;
case a_addsubps:
xmminstr(0xD0,0xF2);
possiblecpu=9;
break;
case a_andnpd:
xmminstr(0x55,0x66);
possiblecpu=9;
break;
case a_andnps:
xmminstr(0x55,0);
possiblecpu=8;
break;
case a_andpd:
xmminstr(0x54,0x66);
possiblecpu=9;
break;
case a_andps:
xmminstr(0x54,0);
possiblecpu=8;
break;
case a_comisd:
xmminstr(0x2F,0x66);
possiblecpu=9;
break;
case a_comiss:
xmminstr(0x2F,0);
possiblecpu=8;
break;
case a_divps:
xmminstr(0x5E,0);
possiblecpu=8;
break;
case a_divsd:
xmminstr(0x5E,0xf2);
possiblecpu=9;
break;
case a_divss:
xmminstr(0x5E,0xF3);
possiblecpu=8;
break;
case a_haddpd:
xmminstr(0x7C,0x66);
possiblecpu=9;
break;
case a_haddps:
xmminstr(0x7C,0xF2);
possiblecpu=9;
break;
case a_hsubpd:
xmminstr(0x7D,0x66);
possiblecpu=9;
break;
case a_hsubps:
xmminstr(0x7D,0xF2);
possiblecpu=9;
break;
case a_maskmovdqu:
xmm2xmm(0xf7,0x66);
possiblecpu=9;
break;
case a_maxpd:
xmminstr(0x5f,0x66);
possiblecpu=9;
break;
case a_maxps:
xmminstr(0x5F,0);
possiblecpu=8;
break;
case a_maxsd:
xmminstr(0x5f,0xf2);
possiblecpu=9;
break;
case a_maxss:
xmminstr(0x5F,0xF3);
possiblecpu=8;
break;
case a_minpd:
xmminstr(0x5d,0x66);
possiblecpu=9;
break;
case a_minps:
xmminstr(0x5D,0);
possiblecpu=8;
break;
case a_minsd:
xmminstr(0x5d,0xf2);
possiblecpu=9;
break;
case a_minss:
xmminstr(0x5D,0xF3);
possiblecpu=8;
break;
case a_mulpd:
xmminstr(0x59,0x66);
possiblecpu=9;
break;
case a_mulps:
xmminstr(0x59,0);
possiblecpu=8;
break;
case a_mulsd:
xmminstr(0x59,0xF2);
possiblecpu=9;
break;
case a_mulss:
xmminstr(0x59,0xF3);
possiblecpu=8;
break;
case a_orpd:
xmminstr(0x56,0x66);
possiblecpu=9;
break;
case a_orps:
xmminstr(0x56,0);
possiblecpu=8;
break;
case a_rcpps:
xmminstr(0x53,0);
possiblecpu=8;
break;
case a_rcpss:
xmminstr(0x53,0xF3);
possiblecpu=8;
break;
case a_rsqrtps:
xmminstr(0x52,0);
possiblecpu=8;
break;
case a_rsqrtss:
xmminstr(0x52,0xF3);
possiblecpu=8;
break;
case a_sqrtpd:
xmminstr(0x51,0x66);
possiblecpu=9;
break;
case a_sqrtps:
xmminstr(0x51,0);
possiblecpu=8;
break;
case a_sqrtsd:
xmminstr(0x51,0xf2);
possiblecpu=9;
break;
case a_sqrtss:
xmminstr(0x51,0xF3);
possiblecpu=8;
break;
case a_subpd:
xmminstr(0x5C,0x66);
possiblecpu=9;
break;
case a_subps:
xmminstr(0x5C,0);
possiblecpu=8;
break;
case a_subsd:
xmminstr(0x5C,0xF2);
possiblecpu=9;
break;
case a_subss:
xmminstr(0x5C,0xF3);
possiblecpu=8;
break;
case a_ucomisd:
xmminstr(0x2E,0x66);
possiblecpu=9;
break;
case a_ucomiss:
xmminstr(0x2E,0);
possiblecpu=8;
break;
case a_unpckhpd:
xmminstr(0x15,0x66);
possiblecpu=9;
break;
case a_unpckhps:
xmminstr(0x15,0);
possiblecpu=8;
break;
case a_unpcklpd:
xmminstr(0x14,0x66);
possiblecpu=9;
break;
case a_unpcklps:
xmminstr(0x14,0);
possiblecpu=8;
break;
case a_xorpd:
xmminstr(0x57,0x66);
possiblecpu=9;
break;
case a_xorps:
xmminstr(0x57,0);
possiblecpu=8;
break;
case a_cmppd:
xmm3instr(0xC2,0x66);
possiblecpu=9;
next=0;
break;
case a_cmpeqpd:
case a_cmpltpd:
case a_cmplepd:
case a_cmpunordpd:
case a_cmpneqpd:
case a_cmpnltpd:
case a_cmpnlepd:
case a_cmpordpd:
xmminstr(0xC2,0x66);
possiblecpu=9;
op(htok-a_cmpeqpd);
break;
case a_cmpps:
xmm3instr(0xC2,0);
possiblecpu=8;
next=0;
break;
case a_cmpeqps:
case a_cmpltps:
case a_cmpleps:
case a_cmpunordps:
case a_cmpneqps:
case a_cmpnltps:
case a_cmpnleps:
case a_cmpordps:
xmminstr(0xC2,0);
possiblecpu=9;
op(htok-a_cmpeqps);
break;
case a_cmpss:
xmm3instr(0xC2,0xF3);
possiblecpu=8;
next=0;
break;
case a_cmpeqss:
case a_cmpltss:
case a_cmpless:
case a_cmpunordss:
case a_cmpneqss:
case a_cmpnltss:
case a_cmpnless:
case a_cmpordss:
xmminstr(0xC2,0xF3);
possiblecpu=9;
op(htok-a_cmpeqss);
break;
case a_cmpeqsd:
case a_cmpltsd:
case a_cmplesd:
case a_cmpunordsd:
case a_cmpneqsd:
case a_cmpnltsd:
case a_cmpnlesd:
case a_cmpordsd:
xmminstr(0xC2,0xF2);
op(htok-a_cmpeqsd);
possiblecpu=9;
break;
case a_shufpd:
xmm3instr(0xC6,0x66);
possiblecpu=9;
next=0;
break;
case a_shufps:
xmm3instr(0xC6,0);
possiblecpu=8;
next=0;
break;
case a_cvtdq2pd:
xmminstr(0xE6,0xF3);
possiblecpu=9;
break;
case a_cvtdq2ps:
xmminstr(0x5B,0);
possiblecpu=9;
break;
case a_cvtpd2dq:
xmminstr(0xE6,0xF2);
possiblecpu=9;
break;
case a_cvtpd2pi:
xmminstr(0x2d,0x66,tk_mmxreg,tk_xmmreg);
possiblecpu=9;
break;
case a_cvtpd2ps:
xmminstr(0x5a,0x66);
possiblecpu=9;
break;
case a_cvtpi2pd:
xmminstr(0x2a,0x66,tk_xmmreg,tk_mmxreg);
possiblecpu=9;
break;
case a_cvtpi2ps:
xmminstr(0x2a,0,tk_xmmreg,tk_mmxreg);
possiblecpu=8;
break;
case a_cvtps2dq:
xmminstr(0x5b,0x66);
possiblecpu=9;
break;
case a_cvtps2pd:
xmminstr(0x5a,0);
possiblecpu=9;
break;
case a_cvtsi2ss:
xmminstr(0x2a,0xf3,tk_xmmreg,tk_reg32);
possiblecpu=8;
break;
case a_cvtps2pi:
xmminstr(0x2d,0,tk_mmxreg,tk_xmmreg);
possiblecpu=9;
break;
case a_cvtsd2si:
xmminstr(0x2d,0xf2,tk_reg32,tk_xmmreg);
possiblecpu=9;
break;
case a_cvtsd2ss:
xmminstr(0x5a,0xf2);
possiblecpu=9;
break;
case a_cvtsi2sd:
xmminstr(0x2a,0xf2,tk_xmmreg,tk_reg32);
possiblecpu=9;
break;
case a_cvtss2sd:
xmminstr(0x5a,0xf3);
possiblecpu=9;
break;
case a_cvtss2si:
xmminstr(0x2d,0xf3,tk_reg32,tk_xmmreg);
possiblecpu=8;
break;
case a_cvttpd2pi:
xmminstr(0x2c,0x66,tk_mmxreg,tk_xmmreg);
possiblecpu=9;
break;
case a_cvttpd2dq:
xmminstr(0xE6,0x66);
possiblecpu=9;
break;
case a_cvttps2dq:
xmminstr(0x5B,0xF3);
possiblecpu=9;
break;
case a_cvttps2pi:
xmminstr(0x2c,0,tk_mmxreg,tk_xmmreg);
possiblecpu=8;
break;
case a_cvttsd2si:
xmminstr(0x2C,0xF2,tk_reg32,tk_xmmreg);
possiblecpu=9;
break;
case a_cvttss2si:
xmminstr(0x2C,0xF3,tk_reg32,tk_xmmreg);
possiblecpu=8;
break;
case a_divpd:
xmminstr(0x5E,0x66);
possiblecpu=9;
break;
case a_punpckhqdq:
xmminstr(0x6D,0x66);
possiblecpu=9;
break;
case a_punpcklqdq:
xmminstr(0x6C,0x66);
possiblecpu=9;
break;
case a_fxrstor:
prefetch(0xAE,1);
possiblecpu=8;
break;
case a_fxsave:
prefetch(0xAE,0);
possiblecpu=8;
break;
case a_ldmxcsr:
prefetch(0xAE,2);
possiblecpu=8;
break;
case a_stmxcsr:
prefetch(0xAE,3);
possiblecpu=8;
break;
case a_clflush:
prefetch(0xAE,7);
possiblecpu=9;
break;
case a_monitor:
outword(0x010F);
op(0xc8);
possiblecpu=9;
break;
case a_mwait:
outword(0x010F);
op(0xc9);
possiblecpu=9;
break;
case a_lddqu:
movxmm4(0xF0,0xF2);
possiblecpu=9;
break;
case a_movhlps:
xmm2xmm(0x12);
possiblecpu=8;
break;
case a_movlhps:
xmm2xmm(0x16);
possiblecpu=8;
break;
case a_movmskps:
xmm2xmm(0x50,0,tk_reg32);
possiblecpu=8;
break;
case a_movntdq:
movxmm3(0xE7,0x66);
possiblecpu=9;
break;
case a_movntpd:
movxmm3(0x2B,0x66);
possiblecpu=9;
break;
case a_movntps:
movxmm3(0x2b,0);
possiblecpu=8;
break;
case a_movapd:
movxmm(0x28,0x66);
possiblecpu=9;
break;
case a_movaps:
movxmm(0x28,0);
possiblecpu=8;
break;
case a_movdqa:
movxmm(0x6f,0x66,0x10);
possiblecpu=9;
break;
case a_movddup:
xmminstr(0x12,0xF2);
possiblecpu=9;
break;
case a_movshdup:
xmminstr(0x16,0xF3);
possiblecpu=9;
break;
case a_movsldup:
xmminstr(0x12,0xF3);
possiblecpu=9;
break;
case a_movdqu:
movxmm(0x6f,0xf3,0x10);
possiblecpu=9;
break;
case a_movdq2q:
xmm2xmm(0xd6,0xf2,tk_mmxreg);
possiblecpu=9;
break;
case a_movhpd:
movxmm2(0x16,0x66);
possiblecpu=9;
break;
case a_movlpd:
movxmm2(0x12,0x66);
possiblecpu=9;
break;
case a_movmskpd:
xmm2xmm(0x50,0x66,tk_reg32);
possiblecpu=9;
break;
case a_movnti: //MOVNTI
movxmm3(0xC3,0,tk_reg32);
possiblecpu=9;
break;
case a_movq2dq: //MOVQ2DQ
nexttok();
hnumber=itok.number;
if(tok!=tk_xmmreg)xmmregexpected(1);
nextexpecting2(tk_camma);
if(tok!=tk_mmxreg)mmxregexpected(2);
op(0xF3);
outword(0xD60F);
op(0xC0+hnumber+itok.number*8);
possiblecpu=9;
break;
case a_movupd:
movxmm(0x10,0x66);
possiblecpu=9;
break;
case a_movups:
movxmm(0x10,0);
possiblecpu=8;
break;
case a_movss:
movxmm(0x10,0xF3);
possiblecpu=8;
break;
case a_movhps:
movxmm2(0x16);
possiblecpu=8;
break;
case a_movlps:
movxmm2(0x12);
possiblecpu=8;
break;
case -1: codeexpected(); break;
default:
preerror("sorry, this instruction is not supported");
break;
}
asmparam=FALSE;
if(cpu<possiblecpu)cpu=possiblecpu;
if(next)nexttok();
}
else if(tok==tk_seg){
switch((unsigned int)itok.number){
case ES: op(0x26); break;
case SS: op(0x36); break;
case CS: op(0x2E); break;
case DS: op(0x3E); break;
case FS: op(0x64);
if(cpu<3)cpu=3;
break;
case GS: op(0x65);
if(cpu<3)cpu=3;
break;
default: beep(); break;
}
nextexpecting2(tk_colon);
}
else if(tok==tk_locallabel)define_locallabel();
else if(tok==tk_at&&ScanTok3()==tk_colon){
nexttok();
LLabel();
}
else codeexpected();
if(tok==tk_semicolon)nexttok();
}
void cmov(int num)
{
int type=r32;
int reg;
nexttok();
if(tok==tk_reg)type=r16;
else if(tok!=tk_reg32)reg32regexpected(1);
reg=itok.number;
ClearReg(reg);
nextexpecting2(tk_camma);
op66(type);
switch(tok){
case tk_reg:
if(type==r32)reg32expected(2);
goto regs;
case tk_reg32:
if(type==r16)regexpected(2);
regs:
op(0x0F);
op(0x40+num);
op(0xC0+reg*8+itok.number);
break;
case tk_wordvar:
case tk_intvar:
if(type==r32)dwordvalexpected();
CheckAllMassiv(bufrm,2,&strinf);
goto dwords;
case tk_dwordvar:
case tk_longvar:
if(type==r16)wordvalexpected();
CheckAllMassiv(bufrm,4,&strinf);
dwords:
outseg(&itok,3);
op(0x0F);
op(0x40+num);
op(itok.rm+reg*8);
outaddress(&itok);
break;
default:
varexpected(2);
break;
}
}
#ifdef OPTVARCONST
int GetOperand(int code)
{
switch(code){
case a_inc: //INC
case a_add: return tk_plus;
case a_or: return tk_or;
case a_and: return tk_and;
case a_dec: //DEC
case a_sub: return tk_minus;
case a_xor: return tk_xor;
case a_not: return tk_not;
case a_neg: return tk_numsign;
case a_shl: return tk_ll;
case a_shr: return tk_rr;
}
return tokens;
}
#endif
void asmtwo1(int basecode) // used for ADD ADC SUB SBB CMP AND OR XOR.
{
unsigned long holdnumber2;
int htok,typet=r16;
long longholdnumber;
char *hbuf;
ITOK hstok;
unsigned char next=1;
SINFO hstr;
#ifdef OPTVARCONST
int initconst=FALSE;
int operand=GetOperand(basecode/8);
#endif
nexttok();
hstok=itok;
htok=tok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
int i=tok;
switch(htok){
case tk_reg:
if((basecode/8)!=a_cmp)ClearReg(hstok.number);
switch(tok){
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:
asmparam=FALSE;
holdnumber2=doconstlongmath();
next=0;
op66(r16);
if(hstok.number==AX){
op(4+1+basecode);
if((postnumflag&f_reloc)!=0)AddReloc();
if(i==tk_undefofs)AddUndefOff(2,hstok.name);
outword(holdnumber2);
}
else{
if((postnumflag&f_reloc)==0&&short_ok(holdnumber2)){
op(128+2+1);
op(128+64+hstok.number+basecode);
op(holdnumber2);
}
else{
op(128+1);
op(128+64+hstok.number+basecode);
if((postnumflag&f_reloc)!=0)AddReloc();
if(i==tk_undefofs)AddUndefOff(2,hstok.name);
outword(holdnumber2);
}
}
break;
case tk_postnumber:
op66(r16);
if(hstok.number==AX)op(4+1+basecode);
else{
op(128+1);
op(128+64+hstok.number+basecode);
}
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
outword((unsigned int)itok.number);
break;
case tk_reg:
op66(r16);
op(2+1+basecode);
op(128+64+(unsigned int)itok.number+hstok.number*8);
break;
case tk_wordvar:
case tk_intvar:
CheckAllMassiv(bufrm,2,&strinf);
op66(r16);
outseg(&itok,2);
op(2+1+basecode);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default: wordvalexpected(); break;
}
break;
case tk_reg32:
if((basecode/8)!=a_cmp)ClearReg(hstok.number);
switch(tok){
case tk_undefofs:
strcpy(hstok.name,itok.name);
tok=tk_number;
goto dnum;
case tk_minus:
i=tk_number;
if(tok2!=tk_number){
dwordvalexpected();
break;
}
case tk_number:
dnum:
op66(r32);
asmparam=FALSE;
longholdnumber=doconstdwordmath();
next=0;
if(i==tk_number&&(postnumflag&f_reloc)==0&&short_ok(longholdnumber,TRUE)){
op(128+2+1);
op(128+64+hstok.number+basecode);
op((int)longholdnumber);
}
else{
if(hstok.number==EAX)op(4+1+basecode);
else{
op(128+1);
op(128+64+hstok.number+basecode);
}
if((postnumflag&f_reloc)!=0)AddReloc();
if(i==tk_undefofs)AddUndefOff(2,hstok.name);
outdword(longholdnumber);
}
break;
case tk_postnumber:
op66(r32);
if(hstok.number==EAX)op(4+1+basecode);
else{
op(128+1);
op(128+64+hstok.number+basecode);
}
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
outdword(itok.number);
break;
case tk_reg32:
op66(r32);
op(2+1+basecode);
op(128+64+(unsigned int)itok.number+hstok.number*8);
break;
case tk_dwordvar:
case tk_longvar:
CheckAllMassiv(bufrm,4,&strinf);
op66(r32);
outseg(&itok,2);
op(2+1+basecode);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default: dwordvalexpected(); break;
}
if(cpu<3)cpu=3;
break;
case tk_beg:
if((basecode/8)!=a_cmp)ClearReg(hstok.number>3?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; //ᬥ饭<E1ACA5><E9A5AD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
goto undefproc;
}
jumploc(itok.number); //<2F><> <20><><EFBFBD><EFBFBD><E6A5A4><EFBFBD> <20><><EFBFBD><><E0A0AD><EFBFBD>
break;
case tk_number:
asmparam=FALSE;
jumploc(doconstlongmath());//<2F><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
next=0;
break;
case tk_ID:
addlocaljump(CALL_SHORT); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
outword(0x00EB); // JMP SHORT
break;
case tk_id:
tobedefined(CALL_SHORT,tk_void);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFA2AB><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
outword(0x00EB); // JMP SHORT
break;
case tk_declare:
tok=tk_undefproc;
updatetree();
case tk_locallabel:
case tk_undefproc: //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFA2AB><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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; //ᬥ饭<E1ACA5><E9A5AD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <><E0A5A6>
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); //<2F>뫮 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<possiblecpu)cpu=possiblecpu;
if(next)nexttok();
return TRUE;
}
void mmxiii(int type)
{
int num1,i=1;
int xmm=FALSE;
nexttok();
if(tok==tk_xmmreg)xmm=TRUE;
else if(tok!=tk_mmxreg)mmxregexpected(1);
num1=itok.number;
nextexpecting2(tk_camma);
switch(tok){
case tk_mmxreg:
if(xmm)xmmregorvarexpected(2);
op(0x0F);
op(type);
op(rm_mod11+itok.number+num1*8);
break;
case tk_xmmreg:
if(xmm==FALSE)mmxormem(2);
outword(0x0F66);
op(type);
op(rm_mod11+itok.number+num1*8);
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(type);
op(itok.rm+num1*8);
outaddress(&itok);
break;
default:
mmxormem(2);
break;
}
if(cpu<8)cpu=8;
if(xmm&&cpu<9)cpu=9;
}
void prefetch(int code,int type)
{
int i=1;
nexttok();
switch(tok){
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);
KillVar(itok.name);
outseg(&itok,3);
op(0x0f);
op(code);
op(itok.rm+type*8);
outaddress(&itok);
break;
default:
datatype_expected(1);
break;
}
}
void pextrw()
{
int num1,num2;
int xmm=FALSE;
nexttok();
if(tok!=tk_reg32)reg32expected(1);
num1=itok.number;
ClearReg(num1);
nextexpecting2(tk_camma);
if(tok==tk_xmmreg)xmm=TRUE;
else if(tok!=tk_mmxreg)mmxregexpected(2);
num2=itok.number;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(3);
if(xmm)op(0x66);
outword(0xC50F);
op(rm_mod11+num1+num2*8);
op(doconstdwordmath());
if(cpu<8)cpu=8;
if(xmm&&cpu<9)cpu=9;
}
void pinsrw()
{
int num1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
int xmm=FALSE;
nexttok();
if(tok==tk_xmmreg)xmm=TRUE;
else if(tok!=tk_mmxreg)mmxregexpected(1);
num1=itok.number;
nextexpecting2(tk_camma);
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(3);
switch(htok){
case tk_reg32:
if(xmm)op(0x66);
outword(0xC40F);
op(rm_mod11+num1+hstok.number*8);
break;
case tk_wordvar:
case tk_intvar:
CheckAllMassiv(hbuf,2,&hstr);
outseg(&hstok,xmm==FALSE?3:4);
if(xmm)op(0x66);
outword(0xC40F);
op(hstok.rm+num1*8);
outaddress(&hstok);
break;
default:
reg32orword(2);
break;
}
op(doconstdwordmath());
if(cpu<8)cpu=8;
if(xmm&&cpu<9)cpu=9;
}
void pshufw()
{
int num1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
int i=1;
nexttok();
if(tok!=tk_mmxreg)mmxregexpected(1);
num1=itok.number;
nextexpecting2(tk_camma);
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(3);
switch(htok){
case tk_mmxreg:
outword(0x700F);
op(rm_mod11+num1+hstok.number*8);
break;
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(hbuf,i,&hstr);
KillVar(hstok.name);
outseg(&hstok,3);
outword(0x700F);
op(hstok.rm+num1*8);
outaddress(&hstok);
break;
default:
mmxregordwordexpected(2);
break;
}
op(doconstdwordmath());
}
void xmminstr(int type,int sec,int op1,int op2)
{
int num1,i=1;
nexttok();
if(tok!=op1){
if(op1==tk_mmxreg)mmxregexpected(1);
else if(op1==tk_reg32)reg32expected(1);
else xmmregexpected(1);
}
if(tok==tk_reg32)ClearReg(itok.number);
num1=itok.number;
nextexpecting2(tk_camma);
switch ( tok ) {
case tk_reg32:
case tk_mmxreg:
case tk_xmmreg:
if(tok!=op2){
if(op2==tk_mmxreg)mmxregexpected(2);
else if(op2==tk_reg32)reg32expected(2);
else xmmregexpected(2);
}
if(sec)op(sec);
op(0x0F);
op(type);
op(rm_mod11+itok.number+num1*8);
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,sec==0?3:4);
if(sec)op(sec);
op(0x0F);
op(type);
op(itok.rm+num1*8);
outaddress(&itok);
break;
default:
if(op2==tk_mmxreg)mmxregordwordexpected(2);
else if(op2==tk_reg32)reg32orword(2);
else xmmregorvarexpected(2);
break;
}
}
void xmm3instr(int type,int sec) //xmm,xmm/mem,i8
{
int num1,i=1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
nexttok();
if(tok!=tk_xmmreg)xmmregexpected(1);
num1=itok.number;
nextexpecting2(tk_camma);
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(3);
switch(htok){
case tk_xmmreg:
if(sec)op(sec);
op(0x0F);
op(type);
op(rm_mod11+hstok.number+num1*8);
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(hbuf,i,&hstr);
outseg(&hstok,sec==0?3:4);
if(sec)op(sec);
op(0x0F);
op(type);
op(hstok.rm+num1*8);
outaddress(&hstok);
break;
default:
xmmregorvarexpected(2);
break;
}
op(doconstdwordmath());
}
void xmm2xmm(int code,int code2,int type)
{
int num;
nexttok();
if(tok!=type){
if(type==tk_mmxreg)mmxregexpected(1);
else if(type==tk_reg32)reg32expected(1);
else xmmregexpected(1);
}
if(tok==tk_reg32)ClearReg(itok.number);
num=itok.number;
nextexpecting2(tk_camma);
if(tok!=tk_xmmreg)xmmregexpected(2);
if(code2)op(code2);
op(0x0F);
op(code);
op(rm_mod11+itok.number+num*8);
}
void movxmm3(int code,int code2,int type)
{
int i=1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
nexttok();
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
if(tok!=type){
if(type==tk_mmxreg)mmxregexpected(2);
else if(type==tk_xmmreg)xmmregexpected(2);
else reg32expected(2);
}
switch(htok){
case tk_qwordvar:
i+=4;
case tk_longvar:
case tk_dwordvar:
case tk_floatvar:
i+=2;
case tk_wordvar:
case tk_intvar:
i+=1;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(hbuf,i,&hstr);
KillVar(hstok.name);
outseg(&hstok,code2==0?3:4);
if(code2)op(code2);
op(0x0F);
op(code);
op(hstok.rm+itok.number*8);
outaddress(&hstok);
break;
default: varexpected(1);
}
}
void movxmm4(int code,int code2)
{
int i=1;
int num;
nexttok();
num=itok.number;
if(tok!=tk_xmmreg)xmmregexpected(1);
nextexpecting2(tk_camma);
switch(tok){
case tk_qwordvar:
i+=4;
case tk_longvar:
case tk_dwordvar:
case tk_floatvar:
i+=2;
case tk_wordvar:
case tk_intvar:
i+=1;
case tk_charvar:
case tk_bytevar:
CheckAllMassiv(bufrm,i,&strinf);
outseg(&itok,(code2==0?3:4));
if(code2)op(code2);
op(0x0F);
op(code);
op(itok.rm+num*8);
outaddress(&itok);
break;
default: varexpected(2);
}
}
void movxmm(int code,int code2,int addc)
{
int i=1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
nexttok();
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
switch(htok){
case tk_xmmreg:
switch(tok){
case tk_xmmreg:
if(code2)op(code2);
op(0x0F);
op(code);
op(rm_mod11+itok.number+hstok.number*8);
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,(code2==0?3:4));
if(code2)op(code2);
op(0x0F);
op(code);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default:
xmmregorvarexpected(2);
break;
}
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:
if(tok!=tk_xmmreg)xmmregexpected(2);
CheckAllMassiv(hbuf,i,&hstr);
KillVar(hstok.name);
outseg(&hstok,code2==0?3:4);
if(code2)op(code2);
op(0x0F);
op(code+addc);
op(hstok.rm+itok.number*8);
outaddress(&hstok);
break;
default:
xmmregorvarexpected(1);
break;
}
}
void movxmm2(int code,int code2)
{
int i=1,htok;
ITOK hstok;
char *hbuf;
SINFO hstr;
nexttok();
htok=tok;
hstok=itok;
hbuf=bufrm;
bufrm=NULL;
hstr=strinf;
strinf.bufstr=NULL;
nextexpecting2(tk_camma);
switch(htok){
case tk_xmmreg:
switch(tok){
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,(code2==0?3:4));
if(code2)op(code2);
op(0x0F);
op(code);
op(itok.rm+hstok.number*8);
outaddress(&itok);
break;
default:
datatype_expected(2);
break;
}
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:
if(tok!=tk_xmmreg)xmmregexpected(2);
CheckAllMassiv(hbuf,i,&hstr);
KillVar(hstok.name);
outseg(&hstok,code2==0?3:4);
if(code2)op(code2);
op(0x0F);
op(code+1);
op(hstok.rm+itok.number*8);
outaddress(&hstok);
break;
default:
xmmregorvarexpected(1);
break;
}
}
void shiftxmm(int rm) //rxmm,i8
{
int num;
nexttok();
if(tok!=tk_xmmreg)xmmregexpected(1);
num=itok.number;
nextexpecting2(tk_camma);
if(tok!=tk_number)numexpected(2);
op(0x66);
op(0x0F);
op(0x73);
op(rm*8+num+rm_mod11);
op(doconstdwordmath());
}
void DDDW(int faradd)
{
int htok,i;
char name[IDLENGTH];
unsigned long hnumber;
if(dbg&2)AddDataNullLine(faradd==0?2:4);
dbgact++;
asmparam=FALSE;
do{
i=1;
nexttok();
CheckIP();
htok=tok;
switch(tok){
case tk_undefofs:
tok=tk_number;
strcpy(name,itok.name);
case tk_number:
hnumber=doconstdwordmath();
if(tok==tk_id&&strcmp((char *)string,"dup")==0){
i=hnumber;
nexttok();
CheckMinusNum();
htok=tok;
if(tok==tk_undefofs){
tok=tk_number;
strcpy(name,itok.name);
}
if(tok==tk_number)hnumber=doconstdwordmath();
else numexpected();
}
for(;i!=0;i--){
if(postnumflag&f_reloc)AddReloc();
if(htok==tk_undefofs)AddUndefOff(2,name);
if(faradd)outdword(hnumber);
else outword(hnumber);
}
break;
case tk_postnumber:
setwordpost(&itok);
if(faradd)outdword(itok.number);
else outword(itok.number);
nexttok();
break;
default:
numexpected();
nexttok();
break;
}
}while(tok==tk_camma);
dbgact--;
}
void AADM(int code)
{
op(code);
itok.number=10;
if(tok2==tk_number)nexttok();
op(itok.number); //AAD
ClearReg(AX);
}
int Push(ITOK *wtok)
{
int i;
int razr;
ITOK hstok;
unsigned long hnumber;
int possiblecpu=0;
int next=1;
i=(am32+1)*2;
razr=r16;
switch(tok){
case tk_id:
case tk_ID:
if((stricmp("dword",(char *)string)==0)||(stricmp("long",(char *)string)==0))i=r32;
else if((stricmp("word",(char *)string)==0)||(stricmp("int",(char *)string)==0))i=r16;
else return FALSE;
goto swpushpar;
case tk_dword:
case tk_long:
i=r32;
goto swpushpar;
case tk_int:
case tk_word:
i=r16;
swpushpar:
nexttok();
CheckMinusNum();
if(tok==tk_number)goto pushnum;
if(tok==tk_undefofs)goto pushundef;
return FALSE;
case tk_reg32:
possiblecpu=3;
case tk_reg:
op66(tok==tk_reg?r16:r32);
op(0x50+(unsigned int)itok.number);
break;
case tk_seg:
PushSeg((unsigned int)itok.number);
break;
case tk_undefofs:
pushundef:
hstok=itok;
tok=tk_number;
hnumber=doconstlongmath();
op66(i); ////
op(0x68);
if(postnumflag&f_reloc)AddReloc();
AddUndefOff(2,hstok.name);
if(i==r16)outword(hnumber);
else outdword(hnumber);
possiblecpu=(unsigned char)(i==r16?2:3);
next=0;
break;
case tk_minus:
if(tok2!=tk_number)return FALSE;
case tk_number:
pushnum:
hnumber=doconstlongmath();
if(i==r16)hnumber&=0xffff;
else hnumber&=0xffffffff;
if(wtok&&(postnumflag&f_reloc)==0)Const2Var(wtok,hnumber,i==r16?tk_word:tk_dword);
op66(i);
if((postnumflag&f_reloc)==0&&short_ok(hnumber,i/2-1)){
op(0x6A);
op(hnumber);
}
else{
op(0x68);
if((postnumflag&f_reloc)!=0)AddReloc();
if(i==r16)outword(hnumber);
else outdword(hnumber);
}
possiblecpu=(unsigned char)(i==r16?2:3);
next=0;
break;
case tk_dwordvar:
case tk_longvar:
CheckAllMassiv(bufrm,4,&strinf);
possiblecpu=3;
razr=r32;
goto push;
case tk_wordvar:
case tk_intvar:
CheckAllMassiv(bufrm,2,&strinf);
push:
op66(razr);
outseg(&itok,2);
op(0xFF); op(0x30+itok.rm);
outaddress(&itok);
break;
case tk_postnumber:
op(0x68);
(itok.flag&f_extern)==0?setwordpost(&itok):setwordext(&itok.number);
if(am32==FALSE)outword((unsigned int)itok.number);
else outdword(itok.number);
break;
case tk_string:
op66(i);
op(0x68);
if(am32==FALSE)outword(addpoststring());
else outdword(addpoststring());
break;
default:
return FALSE;
}
if(cpu<possiblecpu)cpu=possiblecpu;
asmparam=FALSE;
if(next)nexttok();
return i;
}
/* end of TOKR.C */