2020-02-15 20:01:48 +00:00
|
|
|
|
/*Intermediate Code to Machine Code
|
|
|
|
|
|
|
|
|
|
RAX,RBX,RCX and RDX can be clobbered by
|
|
|
|
|
each intermediate code's output code.
|
|
|
|
|
However, intermediate codes must be
|
|
|
|
|
coupled together based on the arg and
|
|
|
|
|
res type specifications in the
|
2020-03-01 01:59:50 +00:00
|
|
|
|
$LK,"CICArg",A="MN:CICArg"$. RAX is the most common reg
|
2020-02-15 20:01:48 +00:00
|
|
|
|
for coupling intermediate codes.
|
|
|
|
|
|
|
|
|
|
Internal calculations take place on
|
|
|
|
|
64-bit vals, so anything which has
|
|
|
|
|
found it's way into a reg has been
|
|
|
|
|
sign or zero extended to 64-bits.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
U0 ICU8(CIntermediateCode *tmpi,U8 b)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
tmpi->ic_body[tmpi->ic_count++]=b;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICRex(CIntermediateCode *tmpi,U8 b)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
if (b)
|
|
|
|
|
tmpi->ic_body[tmpi->ic_count++]=b;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICOpSizeRex(CIntermediateCode *tmpi,U8 b)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
tmpi->ic_body[tmpi->ic_count++]=OC_OP_SIZE_PREFIX;
|
|
|
|
|
if (b)
|
|
|
|
|
tmpi->ic_body[tmpi->ic_count++]=b;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICU16(CIntermediateCode *tmpi,U16 w)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
*(&tmpi->ic_body[tmpi->ic_count])(U16)=w;
|
|
|
|
|
tmpi->ic_count+=2;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICU24(CIntermediateCode *tmpi,U32 d)
|
|
|
|
|
{//Writes extra harmless overhanging byte.
|
2020-02-20 23:40:10 +00:00
|
|
|
|
*(&tmpi->ic_body[tmpi->ic_count])(U32)=d;
|
|
|
|
|
tmpi->ic_count+=3;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICU32(CIntermediateCode *tmpi,U32 d)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
*(&tmpi->ic_body[tmpi->ic_count])(U32)=d;
|
|
|
|
|
tmpi->ic_count+=4;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICU64(CIntermediateCode *tmpi,U64 q)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
*(&tmpi->ic_body[tmpi->ic_count])(U64)=q;
|
|
|
|
|
tmpi->ic_count+=8;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICAddRSP(CIntermediateCode *tmpi,I64 i,Bool optimize=TRUE)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 j,last_start;
|
|
|
|
|
CIntermediateCode *tmpil1;
|
|
|
|
|
if (optimize) {
|
|
|
|
|
tmpil1=tmpi;
|
|
|
|
|
if (tmpi->ic_last_start<0 && !tmpi->ic_count &&
|
|
|
|
|
(tmpil1=OptLag1(tmpi)) && tmpil1->ic_last_start<0)
|
|
|
|
|
tmpil1=NULL;
|
|
|
|
|
if (tmpil1) {
|
|
|
|
|
j=tmpil1->ic_count;
|
|
|
|
|
if (tmpil1->ic_last_start==j-4 && tmpil1->ic_body[j-3]==0x83 &&
|
|
|
|
|
tmpil1->ic_body[j-4]==0x48) {
|
|
|
|
|
if (tmpil1->ic_body[j-2]==0xEC)
|
|
|
|
|
j=-tmpil1->ic_body[j-1](I8);
|
|
|
|
|
else if (tmpil1->ic_body[j-2]==0xC4)
|
|
|
|
|
j=tmpil1->ic_body[j-1](I8);
|
|
|
|
|
else
|
|
|
|
|
j=0;
|
|
|
|
|
} else if (tmpil1->ic_last_start==j-7 && tmpil1->ic_body[j-6]==0x81 &&
|
|
|
|
|
tmpil1->ic_body[j-7]==0x48) {
|
|
|
|
|
if (tmpil1->ic_body[j-5]==0xEC)
|
|
|
|
|
j=-tmpil1->ic_body[j-4](I32);
|
|
|
|
|
else if (tmpil1->ic_body[j-5]==0xC4)
|
|
|
|
|
j=tmpil1->ic_body[j-4](I32);
|
|
|
|
|
else
|
|
|
|
|
j=0;
|
|
|
|
|
} else
|
|
|
|
|
j=0;
|
|
|
|
|
if (j) {
|
|
|
|
|
if (tmpi==tmpil1) {
|
|
|
|
|
tmpi->ic_count=tmpi->ic_last_start;
|
|
|
|
|
i+=j;
|
|
|
|
|
} else if (!(tmpi->ic_flags&ICF_PREV_DELETED)) {
|
|
|
|
|
tmpil1->ic_flags|=ICF_DEL_PREV_INS;
|
|
|
|
|
tmpi->ic_flags=tmpi->ic_flags&~ICF_CODE_FINAL|ICF_PREV_DELETED;
|
|
|
|
|
i+=j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
2020-02-20 23:40:10 +00:00
|
|
|
|
last_start=tmpi->ic_count;
|
|
|
|
|
if (i>0) {
|
|
|
|
|
if (i<=I8_MAX)
|
|
|
|
|
ICU32(tmpi,0xC48348+i<<24);
|
|
|
|
|
else if (i<=I32_MAX) {
|
|
|
|
|
ICU24(tmpi,0xC48148);
|
|
|
|
|
ICU32(tmpi,i);
|
|
|
|
|
} else
|
|
|
|
|
throw('Compiler');
|
|
|
|
|
} else if (i<0) {
|
|
|
|
|
i=-i;
|
|
|
|
|
if (i<=I8_MAX)
|
|
|
|
|
ICU32(tmpi,0xEC8348+i<<24);
|
|
|
|
|
else if (i<=I32_MAX) {
|
|
|
|
|
ICU24(tmpi,0xEC8148);
|
|
|
|
|
ICU32(tmpi,i);
|
|
|
|
|
} else
|
|
|
|
|
throw('Compiler');
|
|
|
|
|
}
|
|
|
|
|
if (optimize && tmpi->ic_count>last_start)
|
|
|
|
|
tmpi->ic_last_start=last_start;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern U0 ICMov(CIntermediateCode *tmpi,
|
2020-02-20 23:40:10 +00:00
|
|
|
|
CICType t1,I64 r1,I64 d1,CICType t2,I64 r2,I64 d2,I64 rip);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
|
2020-02-20 23:40:10 +00:00
|
|
|
|
#define MODR_REG 0
|
|
|
|
|
#define MODR_INDIRECT_REG 1
|
|
|
|
|
#define MODR_D8_INDIRECT_REG 2
|
|
|
|
|
#define MODR_D32_INDIRECT_REG 3
|
|
|
|
|
#define MODR_SIB_INDIRECT_REG 4
|
|
|
|
|
#define MODR_SIB_D8_INDIRECT_REG 5
|
|
|
|
|
#define MODR_SIB_D32_INDIRECT_REG 6
|
|
|
|
|
#define MODR_RIP_REL 7
|
|
|
|
|
#define MODR_RIP_REL_IMM_U32 8
|
2020-02-15 20:01:48 +00:00
|
|
|
|
|
|
|
|
|
I64 ICModr1(I64 r,CICType t2,I64 r2,I64 d2)
|
|
|
|
|
{//res.u8[0] is type
|
|
|
|
|
//res.u8[1] is REX
|
2020-02-20 23:40:10 +00:00
|
|
|
|
//res.u8[2] is ModR
|
|
|
|
|
//res.u8[3] is SIB
|
|
|
|
|
I64 res=0;
|
|
|
|
|
if (t2.raw_type<RT_I64)
|
|
|
|
|
res.u8[1]=0x40;
|
|
|
|
|
else
|
|
|
|
|
res.u8[1]=0x48;
|
|
|
|
|
if (r>7) {
|
|
|
|
|
res.u8[1]+=4;
|
|
|
|
|
r&=7;
|
|
|
|
|
}
|
|
|
|
|
switch (Bsr(t2)) {
|
|
|
|
|
case MDf_REG:
|
|
|
|
|
if (r2>7) {
|
|
|
|
|
res.u8[1]++;
|
|
|
|
|
r2&=7;
|
|
|
|
|
}
|
|
|
|
|
res.u8[2]=0xC0+r<<3+r2;
|
|
|
|
|
res.u8[0]=MODR_REG;
|
|
|
|
|
if (res.u8[1]==0x40 && (t2.raw_type>=RT_I16 || r<4 && r2<4))
|
|
|
|
|
res.u8[1]=0;
|
|
|
|
|
break;
|
|
|
|
|
case MDf_DISP:
|
|
|
|
|
if (r2>7) {
|
|
|
|
|
res.u8[1]++;
|
|
|
|
|
r2&=7;
|
|
|
|
|
}
|
|
|
|
|
if (!d2 && r2!=REG_RBP) {
|
|
|
|
|
res.u8[2]=r<<3+r2;
|
|
|
|
|
res.u8[0]=MODR_INDIRECT_REG;
|
|
|
|
|
} else if (I8_MIN<=d2<=I8_MAX) {
|
|
|
|
|
res.u8[2]=0x40+r<<3+r2;
|
|
|
|
|
res.u8[0]=MODR_D8_INDIRECT_REG;
|
|
|
|
|
} else {
|
|
|
|
|
res.u8[2]=0x80+r<<3+r2;
|
|
|
|
|
res.u8[0]=MODR_D32_INDIRECT_REG;
|
|
|
|
|
}
|
|
|
|
|
if (res.u8[1]==0x40 && (t2.raw_type>=RT_I16 || r<4))
|
|
|
|
|
res.u8[1]=0;
|
|
|
|
|
break;
|
|
|
|
|
case MDf_SIB:
|
|
|
|
|
if (7<r2.u8[0]<REG_NONE)
|
|
|
|
|
res.u8[1]++;
|
|
|
|
|
if (r2.u8[1]&15>7)
|
|
|
|
|
res.u8[1]+=2;
|
|
|
|
|
if (r2.u8[0]==REG_NONE) {
|
|
|
|
|
res.u8[3]=5+(r2.u8[1]&7)<<3+r2.u8[1]&0xC0;
|
|
|
|
|
res.u8[2]=4+r<<3;
|
|
|
|
|
res.u8[0]=MODR_SIB_D32_INDIRECT_REG;
|
|
|
|
|
} else {
|
|
|
|
|
res.u8[3]=r2.u8[0]&7+(r2.u8[1]&7)<<3+r2.u8[1]&0xC0;
|
|
|
|
|
if (!d2 && r2.u8[0]&7!=REG_RBP) {
|
|
|
|
|
res.u8[2]=4+r<<3;
|
|
|
|
|
res.u8[0]=MODR_SIB_INDIRECT_REG;
|
|
|
|
|
} else if (I8_MIN<=d2<=I8_MAX) {
|
|
|
|
|
res.u8[2]=0x44+r<<3;
|
|
|
|
|
res.u8[0]=MODR_SIB_D8_INDIRECT_REG;
|
|
|
|
|
} else {
|
|
|
|
|
res.u8[2]=0x84+r<<3;
|
|
|
|
|
res.u8[0]=MODR_SIB_D32_INDIRECT_REG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (res.u8[1]==0x40 && (t2.raw_type>=RT_I16 || r<4))
|
|
|
|
|
res.u8[1]=0;
|
|
|
|
|
break;
|
|
|
|
|
case MDf_RIP_DISP32:
|
|
|
|
|
res.u8[2]=0x05+r<<3;
|
|
|
|
|
res.u8[0]=MODR_RIP_REL;
|
|
|
|
|
if (res.u8[1]==0x40 && (t2.raw_type>=RT_I16 || r<4))
|
|
|
|
|
res.u8[1]=0;
|
|
|
|
|
break;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
2020-02-20 23:40:10 +00:00
|
|
|
|
return res;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICModr2(CIntermediateCode *tmpi,I64 i,CICType t=0,I64 d,I64 rip=0)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
switch [i.u8[0]] {
|
|
|
|
|
case MODR_REG:
|
|
|
|
|
break;
|
|
|
|
|
case MODR_INDIRECT_REG:
|
|
|
|
|
break;
|
|
|
|
|
case MODR_D8_INDIRECT_REG:
|
|
|
|
|
ICU8(tmpi,d);
|
|
|
|
|
break;
|
|
|
|
|
case MODR_D32_INDIRECT_REG:
|
|
|
|
|
ICU32(tmpi,d);
|
|
|
|
|
break;
|
|
|
|
|
case MODR_SIB_INDIRECT_REG:
|
|
|
|
|
ICU8(tmpi,i.u8[3]);
|
|
|
|
|
break;
|
|
|
|
|
case MODR_SIB_D8_INDIRECT_REG:
|
|
|
|
|
ICU8(tmpi,i.u8[3]);
|
|
|
|
|
ICU8(tmpi,d);
|
|
|
|
|
break;
|
|
|
|
|
case MODR_SIB_D32_INDIRECT_REG:
|
|
|
|
|
ICU8(tmpi,i.u8[3]);
|
|
|
|
|
ICU32(tmpi,d);
|
|
|
|
|
break;
|
|
|
|
|
case MODR_RIP_REL_IMM_U32:
|
|
|
|
|
switch (t.raw_type) {
|
|
|
|
|
case RT_I8:
|
|
|
|
|
case RT_U8:
|
|
|
|
|
d--;
|
|
|
|
|
break;
|
|
|
|
|
case RT_I16:
|
|
|
|
|
case RT_U16:
|
|
|
|
|
d-=2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
d-=4;
|
|
|
|
|
}
|
|
|
|
|
case MODR_RIP_REL:
|
|
|
|
|
ICU32(tmpi,d-(rip+4+tmpi->ic_count));
|
|
|
|
|
tmpi->ic_flags&=~ICF_CODE_FINAL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-20 23:40:10 +00:00
|
|
|
|
#define SLASH_OP_INC 0x0003000000FFFE00
|
|
|
|
|
#define SLASH_OP_DEC 0x052B000000FFFE01
|
|
|
|
|
#define SLASH_OP_NOT 0x0000000000F7F602
|
|
|
|
|
#define SLASH_OP_NEG 0x0000000000F7F603
|
|
|
|
|
#define SLASH_OP_IMM_U8 0x0000000000838000
|
|
|
|
|
#define SLASH_OP_IMM_U32 0x0000000000818300
|
|
|
|
|
#define SLASH_OP_MUL 0x0000000000F7F604
|
|
|
|
|
#define SLASH_OP_IMUL 0x0000000000F7F605
|
|
|
|
|
#define SLASH_OP_DIV 0x0000000000F7F606
|
|
|
|
|
#define SLASH_OP_MOV 0x0000000000898800
|
|
|
|
|
#define SLASH_OP_MOV_IMM 0x0000000000C7C600
|
|
|
|
|
#define SLASH_OP_PUSH 0x0000000000FFFF06
|
|
|
|
|
#define SLASH_OP_POP 0x00000000008F8F00
|
|
|
|
|
#define SLASH_OP_FADD 0x0000C1DE01DCDC00
|
|
|
|
|
#define SLASH_OP_FSUB 0x0000E9DE01DCDC04
|
|
|
|
|
#define SLASH_OP_FSUBR 0x0000E1DE01DCDC05
|
|
|
|
|
#define SLASH_OP_FMUL 0x0000C9DE01DCDC01
|
|
|
|
|
#define SLASH_OP_FDIV 0x0000F9DE01DCDC06
|
|
|
|
|
#define SLASH_OP_FDIVR 0x0000F1DE01DCDC07
|
|
|
|
|
#define SLASH_OP_FLD 0x0000000001DDDD00
|
|
|
|
|
#define SLASH_OP_FSTP 0x0000000001DDDD03
|
|
|
|
|
#define SLASH_OP_FISTTP 0x0000000001DDDD01
|
|
|
|
|
#define SLASH_OP_FILD 0x0000000001DFDF05
|
2020-02-15 20:01:48 +00:00
|
|
|
|
|
|
|
|
|
U0 ICSlashOp(CIntermediateCode *tmpi,CICType t1,I64 r1,I64 d1,I64 op,I64 rip)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i;
|
|
|
|
|
if (t1&MDF_REG && !op.u8[3])
|
|
|
|
|
t1=t1&(MDG_MASK|RTF_UNSIGNED)+RT_I64; //Set to 64 bit,preserving unsigned
|
|
|
|
|
i=ICModr1(op.u8[0],t1,r1,d1);
|
|
|
|
|
if (tmpi->ic_flags&ICF_LOCK && !(t1&MDF_REG) &&
|
|
|
|
|
op&~7!=SLASH_OP_MOV && op!=SLASH_OP_MOV_IMM)
|
|
|
|
|
ICU8(tmpi,OC_LOCK_PREFIX);
|
|
|
|
|
switch (t1.raw_type) {
|
|
|
|
|
case RT_I8:
|
|
|
|
|
case RT_U8:
|
|
|
|
|
ICRex(tmpi,i.u8[1]);
|
|
|
|
|
ICU16(tmpi,i.u8[2]<<8+op.u8[1]);
|
|
|
|
|
break;
|
|
|
|
|
case RT_I16:
|
|
|
|
|
case RT_U16:
|
|
|
|
|
ICOpSizeRex(tmpi,i.u8[1]);
|
|
|
|
|
ICU16(tmpi,i.u8[2]<<8+op.u8[2]);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (i.u8[1]!=0x48 || !op.u8[3])
|
|
|
|
|
ICRex(tmpi,i.u8[1]);
|
|
|
|
|
ICU16(tmpi,i.u8[2]<<8+op.u8[2]);
|
|
|
|
|
}
|
|
|
|
|
if (i.u8[0]==MODR_RIP_REL&& (op==SLASH_OP_MOV_IMM || op&~7==SLASH_OP_IMM_U32))
|
|
|
|
|
i.u8[0]=MODR_RIP_REL_IMM_U32;
|
|
|
|
|
ICModr2(tmpi,i,t1,d1,rip);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICPush(CIntermediateCode *tmpi,CICType t1,I64 r1,I64 d1,I64 rip)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
switch (Bsr(t1)) {
|
|
|
|
|
case MDf_REG:
|
|
|
|
|
if (r1>7)
|
|
|
|
|
ICU16(tmpi,0x5049+(r1&7)<<8);
|
|
|
|
|
else
|
|
|
|
|
ICU8(tmpi,0x50+r1);
|
|
|
|
|
return;
|
|
|
|
|
case MDf_IMM:
|
|
|
|
|
if (I8_MIN<=d1<=I8_MAX)
|
|
|
|
|
ICU16(tmpi,0x6A+d1<<8);
|
|
|
|
|
else if (I32_MIN<=d1<=I32_MAX) {
|
|
|
|
|
ICU8(tmpi,0x68);
|
|
|
|
|
ICU32(tmpi,d1);
|
|
|
|
|
} else {
|
|
|
|
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,t1,r1,d1,rip);
|
|
|
|
|
ICU8(tmpi,0x50+REG_RBX);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case MDf_STACK:
|
|
|
|
|
return;
|
|
|
|
|
case MDf_DISP:
|
|
|
|
|
case MDf_SIB:
|
|
|
|
|
case MDf_RIP_DISP32:
|
|
|
|
|
switch (t1.raw_type) {
|
|
|
|
|
case RT_I64:
|
|
|
|
|
case RT_U64:
|
|
|
|
|
case RT_F64:
|
|
|
|
|
ICSlashOp(tmpi,t1,r1,d1,SLASH_OP_PUSH,rip);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,t1,r1,d1,rip);
|
2020-02-20 23:40:10 +00:00
|
|
|
|
ICU16(tmpi,0x5048+REG_RBX<<8);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICPushRegs(CIntermediateCode *tmpi,I64 mask)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i;
|
|
|
|
|
for (i=0;i<REG_REGS_NUM;i++) {
|
|
|
|
|
if (Bt(&mask,i)) {
|
|
|
|
|
if (i>7)
|
|
|
|
|
ICU16(tmpi,0x5049+(i&7)<<8);
|
|
|
|
|
else
|
|
|
|
|
ICU8(tmpi,0x50+i);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICPop(CIntermediateCode *tmpi,CICType t1,I64 r1,I64 d1,I64 rip)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
switch (Bsr(t1)) {
|
|
|
|
|
case MDf_REG:
|
|
|
|
|
if (r1>7)
|
|
|
|
|
ICU16(tmpi,0x5849+(r1&7)<<8);
|
|
|
|
|
else
|
|
|
|
|
ICU8(tmpi,0x58+r1);
|
|
|
|
|
break;
|
|
|
|
|
case MDf_DISP:
|
|
|
|
|
case MDf_RIP_DISP32:
|
|
|
|
|
case MDf_SIB:
|
|
|
|
|
if (t1.raw_type<RT_I64) {
|
|
|
|
|
ICU8(tmpi,0x58+REG_RBX);
|
|
|
|
|
ICMov(tmpi,t1,r1,d1,MDF_REG+RT_I64,REG_RBX,0,rip);
|
|
|
|
|
} else
|
|
|
|
|
ICSlashOp(tmpi,t1,r1,d1,SLASH_OP_POP,rip);
|
|
|
|
|
break;
|
|
|
|
|
case MDf_STACK:
|
|
|
|
|
case MDf_IMM:
|
|
|
|
|
ICU8(tmpi,0x58+REG_RBX);
|
|
|
|
|
ICMov(tmpi,t1,r1,d1,MDF_REG+RT_I64,REG_RBX,0,rip);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ICAddRSP(tmpi,8);
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICPopRegs(CIntermediateCode *tmpi,I64 mask)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i;
|
|
|
|
|
for (i=REG_REGS_NUM-1;i>=0;i--) {
|
|
|
|
|
if (Bt(&mask,i)) {
|
|
|
|
|
if (i>7)
|
|
|
|
|
ICU16(tmpi,0x5849+(i&7)<<8);
|
|
|
|
|
else
|
|
|
|
|
ICU8(tmpi,0x58+i);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICZero(CIntermediateCode *tmpi,I64 r)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
if (r>7) {
|
|
|
|
|
r&=7;
|
|
|
|
|
ICU24(tmpi,0xC0334D+r<<16+r<<19);
|
|
|
|
|
} else
|
|
|
|
|
ICU16(tmpi,0xC033+r<<8+r<<11);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICTest(CIntermediateCode *tmpi,I64 r)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i=0xC08548; //TEST R,R
|
|
|
|
|
if (r>7) {
|
|
|
|
|
i+=5;
|
|
|
|
|
r&=7;
|
|
|
|
|
}
|
|
|
|
|
ICU24(tmpi,i+r<<16+r<<19);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
I64 ICBuiltInFloatConst(F64 d)
|
|
|
|
|
{//Returns 2-byte opcode for FLD const or zero
|
2020-02-20 23:40:10 +00:00
|
|
|
|
if (!d)
|
|
|
|
|
return 0xEED9;
|
|
|
|
|
else if (d==1.0)
|
|
|
|
|
return 0xE8D9;
|
|
|
|
|
else if (GetOption(OPTf_NO_BUILTIN_CONST))
|
|
|
|
|
return 0;
|
|
|
|
|
else if (d==<EFBFBD>)
|
|
|
|
|
return 0xEBD9;
|
|
|
|
|
else if (d==log2_10)
|
|
|
|
|
return 0xE9D9;
|
|
|
|
|
else if (d==log2_e)
|
|
|
|
|
return 0xEAD9;
|
|
|
|
|
else if (d==log10_2)
|
|
|
|
|
return 0xECD9;
|
|
|
|
|
else if (d==loge_2)
|
|
|
|
|
return 0xEDD9;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICMov(CIntermediateCode *tmpi,
|
2020-02-20 23:40:10 +00:00
|
|
|
|
CICType t1,I64 r1,I64 d1,CICType t2,I64 r2,I64 d2,I64 rip)
|
2020-02-15 20:01:48 +00:00
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i,count1,count2,b1_rex,b2_rex,b1,b2,b1_modr,b2_modr,
|
|
|
|
|
b1_r1,b1_r2,b2_r1,b2_r2,last_start=tmpi->ic_count;
|
|
|
|
|
CIntermediateCode *tmpil1;
|
|
|
|
|
Bool old_lock=Btr(&tmpi->ic_flags,ICf_LOCK);
|
|
|
|
|
switch (Bsr(t1)) {
|
|
|
|
|
case MDf_REG:
|
|
|
|
|
if (t2&MDF_IMM) {
|
|
|
|
|
if (!d2)
|
|
|
|
|
ICZero(tmpi,r1);
|
|
|
|
|
else if (0<=d2<=U8_MAX) {
|
|
|
|
|
ICZero(tmpi,r1);
|
|
|
|
|
if (r1>7)
|
|
|
|
|
ICU24(tmpi,d2<<16+(0xB0+r1&7)<<8+0x41);
|
|
|
|
|
else if (r1>3)
|
|
|
|
|
ICU24(tmpi,d2<<16+(0xB0+r1)<<8+0x40);
|
|
|
|
|
else
|
|
|
|
|
ICU16(tmpi,d2<<8+0xB0+r1);
|
|
|
|
|
} else if (I8_MIN<=d2<0) {
|
|
|
|
|
if (r1>7) {
|
|
|
|
|
r1&=7;
|
|
|
|
|
ICU24(tmpi,d2<<16+(0xB0+r1)<<8+0x41);
|
|
|
|
|
ICU32(tmpi,0xC0BE0F4D+r1<<24+r1<<27);
|
|
|
|
|
} else {
|
|
|
|
|
if (r1>3)
|
|
|
|
|
ICU24(tmpi,d2<<16+(0xB0+r1)<<8+0x40);
|
|
|
|
|
else
|
|
|
|
|
ICU16(tmpi,d2<<8+0xB0+r1);
|
|
|
|
|
ICU32(tmpi,0xC0BE0F48+r1<<24+r1<<27);
|
|
|
|
|
}
|
|
|
|
|
} else if (0<=d2<=U32_MAX) {
|
|
|
|
|
if (r1>7) {
|
|
|
|
|
r1&=7;
|
|
|
|
|
ICU16(tmpi,(0xB8+r1)<<8+0x41);
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
} else {
|
|
|
|
|
ICU8(tmpi,0xB8+r1);
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
}
|
|
|
|
|
} else if (I32_MIN<=d2<0) {
|
|
|
|
|
if (r1>7) {
|
|
|
|
|
r1&=7;
|
|
|
|
|
ICU16(tmpi,(0xB8+r1)<<8+0x41);
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
ICU24(tmpi,0xC0634D+r1<<16+r1<<19);
|
|
|
|
|
} else {
|
|
|
|
|
ICU8(tmpi,0xB8+r1);
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
ICU24(tmpi,0xC06348+r1<<16+r1<<19);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
i=0xB848;
|
|
|
|
|
if (r1>7) {
|
|
|
|
|
i++;
|
|
|
|
|
r1&=7;
|
|
|
|
|
}
|
|
|
|
|
ICU16(tmpi,i+r1<<8);
|
|
|
|
|
ICU64(tmpi,d2);
|
|
|
|
|
}
|
|
|
|
|
} else if (t2&MDF_STACK)
|
|
|
|
|
ICPop(tmpi,t1,r1,d1,rip);
|
|
|
|
|
else {
|
|
|
|
|
if (r1==r2 && t2&MDF_REG)
|
|
|
|
|
goto move_done;
|
|
|
|
|
if (t2&MDF_REG)
|
|
|
|
|
t2=MDF_REG+RT_I64;
|
|
|
|
|
i=ICModr1(r1,t2,r2,d2);
|
|
|
|
|
if (t2.raw_type!=RT_U32)
|
|
|
|
|
i|=0x4800;
|
|
|
|
|
ICRex(tmpi,i.u8[1]);
|
|
|
|
|
switch (t2.raw_type) {
|
|
|
|
|
case RT_I8:
|
|
|
|
|
ICU24(tmpi,i.u8[2]<<16+0xBE0F);
|
|
|
|
|
break;
|
|
|
|
|
case RT_I16:
|
|
|
|
|
ICU24(tmpi,i.u8[2]<<16+0xBF0F);
|
|
|
|
|
break;
|
|
|
|
|
case RT_I32:
|
|
|
|
|
ICU16(tmpi,i.u8[2]<<8+0x63);
|
|
|
|
|
break;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
|
2020-02-20 23:40:10 +00:00
|
|
|
|
case RT_U8:
|
|
|
|
|
ICU24(tmpi,i.u8[2]<<16+0xB60F);
|
|
|
|
|
break;
|
|
|
|
|
case RT_U16:
|
|
|
|
|
ICU24(tmpi,i.u8[2]<<16+0xB70F);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ICU16(tmpi,i.u8[2]<<8+0x8B);
|
|
|
|
|
}
|
|
|
|
|
ICModr2(tmpi,i,,d2,rip);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case MDf_STACK:
|
|
|
|
|
if (tmpi->ic_flags&ICF_PUSH_CMP)
|
|
|
|
|
ICPopRegs(tmpi,1<<REG_RBX);
|
|
|
|
|
if (t1.raw_type<t2.raw_type)
|
|
|
|
|
ICPush(tmpi,t2&MDG_MASK+t1.raw_type,r2,d2,rip);
|
|
|
|
|
else
|
|
|
|
|
ICPush(tmpi,t2,r2,d2,rip);
|
|
|
|
|
if (tmpi->ic_flags&ICF_PUSH_CMP)
|
|
|
|
|
ICPushRegs(tmpi,1<<REG_RBX);
|
|
|
|
|
break;
|
|
|
|
|
case MDf_DISP:
|
|
|
|
|
case MDf_RIP_DISP32:
|
|
|
|
|
case MDf_SIB:
|
|
|
|
|
if (t2&MDF_IMM && (t1.raw_type<RT_I64 || (I32_MIN<=d2<=I32_MAX))) {
|
|
|
|
|
ICSlashOp(tmpi,t1,r1,d1,SLASH_OP_MOV_IMM,rip);
|
|
|
|
|
switch (t1.raw_type) {
|
|
|
|
|
case RT_I8:
|
|
|
|
|
case RT_U8:
|
|
|
|
|
ICU8(tmpi,d2);
|
|
|
|
|
break;
|
|
|
|
|
case RT_I16:
|
|
|
|
|
case RT_U16:
|
|
|
|
|
ICU16(tmpi,d2);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (t2&MDF_REG)
|
|
|
|
|
ICSlashOp(tmpi,t1,r1,d1,r2+SLASH_OP_MOV,rip);
|
|
|
|
|
else {
|
|
|
|
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,t2,r2,d2,rip);
|
|
|
|
|
ICMov(tmpi,t1,r1,d1,MDF_REG+RT_I64,REG_RBX,0,rip);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
move_done:
|
2020-02-20 23:40:10 +00:00
|
|
|
|
if (!((t1|t2)&(MDF_STACK|MDF_RIP_DISP32))) {
|
|
|
|
|
tmpil1=tmpi;
|
|
|
|
|
if (tmpi->ic_last_start<0 && (tmpil1=OptLag1(tmpi)) &&
|
|
|
|
|
tmpil1->ic_last_start<0)
|
|
|
|
|
tmpil1=NULL;
|
|
|
|
|
if (tmpil1) {
|
|
|
|
|
if (tmpil1==tmpi)
|
|
|
|
|
count1=last_start-tmpil1->ic_last_start;
|
|
|
|
|
else {
|
|
|
|
|
if (!(tmpil1->ic_flags&ICF_CODE_FINAL))
|
|
|
|
|
tmpi->ic_flags&=~ICF_CODE_FINAL;
|
|
|
|
|
if (last_start)
|
|
|
|
|
count1=0;
|
|
|
|
|
else
|
|
|
|
|
count1=tmpil1->ic_count-tmpil1->ic_last_start;
|
|
|
|
|
}
|
|
|
|
|
count2=tmpi->ic_count-last_start;
|
|
|
|
|
if (count1 && count1==count2) {
|
|
|
|
|
b1_rex=tmpil1->ic_body[tmpil1->ic_last_start];
|
|
|
|
|
b2_rex=tmpi->ic_body[last_start];
|
|
|
|
|
if (b1_rex&0x48==0x48 && b2_rex&0x48==0x48) {
|
|
|
|
|
for (i=1;i<count1;i++)
|
|
|
|
|
if ((b1=tmpil1->ic_body[tmpil1->ic_last_start+i])==
|
|
|
|
|
(b2=tmpi->ic_body[last_start+i])) {
|
|
|
|
|
if (i==1 && (b2==0x89 || b2==0x8B)) {
|
|
|
|
|
b1_modr=tmpil1->ic_body[tmpil1->ic_last_start+2];
|
|
|
|
|
b1_r1=b1_modr&7 +Bt(&b1_rex,0)<<3;
|
|
|
|
|
b1_r2=b1_modr>>3&7+Bt(&b1_rex,2)<<3;
|
|
|
|
|
b2_modr=tmpi->ic_body[last_start+2];
|
|
|
|
|
b2_r1=b2_modr&7 +Bt(&b2_rex,0)<<3;
|
|
|
|
|
b2_r2=b2_modr>>3&7+Bt(&b2_rex,2)<<3;
|
|
|
|
|
if (count1==3 && b2_modr&0xC0==0xC0) {
|
|
|
|
|
if (b2_r1==b2_r2)
|
|
|
|
|
goto move_redundant;
|
|
|
|
|
if (b1_modr&0xC0==0xC0) {
|
|
|
|
|
if (b1_r1==b2_r2 && b2_r1==b1_r2)
|
|
|
|
|
goto move_redundant;
|
|
|
|
|
}
|
|
|
|
|
} else if (b1_rex!=b2_rex || b1_r1==b1_r2 || (t1|t2)&MDF_SIB)
|
|
|
|
|
break;
|
|
|
|
|
} else if (b1_rex!=b2_rex)
|
|
|
|
|
break;
|
|
|
|
|
} else if (i!=1)
|
|
|
|
|
break;
|
|
|
|
|
else if (b2!=0x89 && b2!=0x8B)
|
|
|
|
|
break;
|
|
|
|
|
else {
|
|
|
|
|
b1_modr=tmpil1->ic_body[tmpil1->ic_last_start+2];
|
|
|
|
|
b1_r1=b1_modr&7 +Bt(&b1_rex,0)<<3;
|
|
|
|
|
b1_r2=b1_modr>>3&7+Bt(&b1_rex,2)<<3;
|
|
|
|
|
b2_modr=tmpi->ic_body[last_start+2];
|
|
|
|
|
b2_r1=b2_modr&7 +Bt(&b2_rex,0)<<3;
|
|
|
|
|
b2_r2=b2_modr>>3&7+Bt(&b2_rex,2)<<3;
|
|
|
|
|
if (count1==3 && b2_modr&0xC0==0xC0) {
|
|
|
|
|
if (b2_r1==b2_r2)
|
|
|
|
|
goto move_redundant;
|
|
|
|
|
if (b1==0x89 && b2==0x8B || b1==0x8B && b2==0x89) {
|
|
|
|
|
if (b1_modr&0xC0==0xC0) {
|
|
|
|
|
if (b1_r1==b2_r1 && b1_r2==b2_r2 ||
|
|
|
|
|
b1_r1==b2_r2 && b2_r1==b1_r2)
|
|
|
|
|
goto move_redundant;
|
|
|
|
|
}
|
|
|
|
|
if (b1_rex!=b2_rex)
|
|
|
|
|
break;
|
|
|
|
|
} else
|
|
|
|
|
break;
|
|
|
|
|
} else if (b1_r1==b1_r2 || (t1|t2)&MDF_SIB || b1_rex!=b2_rex ||
|
|
|
|
|
!(b1==0x89 && b2==0x8B || b1==0x8B && b2==0x89))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (i==count1) {
|
2020-02-15 20:01:48 +00:00
|
|
|
|
move_redundant:
|
2020-02-20 23:40:10 +00:00
|
|
|
|
tmpi->ic_count=last_start;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
2020-02-20 23:40:10 +00:00
|
|
|
|
if (tmpi->ic_count>last_start>tmpi->ic_last_start)
|
|
|
|
|
tmpi->ic_last_start=last_start;
|
|
|
|
|
BEqual(&tmpi->ic_flags,ICf_LOCK,old_lock);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICLea(CIntermediateCode *tmpi,CICType t1,I64 r1,I64 d1,
|
2020-02-20 23:40:10 +00:00
|
|
|
|
CICType t2,I64 r2,I64 d2,CCompCtrl *cc,U8 *buf,I64 rip)
|
2020-02-15 20:01:48 +00:00
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
I64 i;
|
|
|
|
|
CAOTAbsAddr *tmpa;
|
|
|
|
|
switch (Bsr(t1)) {
|
|
|
|
|
case MDf_REG:
|
|
|
|
|
i=ICModr1(r1,t2,r2,d2);
|
|
|
|
|
i.u8[1]|=0x48;
|
|
|
|
|
ICU24(tmpi,i.u8[2]<<16+0x8D00+i.u8[1]);
|
|
|
|
|
ICModr2(tmpi,i,,d2,rip);
|
|
|
|
|
break;
|
|
|
|
|
case MDf_STACK:
|
|
|
|
|
if (t2&MDF_RIP_DISP32) {
|
|
|
|
|
ICU8(tmpi,0x68);
|
|
|
|
|
ICU32(tmpi,d2);
|
|
|
|
|
if (cc->flags&CCF_AOT_COMPILE && buf && !(cc->flags&CCF_NO_ABSS)) {
|
|
|
|
|
tmpa=CAlloc(sizeof(CAOTAbsAddr));
|
|
|
|
|
tmpa->next=cc->aotc->abss;
|
|
|
|
|
tmpa->type=AAT_ADD_U32;
|
|
|
|
|
cc->aotc->abss=tmpa;
|
|
|
|
|
tmpa->rip=rip+tmpi->ic_count-4;
|
|
|
|
|
}
|
|
|
|
|
tmpi->ic_flags&=~ICF_CODE_FINAL;
|
|
|
|
|
break;
|
|
|
|
|
} // Fall thru
|
|
|
|
|
default:
|
|
|
|
|
ICLea(tmpi,MDF_REG+RT_I64,REG_RCX,0,t2,r2,d2,cc,buf,rip);
|
|
|
|
|
ICMov(tmpi,t1,r1,d1,MDF_REG+RT_I64,REG_RCX,0,rip);
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U0 ICDeref(CIntermediateCode *tmpi,I64 rip)
|
|
|
|
|
{
|
2020-02-20 23:40:10 +00:00
|
|
|
|
CICType t;
|
|
|
|
|
t=tmpi->res.type.raw_type;
|
|
|
|
|
if (t>tmpi->arg1_type_pointed_to)
|
|
|
|
|
t=tmpi->arg1_type_pointed_to;
|
|
|
|
|
if (tmpi->arg1.type&MDF_REG)
|
|
|
|
|
ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
|
|
|
|
|
MDF_DISP+t,tmpi->arg1.reg,tmpi->arg1.disp,rip);
|
|
|
|
|
else {
|
|
|
|
|
ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,
|
|
|
|
|
tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip);
|
|
|
|
|
ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
|
|
|
|
|
MDF_DISP+t,REG_RCX,0,rip);
|
|
|
|
|
}
|
2020-02-15 20:01:48 +00:00
|
|
|
|
}
|