mirror of https://github.com/minexew/Shrine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
771 lines
21 KiB
771 lines
21 KiB
U0 ICAndBranch(CIntermediateCode *tmpi,I64 rip,I64 is,U8 *buf,I64 rip2) |
|
{ |
|
U64 i; |
|
I64 it,t1,r1,d1,r2; |
|
Bool short_jmp,swap,override; |
|
CCodeMisc *lb; |
|
CICArg *arg1,*arg2; |
|
|
|
if (tmpi->arg1.type&MDF_IMM) { |
|
swap=TRUE; |
|
arg1=&tmpi->arg2; |
|
arg2=&tmpi->arg1; |
|
} else { |
|
swap=FALSE; |
|
arg1=&tmpi->arg1; |
|
arg2=&tmpi->arg2; |
|
} |
|
|
|
if (arg2->type&MDF_IMM && arg2->disp>U32_MAX) |
|
override=TRUE; |
|
else |
|
override=FALSE; |
|
|
|
if (arg1->type.raw_type<arg2->type.raw_type) |
|
it=arg1->type.raw_type; |
|
else |
|
it=arg2->type.raw_type; |
|
|
|
i=arg2->disp; |
|
if (arg2->type&MDF_IMM && i<=U32_MAX) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
if (i<=U8_MAX) |
|
ICU16(tmpi,i<<8+0xA8); |
|
else if (i<=U16_MAX) |
|
ICU32(tmpi,i<<16+0xA900+OC_OP_SIZE_PREFIX); |
|
else { |
|
ICU8(tmpi,0xA9); |
|
ICU32(tmpi,i); |
|
} |
|
} else { |
|
t1=MDF_REG+it; |
|
d1=0; |
|
if (swap && !override) { |
|
if (arg1->type&MDF_REG) { |
|
r1=arg1->reg; |
|
swap=TRUE; |
|
} else { |
|
r1=REG_RCX; |
|
swap=FALSE; |
|
} |
|
if (arg2->type&MDF_REG) { |
|
r2=arg2->reg; |
|
swap=FALSE; |
|
} else |
|
r2=REG_RDX; |
|
if (swap) { |
|
if (!(arg1->type&MDF_REG) || r1!=arg1->reg) |
|
ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
if (arg2->type&MDG_REG_DISP_SIB_RIP) { |
|
t1=arg2->type&MDG_MASK+it; |
|
r2=arg2->reg; |
|
d1=arg2->disp; |
|
} else |
|
ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
i=ICModr1(r1,t1,r2,d1); |
|
} else { |
|
if (arg1->type&MDG_REG_DISP_SIB_RIP) { |
|
t1=arg1->type&MDG_MASK+it; |
|
r1=arg1->reg; |
|
d1=arg1->disp; |
|
} else |
|
ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
if (!(arg2->type&MDF_REG) || r2!=arg2->reg) |
|
ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
i=ICModr1(r2,t1,r1,d1); |
|
} |
|
} else { |
|
if (arg2->type&MDF_REG) { |
|
r2=arg2->reg; |
|
swap=FALSE; |
|
} else { |
|
r2=REG_RDX; |
|
swap=TRUE; |
|
} |
|
if (arg1->type&MDF_REG) { |
|
r1=arg1->reg; |
|
swap=TRUE; |
|
} else |
|
r1=REG_RCX; |
|
if (override) |
|
swap=FALSE; |
|
if (swap) { |
|
if (arg2->type&MDG_REG_DISP_SIB_RIP) { |
|
t1=arg2->type&MDG_MASK+it; |
|
r2=arg2->reg; |
|
d1=arg2->disp; |
|
} else |
|
ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
if (!(arg1->type&MDF_REG) || r1!=arg1->reg) |
|
ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
i=ICModr1(r1,t1,r2,d1); |
|
} else { |
|
if (!(arg2->type&MDF_REG) || r2!=arg2->reg) |
|
ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
if (arg1->type&MDG_REG_DISP_SIB_RIP) { |
|
t1=arg1->type&MDG_MASK+it; |
|
r1=arg1->reg; |
|
d1=arg1->disp; |
|
} else |
|
ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
i=ICModr1(r2,t1,r1,d1); |
|
} |
|
} |
|
switch (it) { |
|
case RT_I8: |
|
case RT_U8: |
|
ICRex(tmpi,i.u8[1]); |
|
ICU16(tmpi,i.u8[2]<<8+0x84); |
|
break; |
|
case RT_U16: |
|
case RT_I16: |
|
ICOpSizeRex(tmpi,i.u8[1]); |
|
ICU16(tmpi,i.u8[2]<<8+0x85); |
|
break; |
|
default: |
|
ICRex(tmpi,i.u8[1]); |
|
ICU16(tmpi,i.u8[2]<<8+0x85); |
|
} |
|
ICModr2(tmpi,i,,d1,rip2); |
|
} |
|
|
|
rip+=tmpi->ic_cnt; |
|
lb=OptLabelFwd(tmpi->ic_data); |
|
short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP); |
|
if (!buf && lb->addr!=INVALID_PTR) { |
|
i=lb->addr-(rip+2); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
if (I8_MIN<=i<=I8_MAX) |
|
short_jmp=TRUE; |
|
} |
|
|
|
if (short_jmp) { |
|
tmpi->ic_flags|=ICF_SHORT_JMP; |
|
i=lb->addr-(rip+2); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
ICU16(tmpi,i<<8+is.u8[2]); |
|
} else { |
|
tmpi->ic_flags&=~ICF_SHORT_JMP; |
|
i=lb->addr-(rip+6); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
ICU16(tmpi,is.u16[0]); |
|
ICU32(tmpi,i); |
|
} |
|
} |
|
|
|
U0 ICAssign(CIntermediateCode *tmpi,I64 rip) |
|
{ |
|
CIntermediateCode *tmpi1; |
|
if (tmpi->ic_flags & ICF_BY_VAL) { |
|
ICMov(tmpi,tmpi->arg1.type&MDG_MASK+tmpi->arg1_type_pointed_to, |
|
tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
if (tmpi->res.type.mode) |
|
ICMov(tmpi,tmpi->res.type&MDG_MASK+tmpi->arg1_type_pointed_to, |
|
tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg1.type&MDG_MASK+tmpi->arg1_type_pointed_to, |
|
tmpi->arg1.reg,tmpi->arg1.disp,rip); |
|
} else { |
|
if (tmpi->arg1.type&MDF_REG) { |
|
if (!(tmpi1=OptLag1(tmpi)) || tmpi1->ic_code!=IC_ADD_CONST || |
|
tmpi1->res.type!=MDF_REG+RT_I64 || tmpi1->res.reg!=tmpi->arg1.reg || |
|
tmpi1->arg1.type!=MDF_REG+RT_I64 || |
|
tmpi1->arg1.reg!=tmpi->arg1.reg || |
|
(tmpi->arg2.type&MDF_REG || tmpi->arg2.type&MDF_DISP) && |
|
tmpi->arg2.reg==tmpi->arg1.reg || |
|
tmpi->res.type.mode || tmpi1->ic_flags&~ICG_NO_CVT_MASK) { |
|
ICMov(tmpi, |
|
MDF_DISP+tmpi->arg1_type_pointed_to, |
|
tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
if (tmpi->res.type.mode) |
|
ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
} else { |
|
tmpi->ic_flags=(tmpi->ic_flags|tmpi1->ic_flags)& |
|
~ICF_CODE_FINAL|ICF_DONT_RESTORE; |
|
tmpi->arg1.disp=tmpi1->ic_data; |
|
OptSetNOP1(tmpi1); //This better not be last pass! |
|
ICMov(tmpi,MDF_DISP+tmpi->arg1_type_pointed_to, |
|
tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
} |
|
} else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip); |
|
ICMov(tmpi,MDF_DISP+tmpi->arg1_type_pointed_to,REG_RCX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
if (tmpi->res.type.mode) |
|
ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip); |
|
} |
|
} |
|
} |
|
|
|
U0 ICBrBitOps(CIntermediateCode *tmpi,I64 rip, |
|
I64 op,I64 op_imm,I64 is,U8 *buf,I64 rip2) |
|
{ |
|
I64 i,t,r1,r2,d1,d2,t1,t2; |
|
CICArg *arg1=&tmpi->arg1,*arg2=&tmpi->arg2; |
|
Bool short_jmp; |
|
CCodeMisc *lb; |
|
|
|
if (tmpi->ic_flags & ICF_BY_VAL) { |
|
if (tmpi->ic_flags&ICF_SWAP && !(arg2->type&MDF_REG) && |
|
(!(arg2->type&MDF_IMM) ||arg2->disp>63)|| |
|
!(tmpi->ic_flags&ICF_SWAP) && arg2->type&MDF_IMM && |
|
arg2->disp<64 || arg2->type&MDF_STK) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
t2=MDF_REG+RT_I64; |
|
r2=REG_RCX; |
|
d2=0; |
|
} else { |
|
t2=arg2->type; |
|
if (t2&MDF_IMM && arg2->disp<64) |
|
r2=0; |
|
else |
|
r2=arg2->reg; |
|
d2=arg2->disp; |
|
} |
|
if (!(tmpi->ic_flags&ICF_SWAP) && !(arg1->type&MDF_REG) && |
|
(!(arg1->type&MDF_IMM) || arg1->disp>63) || |
|
tmpi->ic_flags&ICF_SWAP && arg1->type&MDF_IMM && |
|
arg1->disp<64 || arg1->type&MDF_STK) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
t1=MDF_REG+RT_I64; |
|
r1=REG_RDX; |
|
d1=0; |
|
} else { |
|
t1=arg1->type; |
|
if (t1&MDF_IMM && arg1->disp<64) |
|
r1=0; |
|
else |
|
r1=arg1->reg; |
|
d1=arg1->disp; |
|
} |
|
} else { |
|
t1=MDF_DISP+RT_I64; |
|
t2=MDF_DISP+RT_I64; |
|
d1=0; |
|
d2=0; |
|
if (arg2->type&MDF_REG) |
|
r2=arg2->reg; |
|
else if (!(tmpi->ic_flags&ICF_SWAP) || !(arg2->type&MDF_IMM) || |
|
arg2->disp>63) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,arg2->type,arg2->reg,arg2->disp,rip2); |
|
r2=REG_RCX; |
|
} else |
|
r2=0; |
|
if (arg1->type&MDF_REG) |
|
r1=arg1->reg; |
|
else if (tmpi->ic_flags&ICF_SWAP || |
|
!(arg1->type&MDF_IMM) || arg1->disp>63) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,arg1->type,arg1->reg,arg1->disp,rip2); |
|
r1=REG_RDX; |
|
} else |
|
r1=0; |
|
} |
|
if (tmpi->ic_flags&ICF_LOCK && op!=0xA30F) |
|
ICU8(tmpi,OC_LOCK_PREFIX); |
|
if (tmpi->ic_flags&ICF_SWAP) { |
|
if (arg2->type&MDF_IMM && arg2->disp<32) { |
|
if (op==0xA30F && arg2->disp<8) { |
|
t=t1&MDG_MASK+RT_U8; |
|
op_imm=0xF6; //TEST |
|
} else |
|
t=t1&MDG_MASK+RT_U32; |
|
} else |
|
t=t1; |
|
i=ICModr1(r2,t,r1,d1); |
|
SwapI64(&arg1,&arg2); |
|
} else { |
|
if (arg1->type&MDF_IMM && arg1->disp<32) { |
|
if (op==0xA30F && arg1->disp<8) { |
|
t=t2&MDG_MASK+RT_U8; |
|
op_imm=0xF6; //TEST |
|
} else |
|
t=t2&MDG_MASK+RT_U32; |
|
} else |
|
t=t2; |
|
i=ICModr1(r1,t,r2,d2); |
|
} |
|
ICRex(tmpi,i.u8[1]); |
|
if (op_imm==0xF6) {//TEST |
|
ICU16(tmpi,i.u8[2]<<8+op_imm); |
|
ICModr2(tmpi,i,,arg2->disp,rip2+1); |
|
ICU8(tmpi,1<<arg1->disp); |
|
if (is==0x72820F) |
|
is=0x75850F; |
|
else |
|
is=0x74840F; |
|
} else if (arg1->type&MDF_IMM && arg1->disp<64) { |
|
ICU24(tmpi,i.u8[2]<<16+op_imm); |
|
ICModr2(tmpi,i,,arg2->disp,rip2+1); |
|
ICU8(tmpi,arg1->disp); |
|
} else { |
|
ICU24(tmpi,i.u8[2]<<16+op); |
|
ICModr2(tmpi,i,,arg2->disp,rip2); |
|
} |
|
|
|
rip+=tmpi->ic_cnt; |
|
lb=OptLabelFwd(tmpi->ic_data); |
|
short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP); |
|
if (!buf && lb->addr!=INVALID_PTR) { |
|
i=lb->addr-(rip+2); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
if (I8_MIN<=i<=I8_MAX) |
|
short_jmp=TRUE; |
|
} |
|
|
|
if (short_jmp) { |
|
tmpi->ic_flags|=ICF_SHORT_JMP; |
|
i=lb->addr-(rip+2); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
ICU16(tmpi,i<<8+is.u8[2]); |
|
} else { |
|
tmpi->ic_flags&=~ICF_SHORT_JMP; |
|
i=lb->addr-(rip+6); |
|
if (lb->flags&CMF_POP_CMP) |
|
i+=8; |
|
ICU16(tmpi,is.u16[0]); |
|
ICU32(tmpi,i); |
|
} |
|
} |
|
|
|
U0 ICQueInit(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 r1; |
|
if (tmpi->arg1.type==MDF_REG+RT_I64) |
|
r1=tmpi->arg1.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
r1=REG_RAX; |
|
} |
|
ICMov(tmpi,MDF_DISP+RT_I64,r1,0,MDF_REG+RT_I64,r1,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r1,sizeof(U8 *),MDF_REG+RT_I64,r1,0,rip2); |
|
} |
|
|
|
U0 ICQueIns(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 r1,r2; |
|
if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RDX) |
|
r2=tmpi->arg2.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
r2=REG_RAX; |
|
} |
|
if (tmpi->arg1.type==MDF_REG+RT_I64) |
|
r1=tmpi->arg1.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
r1=REG_RDX; |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r1,0,MDF_REG+RT_I64,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r2,0,MDF_REG+RT_I64,REG_RBX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r2,sizeof(U8 *),MDF_REG+RT_I64,r1,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,REG_RBX,sizeof(U8 *),MDF_REG+RT_I64,r2,0,rip2); |
|
} |
|
|
|
U0 ICQueInsRev(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 r1,r2; |
|
if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RDX) |
|
r2=tmpi->arg2.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
r2=REG_RAX; |
|
} |
|
if (tmpi->arg1.type==MDF_REG+RT_I64) |
|
r1=tmpi->arg1.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
r1=REG_RDX; |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,sizeof(U8 *),rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,REG_RBX,0,MDF_REG+RT_I64,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r2,0,MDF_REG+RT_I64,r1,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r2,sizeof(U8 *),MDF_REG+RT_I64,REG_RBX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,r1,sizeof(U8 *),MDF_REG+RT_I64,r2,0,rip2); |
|
} |
|
|
|
U0 ICQueRem(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 r1; |
|
if (tmpi->arg1.type==MDF_REG+RT_I64) |
|
r1=tmpi->arg1.reg; |
|
else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
r1=REG_RAX; |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_I64,r1,sizeof(U8 *),rip2); |
|
ICU24(tmpi,0x1A8948); |
|
ICU32(tmpi,sizeof(U8 *)<<24+0x538948); |
|
} |
|
|
|
U0 ICMinMax(CIntermediateCode *tmpi,I64 op,I64 rip2) |
|
{ |
|
I64 r1,i1=0x48; |
|
if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RAX) { |
|
r1=tmpi->arg2.reg; |
|
if (r1>7) { |
|
i1++; |
|
r1&=7; |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
} else { |
|
if (tmpi->arg1.reg==REG_RAX && tmpi->arg1.type&MDG_REG_DISP_SIB) { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
r1=REG_RDX; |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
} else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
if (tmpi->arg1.type==MDF_REG+RT_I64) { |
|
r1=tmpi->arg1.reg; |
|
if (r1>7) { |
|
i1++; |
|
r1&=7; |
|
} |
|
} else { |
|
r1=REG_RDX; |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
} |
|
} |
|
} |
|
ICU24(tmpi,0xC03B00+r1<<16+i1); |
|
ICU32(tmpi,0xC0000F00+op<<16+r1<<24+i1); |
|
} |
|
|
|
U0 ICSqr(CIntermediateCode *tmpi,I64 op,I64 rip2) |
|
{ |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
ICSlashOp(tmpi,MDF_REG+RT_I64,REG_RAX,0,op,rip2); |
|
} |
|
|
|
U0 ICModU64(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
CICType t1; |
|
I64 r1,d1; |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
if (tmpi->arg1.reg!=REG_RAX && tmpi->arg1.reg!=REG_RDX && |
|
tmpi->arg1.type&MDG_REG_DISP_SIB && |
|
tmpi->arg1.type.raw_type>=RT_I64) { |
|
t1=tmpi->arg1.type; |
|
r1=tmpi->arg1.reg; |
|
d1=tmpi->arg1.disp; |
|
} else { |
|
t1=MDF_REG+RT_I64; |
|
r1=REG_RBX; |
|
d1=0; |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,MDF_DISP+RT_I64,REG_RCX,0,rip2); |
|
ICZero(tmpi,REG_RDX); |
|
ICSlashOp(tmpi,t1,r1,d1,SLASH_OP_DIV,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_I64,REG_RCX,0,MDF_REG+RT_I64,REG_RAX,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0, |
|
MDF_REG+RT_I64,REG_RDX,0,rip2); |
|
} |
|
|
|
U0 ICSwap(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 r1,r2; |
|
if (tmpi->arg1.type&MDF_REG) |
|
r1=tmpi->arg1.reg; |
|
else |
|
r1=REG_RAX; |
|
if (tmpi->arg2.type&MDF_REG) |
|
r2=tmpi->arg2.reg; |
|
else |
|
r2=REG_RAX; |
|
if (r1==r2) { |
|
if (r1==REG_RAX) |
|
r1=REG_RBX; |
|
else |
|
r2=REG_RAX; |
|
} |
|
ICMov(tmpi,MDF_REG+RT_I64,r2,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,r1,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
switch (tmpi->ic_code) { |
|
case IC_SWAP_U8: |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U8,r1,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U8,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U8,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U8,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2); |
|
break; |
|
case IC_SWAP_U16: |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U16,r1,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U16,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U16,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U16,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2); |
|
break; |
|
case IC_SWAP_U32: |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U32,r1,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U32,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U32,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U32,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2); |
|
break; |
|
case IC_SWAP_I64: |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U64,r1,0,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U64,r2,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U64,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2); |
|
ICMov(tmpi,MDF_DISP+RT_U64,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2); |
|
break; |
|
} |
|
} |
|
|
|
U0 ICAndEqu(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 i,bit; |
|
if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STK) && |
|
tmpi->ic_flags&ICF_RES_NOT_USED) { |
|
i=~tmpi->arg2.disp; |
|
bit=Bsf(i); |
|
if (0<=bit==Bsr(i)) { |
|
tmpi->arg2.disp=bit; |
|
tmpi->arg2.reg=0; |
|
tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64; |
|
ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xB30F,0x30BA0F,rip2); |
|
return; |
|
} |
|
} |
|
ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to, |
|
tmpi->res.type,tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x210425240423,rip2); |
|
} |
|
|
|
U0 ICOrEqu(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 i,bit; |
|
if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STK) && |
|
tmpi->ic_flags&ICF_RES_NOT_USED) { |
|
i=tmpi->arg2.disp; |
|
bit=Bsf(i); |
|
if (0<=bit==Bsr(i) && i>I8_MAX) { |
|
tmpi->arg2.disp=bit; |
|
tmpi->arg2.reg=0; |
|
tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64; |
|
ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xAB0F,0x28BA0F,rip2); |
|
return; |
|
} |
|
} |
|
ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to, |
|
tmpi->res.type,tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x09010D0C010B,rip2); |
|
} |
|
|
|
U0 ICXorEqu(CIntermediateCode *tmpi,I64 rip2) |
|
{ |
|
I64 i,bit; |
|
if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STK) && |
|
tmpi->ic_flags&ICF_RES_NOT_USED) { |
|
i=tmpi->arg2.disp; |
|
bit=Bsf(i); |
|
if (0<=bit==Bsr(i)) { |
|
tmpi->arg2.disp=bit; |
|
tmpi->arg2.reg=0; |
|
tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64; |
|
ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xBB0F,0x38BA0F,rip2); |
|
return; |
|
} |
|
} |
|
ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to, |
|
tmpi->res.type,tmpi->res.reg,tmpi->res.disp, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x310635340633,rip2); |
|
} |
|
|
|
U0 ICSwitch(CIntermediateCode *tmpi,I64 rip, |
|
Bool nobound,CCmpCtrl *cc,U8 *buf,I64 rip2) |
|
{ |
|
I64 i,j,cnt,min,max,begin,r; |
|
CCodeMisc *lb; |
|
Bool short_jmp; |
|
CAOTAbsAddr *tmpa; |
|
if (!(tmpi->arg1.type&MDF_REG) || tmpi->arg1.reg&7==REG_RSP) |
|
r=REG_RDX; |
|
else |
|
r=tmpi->arg1.reg; |
|
if (nobound) |
|
ICMov(tmpi,MDF_REG+RT_I64,r,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
else { |
|
if (tmpi->arg2.type&MDF_IMM) { |
|
j=tmpi->arg2.disp; |
|
ICMov(tmpi,MDF_REG+RT_I64,r,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
if (I8_MIN<=j<=I8_MAX) { |
|
i=0xF88348+(r&7)<<16; |
|
if (r>7) i++; |
|
ICU24(tmpi,i); |
|
ICU8(tmpi,j); |
|
} else if (I32_MIN<=j<=I32_MAX) { |
|
i=0xF88148+(r&7)<<16; |
|
if (r>7) i++; |
|
ICU24(tmpi,i); |
|
ICU32(tmpi,j); |
|
} else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
i=0xC13B48+(r&7)<<19; |
|
if (r>7) i+=4; |
|
ICU24(tmpi,i); |
|
} |
|
} else { |
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0, |
|
tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2); |
|
ICMov(tmpi,MDF_REG+RT_I64,r,0, |
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2); |
|
i=0xC13B48+(r&7)<<19; |
|
if (r>7) i+=4; |
|
ICU24(tmpi,i); |
|
} |
|
|
|
rip+=tmpi->ic_cnt; |
|
lb=tmpi->ic_data(CCodeMisc *)->dft; |
|
short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP); |
|
if (!buf && lb->addr!=INVALID_PTR) { |
|
i=lb->addr-(rip+2); |
|
if (I8_MIN<=i<=I8_MAX) |
|
short_jmp=TRUE; |
|
} |
|
if (short_jmp) { |
|
tmpi->ic_flags|=ICF_SHORT_JMP; |
|
ICU16(tmpi,(lb->addr-(rip+2))<<8+0x73); |
|
} else { |
|
tmpi->ic_flags&=~ICF_SHORT_JMP; |
|
ICU16(tmpi,0x830F); |
|
ICU32(tmpi,lb->addr-(rip+6)); |
|
} |
|
} |
|
|
|
lb=tmpi->ic_data; |
|
begin=lb->begin->addr; |
|
if (!buf && begin!=INVALID_PTR) { |
|
min=I64_MAX; |
|
max=I64_MIN; |
|
for (i=0;i<lb->range;i++) { |
|
if (lb->jmp_table[i]->addr==INVALID_PTR) { |
|
min=I64_MIN; |
|
max=I64_MAX; |
|
break; |
|
} else { |
|
j=lb->jmp_table[i]->addr-begin; |
|
min=MinI64(min,j); |
|
max=MaxI64(max,j); |
|
} |
|
} |
|
if (I8_MIN<=min<=max<=I8_MAX) |
|
lb->flags|=CMF_I8_JMP_TABLE; |
|
else if (U8_MIN<=min<=max<=U8_MAX) |
|
lb->flags|=CMF_U8_JMP_TABLE; |
|
else if (I16_MIN<=min<=max<=I16_MAX) |
|
lb->flags|=CMF_I16_JMP_TABLE; |
|
else if (U16_MIN<=min<=max<=U16_MAX) |
|
lb->flags|=CMF_U16_JMP_TABLE; |
|
} |
|
|
|
if (lb->flags&CMF_I8_JMP_TABLE) { |
|
if (r<8) |
|
ICU8(tmpi,0x48); |
|
else |
|
ICU8(tmpi,0x49); |
|
ICU24(tmpi,0x98BE0F+(r&7)<<16); |
|
cnt=1; |
|
} else if (lb->flags&CMF_U8_JMP_TABLE) { |
|
if (r<8) |
|
cnt=2; |
|
else { |
|
ICU8(tmpi,0x49); |
|
cnt=1; |
|
} |
|
ICU24(tmpi,0x98B60F+(r&7)<<16); |
|
} else if (lb->flags&CMF_I16_JMP_TABLE) { |
|
if (r<8) |
|
ICU8(tmpi,0x48); |
|
else |
|
ICU8(tmpi,0x4A); |
|
ICU32(tmpi,0x451CBF0F+(r&7)<<27); |
|
cnt=0; |
|
} else if (lb->flags&CMF_U16_JMP_TABLE) { |
|
if (r<8) |
|
cnt=1; |
|
else { |
|
ICU8(tmpi,0x4A); |
|
cnt=0; |
|
} |
|
ICU32(tmpi,0x451CB70F+(r&7)<<27); |
|
} else { |
|
if (r<8) |
|
cnt=2; |
|
else { |
|
ICU8(tmpi,0x42); |
|
cnt=1; |
|
} |
|
ICU24(tmpi,0x851C8B+(r&7)<<19); |
|
} |
|
if (buf && cc->flags&CCF_AOT_COMPILE) { |
|
tmpa=CAlloc(sizeof(CAOTAbsAddr)); |
|
tmpa->next=cc->aotc->abss; |
|
tmpa->type=AAT_ADD_U32; |
|
cc->aotc->abss=tmpa; |
|
tmpa->rip=rip2+tmpi->ic_cnt; |
|
ICU32(tmpi,lb->addr+cc->aotc->rip); |
|
} else |
|
ICU32(tmpi,lb->addr+buf); |
|
|
|
if (lb->flags&(CMF_I8_JMP_TABLE|CMF_U8_JMP_TABLE| |
|
CMF_I16_JMP_TABLE|CMF_U16_JMP_TABLE)) { |
|
ICU16(tmpi,0xC381); //ADD EBX,0x12345678 |
|
if (buf && cc->flags&CCF_AOT_COMPILE) { |
|
tmpa=CAlloc(sizeof(CAOTAbsAddr)); |
|
tmpa->next=cc->aotc->abss; |
|
tmpa->type=AAT_ADD_U32; |
|
cc->aotc->abss=tmpa; |
|
tmpa->rip=rip2+tmpi->ic_cnt; |
|
ICU32(tmpi,begin+cc->aotc->rip); |
|
} else |
|
ICU32(tmpi,begin+buf); |
|
} else |
|
cnt+=6; |
|
ICU16(tmpi,0xE3FF); //JMP EBX |
|
for (i=0;i<cnt;i++) //Code must always shrink, not expand |
|
ICU8(tmpi,OC_NOP); |
|
tmpi->ic_flags&=~ICF_CODE_FINAL; |
|
} |
|
|
|
U0 ICLocalVarInit(CIntermediateCode *tmpi) |
|
{ |
|
ICU24(tmpi,0xC48B48); |
|
ICU16(tmpi,0x5748); |
|
ICU24(tmpi,0xF88B48); |
|
ICU24(tmpi,0xC1C748); |
|
ICU32(tmpi,tmpi->ic_data); |
|
ICU16(tmpi,sys_var_init_val<<8+0xB0); |
|
ICU24(tmpi,0xAA48F3); |
|
ICU16(tmpi,0x5F48); |
|
}
|
|
|