Files
TempleOS-Rijn/LT/Compiler/Code.CPZ
T
2018-09-08 21:45:20 +02:00

2452 lines
70 KiB
Plaintext

$WW,1$/*$FG,5$$TX+CX,"Intermediate Code"$
$TX+CX,"To"$
$TX+CX,"Machine Code"$
$FG$
$FG,2$RAX$FG$,$FG,2$RBX$FG$,$FG,2$RCX$FG$ and $FG,2$RDX$FG$ can be trashed by each intermediate code's output code. However, intermediate codes must be coupled together based on the parameter and result type specifications in the $LK,"IcParam","MN:IcParam"$. $FG,2$RAX$FG$ is the most common register for coupling intermediate codes.
Internal calculations take place on 64-bit values, so anything which has found it's way into a register has been sign or zero extended to 64-bits. However, calculations can lead to range violations. Performance can be boosted if you avoid causing this situation in your code. The $LK,"OPTf_IGNORE_OVERFLOW","MN:OPTf_IGNORE_OVERFLOW"$ flag sent to $LK,"OptOn","MN:OptOn"$() will make the compiler assume no range violations will occur. Since, I have the power of creating standards for this language, I should probably just mandate that nobody assume range restrictions for less than 64-bit variables will be enforced through-out intermediate calculations, but I want to try not to break with $FG,2$C$FG$ standards unless it's way better. I'm planning to make my code $LK,"OPTf_IGNORE_OVERFLOW","MN:OPTf_IGNORE_OVERFLOW"$ compliant.
The $LK,"IcMov","MN:IcMov"$() routine is commonly used. It needs a register for zero-extensions when dealing with U4's and when shuffling things around. I try to use the $FG,2$RBX$FG$ register as a scratch register available for sub-intermediate codes to trash. Don't assume $FG,2$RBX$FG$ will be preserved by $LK,"IcMov","MN:IcMov"$() or other sub-intermediate code routines. If you are not calling such routines, you can use it.
You might get away with returning a value from a $UL,1$sub$UL,0$intermediate code helper routine in $FG,2$RBX$FG$, but maybe not because it has to zero-extend $FG,2$U4$FG$'s and I know no way besides XORing ahead and moving a $FG,2$U4$FG$ in, which requires two registers.
Code size changing during passes could cause problems. Jumps will be shortened (not lengthened) on successive passes and contraction does not hurt jumps, but contraction can hurt a glbl displacement. I decided all code must reside in the lowest 2Gig allowing 32-bit relative addressing for $FG,2$CALLS$FG$ and $FG,2$JMPS$FG$. To allow code beyond 2Gig, indirect calls and jmps could be used. (Load a 64-bit value in a register and call the register.)
*/$WW,0$
void IcU1(IntermediateCode *tempi,U1 b)
{
if (tempi->ic_cnt>=IC_BODY_SIZE-1|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=b;
} else
tempi->ic_body[tempi->ic_cnt++]=b;
}
void IcRex(IntermediateCode *tempi,U1 b)
{
if (b) {
if (tempi->ic_cnt>=IC_BODY_SIZE-1|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=b;
} else
tempi->ic_body[tempi->ic_cnt++]=b;
}
}
void Ic66Rex(IntermediateCode *tempi,U1 b)
{
if (!b) {
if (tempi->ic_cnt>=IC_BODY_SIZE-1|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=0x66;
} else
tempi->ic_body[tempi->ic_cnt++]=0x66;
} else {
if (tempi->ic_cnt>=IC_BODY_SIZE-2|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=0x66;
tempi->ic_ext_body[tempi->ic_cnt++]=b;
} else {
tempi->ic_body[tempi->ic_cnt++]=0x66;
tempi->ic_body[tempi->ic_cnt++]=b;
}
}
}
void IcU2(IntermediateCode *tempi,U2 w)
{
if (tempi->ic_cnt>=IC_BODY_SIZE-2|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=w.u1[0];
tempi->ic_ext_body[tempi->ic_cnt++]=w.u1[1];
} else {
tempi->ic_body[tempi->ic_cnt++]=w.u1[0];
tempi->ic_body[tempi->ic_cnt++]=w.u1[1];
}
}
void IcU3(IntermediateCode *tempi,U4 d)
{
if (tempi->ic_cnt>=IC_BODY_SIZE-3|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
tempi->ic_ext_body[tempi->ic_cnt++]=d.u1[0];
tempi->ic_ext_body[tempi->ic_cnt++]=d.u1[1];
tempi->ic_ext_body[tempi->ic_cnt++]=d.u1[2];
} else {
tempi->ic_body[tempi->ic_cnt++]=d.u1[0];
tempi->ic_body[tempi->ic_cnt++]=d.u1[1];
tempi->ic_body[tempi->ic_cnt++]=d.u1[2];
}
}
void IcU4(IntermediateCode *tempi,U4 d)
{
U4 *dd;
if (tempi->ic_cnt>=IC_BODY_SIZE-4|| tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
dd=&tempi->ic_ext_body[tempi->ic_cnt];
} else {
dd=&tempi->ic_body[tempi->ic_cnt];
}
*dd=d;
tempi->ic_cnt+=4;
}
void IcU8(IntermediateCode *tempi,U8 q)
{
U8 *qq;
if (tempi->ic_cnt>=IC_BODY_SIZE-8 || tempi->ic_ext_body) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
qq=&tempi->ic_ext_body[tempi->ic_cnt];
} else
qq=&tempi->ic_body[tempi->ic_cnt];
*qq=q;
tempi->ic_cnt+=8;
}
void IcCopyIrq(IntermediateCode *tempi,U8 op)
{
U1 *ptr;
I8 i;
ptr=sys_irq_vectors[op];
i=sys_irq_vectors[op+1]-2-ptr; //sub 2 because IRET
if (tempi->ic_cnt+i>=IC_BODY_SIZE) {
if (!tempi->ic_ext_body) {
tempi->ic_ext_body=MAlloc(256);
MemCpy(tempi->ic_ext_body,tempi->ic_body,tempi->ic_cnt);
}
MemCpy(&tempi->ic_ext_body[tempi->ic_cnt],ptr,i);
} else
MemCpy(&tempi->ic_body[tempi->ic_cnt],ptr,i);
tempi->ic_cnt+=i;
}
extern void IcMov(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,U8 t2,U8 r2,I8 d2,I8 ip);
U8 IcModr(U8 r,U8 t2,U8 r2,I8 d2)
{
//result.u[0] is type 0=[REG],1=disp8[REG],2=disp32[REG],3=REG,4=RIP_REL
//result.u[1] is REX
//result.u[2] is ModR
U8 result=0;
if (t2&IT_MASK<IT_I8)
result.u1[1]=0x40;
else
result.u1[1]=0x48;
if (r>7) {
result.u1[1]+=4;
r&=7;
}
if (t2&TY_MASK==TY_RIP_DISP32) {
result.u1[2]=0x05+r<<3;
result.u1[0]=4;
if (result.u1[1]==0x40 &&
(t2&IT_MASK>=IT_I2 ||
r<4))
result.u1[1]=0;
} else {
if (r2>7) {
result.u1[1]++;
r2&=7;
}
if (t2&TY_MASK==TY_REG) {
result.u1[2]=0xC0+r<<3+r2;
result.u1[0]=3;
if (result.u1[1]==0x40 &&
(t2&IT_MASK>=IT_I2 ||
(r<4 && r2<4)))
result.u1[1]=0;
} else if (t2&TY_MASK==TY_DISP) {
if (!d2) {
result.u1[2]=r<<3+r2;
result.u1[0]=0;
} else if (MIN_I1<=d2<=MAX_I1) {
result.u1[2]=0x40+r<<3+r2;
result.u1[0]=1;
} else {
result.u1[2]=0x80+r<<3+r2;
result.u1[0]=2;
}
if (result.u1[1]==0x40 &&
(t2&IT_MASK>=IT_I2 ||
r<4))
result.u1[1]=0;
}
}
return result;
}
#define SLASH_OP_INC 0xFFFE00
#define SLASH_OP_DEC 0xFFFE01
#define SLASH_OP_NOT 0xF7F602
#define SLASH_OP_NEG 0xF7F603
#define SLASH_OP_MUL 0xF7F604
#define SLASH_OP_MOV 0x898800
void IcSlashOp(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,U8 op,I8 ip)
{
I8 i=IcModr(op.u1[0],t1,r1,d1);
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op.u1[1]);
break;
case IT_I2:
case IT_U2:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op.u1[2]);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op.u1[2]);
}
if (i.u1[0]==1)
IcU1(tempi,d1);
else if (i.u1[0]==2)
IcU4(tempi,d1);
else if (i.u1[0]==4) {
IcU4(tempi,d1-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
}
void IcPush(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,I8 ip)
{
U8 i;
IntermediateCode *tempi_last=tempi-sizeof(IntermediateCode);
switch (t1>>4) {
case TY_REG>>4:
if (t1&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t1,r1,d1,ip);
IcU2(tempi,0x5048+CREG_RBX<<8);
} else {
if (r1>7)
IcU2(tempi,0x5049+(r1&7)<<8);
else
IcU2(tempi,0x5048+r1<<8);
}
break;
case TY_IMM>>4:
if (MIN_I1<=d1<=MAX_I1)
IcU3(tempi,0x6A48+d1<<16);
else if (MIN_I4<=d1<=MAX_I4) {
IcU2(tempi,0x6848);
IcU4(tempi,d1);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t1,r1,d1,ip);
IcU2(tempi,0x5048+CREG_RBX<<8);
}
break;
case TY_DISP>>4:
i=0x48;
switch (t1&IT_MASK) {
case IT_I8:
case IT_U8:
case IT_DOUBLE:
if (r1>7) {
i++;
r1&=7;
}
if (!d1)
IcU3(tempi,0x30FF00+r1<<16+i);
else if (MIN_I1<=d1<=MAX_I1) {
IcU3(tempi,0x70FF00+r1<<16+i);
IcU1(tempi,d1);
} else {
IcU3(tempi,0xB0FF00+r1<<16+i);
IcU4(tempi,d1);
}
break;
default:
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t1,r1,d1,ip);
IcU2(tempi,0x5048+CREG_RBX<<8);
}
break;
case TY_RIP_DISP32>>4:
switch (t1&IT_MASK) {
case IT_I8:
case IT_U8:
case IT_DOUBLE:
IcU3(tempi,0x35FF48);
IcU4(tempi,d1-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
break;
default:
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t1,r1,d1,ip);
IcU2(tempi,0x5048+CREG_RBX<<8);
}
break;
default:
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t1,r1,d1,ip);
IcU2(tempi,0x5048+CREG_RBX<<8);
break;
}
}
void IcPushRegs(IntermediateCode *tempi,U8 mask)
{
I8 i;
for (i=0;i<NUM_REGS;i++) {
if (Bt(&mask,i)) {
if (i>7)
IcU2(tempi,0x5049+(i&7)<<8);
else
IcU2(tempi,0x5048+i<<8);
}
}
}
void IcPop(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,I8 ip)
{
switch (t1>>4) {
case TY_REG>>4:
if (r1>7)
IcU2(tempi,0x5849+(r1&7)<<8);
else
IcU2(tempi,0x5848+r1<<8);
break;
case TY_NULL>>4:
break;
default:
IcU2(tempi,0x5848+CREG_RBX<<8);
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RBX,0,ip);
}
}
void IcPopRegs(IntermediateCode *tempi,U8 mask)
{
I8 i;
for (i=NUM_REGS-1;i>=0;i--) {
if (Bt(&mask,i)) {
if (i>7)
IcU2(tempi,0x5849+(i&7)<<8);
else
IcU2(tempi,0x5848+i<<8);
}
}
}
void IcZero(IntermediateCode *tempi,U8 r)
{
if (r>7) {
r&=7;
IcU3(tempi,0xC0334D+r<<16+r<<19);
} else
IcU2(tempi,0xC033+r<<8+r<<11);
}
void IcOr(IntermediateCode *tempi,U8 r)
{
U8 i=0xC00B48; //OR R,R
if (r>7) {
i+=5;
r&=7;
}
IcU3(tempi,i+r<<16+r<<19);
}
void IcMov(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,U8 t2,U8 r2,I8 d2,I8 ip)
{
I8 i,last_cnt=tempi->ic_cnt;
BoolU4 copy_from_rbx;
switch (t1>>4) {
case TY_REG>>4:
if (t2&TY_MASK==TY_IMM) {
if (!d2)
IcZero(tempi,r1);
else if (d2>=0 && d2<=MAX_U1) {
IcZero(tempi,r1);
if (r1>7)
IcU3(tempi,d2<<16+(0xB0+r1&7)<<8+0x41);
else
IcU3(tempi,d2<<16+(0xB0+r1)<<8+0x40);
} else if (MIN_I1<=d2<=MAX_I1) {
if (r1>7) {
r1&=7;
IcU3(tempi,d2<<16+(0xB0+r1)<<8+0x41);
IcU4(tempi,0xC0BE0F4D+r1<<24+r1<<27);
} else {
IcU3(tempi,d2<<16+(0xB0+r1)<<8+0x40);
IcU4(tempi,0xC0BE0F48+r1<<24+r1<<27);
}
} else if (MIN_I4<=d2<=MAX_I4) {
if (r1>7) {
r1&=7;
IcU2(tempi,(0xB8+r1)<<8+0x41);
IcU4(tempi,d2);
IcU3(tempi,0xC0634D+r1<<16+r1<<19);
} else {
IcU2(tempi,(0xB8+r1)<<8+0x40);
IcU4(tempi,d2);
IcU3(tempi,0xC06348+r1<<16+r1<<19);
}
} else if (d2>=0 && d2<=MAX_I4) {
IcZero(tempi,r1);
if (r1>7) {
IcU2(tempi,(0xB8+r1&7)<<8+0x41);
IcU4(tempi,d2);
} else {
IcU2(tempi,(0xB8+r1)<<8+0x40);
IcU4(tempi,d2);
}
} else {
i=0xB848;
if (r1>7) {
i++;
r1&=7;
}
IcU2(tempi,i+r1<<8);
IcU8(tempi,d2);
}
} else if (t2&TY_MASK==TY_STK)
IcPop(tempi,t1,r1,d1,ip);
else {
if (r1==r2) {
if (t2&TY_MASK==TY_REG)
if (t2&IT_MASK>=IT_I8)
return;
else
if (GetOpt(OPTf_IGNORE_OVERFLOW))
return;
}
if (t2&TY_MASK==TY_REG) {
if (GetOpt(OPTf_IGNORE_OVERFLOW))
t2=TY_REG+IT_I8;
if (t1&TY_MASK==TY_REG) {
i=tempi->ic_cnt;
if (tempi->ic_last_cnt==i-3 && i>=3) {
if (tempi->ic_body[i-2]==0x8B)
if (tempi->ic_body[i-1]==0xC0+(r1&7)+(r2&7)<<3)
if (tempi->ic_body[i-3]==0x48+((r2>7)?4:0)+((r1>7)?1:0) )
return;
}
}
}
i=IcModr(r1,t2,r2,d2);
if (t2&IT_MASK==IT_U4) {
if (r1!=r2) {
IcZero(tempi,r1);
copy_from_rbx=FALSE;
} else {
IcZero(tempi,CREG_RBX);
copy_from_rbx=TRUE;
i=IcModr(CREG_RBX,t2,r2,d2);
}
} else
i|=0x4800;
IcRex(tempi,i.u1[1]);
switch (t2&IT_MASK) {
case IT_I1:
IcU3(tempi,i.u1[2]<<16+0xBE0F);
break;
case IT_I2:
IcU3(tempi,i.u1[2]<<16+0xBF0F);
break;
case IT_I4:
IcU2(tempi,i.u1[2]<<8+0x63);
break;
case IT_U1:
IcU3(tempi,i.u1[2]<<16+0xB60F);
break;
case IT_U2:
IcU3(tempi,i.u1[2]<<16+0xB70F);
break;
case IT_U4:
IcU2(tempi,i.u1[2]<<8+0x8B);
if (i.u1[0]==1)
IcU1(tempi,d2);
else if (i.u1[0]==2)
IcU4(tempi,d2);
else if (i.u1[0]==4) {
IcU4(tempi,d2-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
if (copy_from_rbx) {
if (r1>7)
IcU3(tempi,0xC38B4C+(r1&7)<<19);
else
IcU3(tempi,0xC38B48+r1<<19);
}
i=0; // no further disp
break;
default:
IcU2(tempi,i.u1[2]<<8+0x8B);
break;
}
if (i.u1[0]==1)
IcU1(tempi,d2);
else if (i.u1[0]==2)
IcU4(tempi,d2);
else if (i.u1[0]==4) {
IcU4(tempi,d2-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
}
break;
case TY_STK>>4:
if (t1&IT_MASK<t2&IT_MASK)
IcPush(tempi,t2&TY_MASK+t1&IT_MASK,r2,d2,ip);
else
IcPush(tempi,t2,r2,d2,ip);
break;
case TY_DISP>>4:
case TY_RIP_DISP32>>4:
if (t2&TY_MASK==TY_IMM &&
(t1&IT_MASK<IT_I8 || (MIN_I4<=d2<=MAX_I4))) {
i=IcModr(0,t1,r1,d1);
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xC6);
break;
case IT_U2:
case IT_I2:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xC7);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xC7);
break;
}
if (i.u1[0]==1)
IcU1(tempi,d1);
else if (i.u1[0]==2)
IcU4(tempi,d1);
else if (i.u1[0]==4) {
i=d1-(ip+tempi->ic_cnt+4);
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
i--;
break;
case IT_I2:
case IT_U2:
i-=2;
break;
default:
i-=4;
}
IcU4(tempi,i);
tempi->ic_flags&=~ICF_CODE_FINAL;
}
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
IcU1(tempi,d2);
break;
case IT_I2:
case IT_U2:
IcU2(tempi,d2);
break;
default:
IcU4(tempi,d2);
break;
}
} else {
if (t2&TY_MASK==TY_REG)
IcSlashOp(tempi,t1,r1,d1,r2+SLASH_OP_MOV,ip);
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t2,r2,d2,ip);
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RBX,0,ip);
}
}
break;
}
tempi->ic_last_cnt=last_cnt;
}
void IcLea(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,U8 t2,U8 r2,I8 d2,I8 ip)
{
I8 i;
if (t1&TY_MASK==TY_REG) {
i=IcModr(r1,t2,r2,d2);
i.u1[1]|=0x48;
IcU3(tempi,i.u1[2]<<16+0x8D00+i.u1[1]);
if (i.u1[0]==1)
IcU1(tempi,d2);
else if (i.u1[0]==2)
IcU4(tempi,d2);
else if (i.u1[0]==4) {
IcU4(tempi,d2-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
} else {
IcLea(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RCX,0,ip);
}
}
void IcDeref(IntermediateCode *tempi,I8 ip)
{
I8 t;
t=tempi->r.type&IT_MASK;
if (t>tempi->p1.ptype)
t=tempi->p1.ptype;
if (tempi->p1.type&TY_MASK==TY_REG)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_DISP+t,tempi->p1.reg,tempi->p1.disp,ip);
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_DISP+t,CREG_RCX,0,ip);
}
}
void IcAddEct(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,U8 op,I8 ip)
{
I8 i=0x48;
if (t2&TY_MASK==TY_DISP &&
t2&IT_MASK>=IT_I8 &&
r2!=CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
if (r2>7) {
i++;
r2&=7;
}
if (!d2) {
IcU3(tempi,0x000000+i+r2<<16+op<<8);
} else if (MIN_I1<=d2<=MAX_I1) {
IcU3(tempi,0x400000+i+r2<<16+op<<8);
IcU1(tempi,d2);
} else {
IcU3(tempi,0x800000+i+r2<<16+op<<8);
IcU4(tempi,d2);
}
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
r2=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
if (t2&TY_MASK!=TY_REG || t2&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
r2=CREG_RCX;
}
}
if (r2>7) {
i++;
r2&=7;
}
IcU3(tempi,0xC00000+i+r2<<16+op<<8);
}
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcAddConst(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,I8 disp,U8 op,I8 ip)
{
I8 i,r;
if (op.u1[0]==0x2B) {
op=0x0003;
disp=-disp;
}
if (t1&TY_MASK==TY_REG) {
if (t2&TY_MASK!=TY_REG) {
IcMov(tempi,t1,r1,d1,t2,r2,d2,ip);
t2=t1;
r2=r1;
d2=d1;
}
if (r1==r2) {
if (r1>7)
i=0x49;
else
i=0x48;
if (!disp &&
(op.u1[0]==0x03||op.u1[0]==0x2B||
op.u1[0]==0x33||op.u1[0]==0x0B))
return;
else if (disp==1 && op.u1[0]==0x03) {
IcU3(tempi,0xC0FF00+op.u1[1]<<19+i+(r1&7)<<16);
return;
} else if (disp==-1 && op.u1[0]==0x03) {
IcU3(tempi,0xC8FF00+i+(r1&7)<<16);
return;
} else if (MIN_I1<=disp<=MAX_I1) {
IcU3(tempi,0xC08300+op.u1[1]<<19+i+(r1&7)<<16);
IcU1(tempi,disp);
return;
} else if (MIN_I4<=disp<=MAX_I4) {
IcU3(tempi,0xC08100+op.u1[1]<<19+i+(r1&7)<<16);
IcU4(tempi,disp);
return;
}
}
if (op.u1[0]==0x03 && MIN_I4<=disp<=MAX_I4 &&
!Bt(&non_ptr_vars_mask,r2)) {
i=IcModr(r1,TY_DISP+IT_I8,r2,disp);
i.u1[1]|=0x48;
IcU3(tempi,i.u1[2]<<16+0x8D00+i.u1[1]);
if (i.u1[0]==1)
IcU1(tempi,disp);
else if (i.u1[0]==2)
IcU4(tempi,disp);
else if (i.u1[0]==4) {
IcU4(tempi,disp-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
return;
}
}
switch (t1>>4) {
case TY_REG>>4:
case TY_DISP>>4:
case TY_RIP_DISP32>>4:
if (t1!=t2 || r1!=r2 || d1!=d2) {
IcMov(tempi,t1,r1,d1,t2,r2,d2,ip);
t2=t1;
r2=r1;
d2=d1;
}
if (!disp &&
(op.u1[0]==0x03||op.u1[0]==0x2B||
op.u1[0]==0x33||op.u1[0]==0x0B))
return;
r=op.u1[1];
if (op.u1[0]==0x03 && disp==-1)
r=1;
if (op.u1[0]==0x03 && (disp==1 || disp==-1)) {
i=IcModr(r,t1,r1,d1);
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xFE);
break;
case IT_I2:
case IT_U2:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xFF);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xFF);
break;
}
if (i.u1[0]==1)
IcU1(tempi,d1);
else if (i.u1[0]==2)
IcU4(tempi,d1);
else if (i.u1[0]==4) {
IcU4(tempi,d1-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
return;
}
if (MIN_I1<=disp<=MAX_I1 ||
t1&IT_MASK==IT_I1 ||
t1&IT_MASK==IT_U1) {
i=IcModr(r,t1,r1,d1);
switch (t1&IT_MASK) {
case IT_I1:
case IT_U1:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x80);
break;
case IT_I1:
case IT_U1:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x83);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x83);
break;
}
if (i.u1[0]==1)
IcU1(tempi,d1);
else if (i.u1[0]==2)
IcU4(tempi,d1);
else if (i.u1[0]==4) {
IcU4(tempi,d1-(ip+tempi->ic_cnt+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,disp);
return;
}
if (MIN_I4<=disp<=MAX_I4 ||
t1&IT_MASK<IT_I8) {
i=IcModr(r,t1,r1,d1);
switch (t1&IT_MASK) {
case IT_I2:
case IT_U2:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x81);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x81);
}
if (i.u1[0]==1)
IcU1(tempi,d1);
else if (i.u1[0]==2)
IcU4(tempi,d1);
else if (i.u1[0]==4) {
if (t1&IT_MASK==IT_U2 ||
t1&IT_MASK==IT_I2)
IcU4(tempi,d1-(ip+tempi->ic_cnt+6));
else
IcU4(tempi,d1-(ip+tempi->ic_cnt+8));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
if (t1&IT_MASK==IT_U2 ||
t1&IT_MASK==IT_I2)
IcU2(tempi,disp);
else
IcU4(tempi,disp);
return;
}
break;
case TY_STK>>4:
IcAddConst(tempi,TY_REG+IT_I8,CREG_RAX,0,t2,r2,d2,disp,op,ip);
IcPushRegs(tempi,1<<CREG_RAX);
return;
}
IcAddEct(tempi,t1,r1,d1,TY_IMM+IT_I8,0,disp,t2,r2,d2,op.u1[0],ip);
}
void IcSubEct(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,U8 op,I8 ip)
{
I8 i=0x48;
if (t3&TY_MASK==TY_DISP &&
t3&IT_MASK>=IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
if (r3>7) {
i++;
r3&=7;
}
if (!d3)
IcU3(tempi,0x080000+i+r3<<16+op<<8);
else if (MIN_I1<=d3<=MAX_I1) {
IcU3(tempi,0x480000+i+r3<<16+op<<8);
IcU1(tempi,d3);
} else {
IcU3(tempi,0x880000+i+r3<<16+op<<8);
IcU4(tempi,d3);
}
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
if (t3&TY_MASK!=TY_REG || t3&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
r3=CREG_RAX;
}
} else {
if (t3&TY_MASK!=TY_REG || t3&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
r3=CREG_RAX;
}
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
}
if (r3>7) {
i++;
r3&=7;
}
IcU3(tempi,0xC80000+i+r3<<16+op<<8);
}
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RCX,0,ip);
}
void IcMul(IntermediateCode *tempi,I8 ip)
{
I8 i,r2,r=CREG_RAX,j;
IcParam *p1,*p2;
if (tempi->p1.type&TY_MASK==TY_IMM) {
p1=&tempi->p2;
p2=&tempi->p1;
tempi->ic_flags|=ICF_P1_FIRST;
} else {
p1=&tempi->p1;
p2=&tempi->p2;
}
i=p2->disp;
if (!(tempi->ic_class->sub_type&1) &&
p2->type&TY_MASK==TY_IMM && MIN_I4<=i<=MAX_I4) {
if (tempi->r.type==TY_REG+IT_I8) {
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,p1->type,p1->reg,p1->disp,ip);
r=tempi->r.reg;
} else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p1->type,p1->reg,p1->disp,ip);
if (r>7)
j=0xC0004D;
else
j=0xC00048;
if (MIN_I1<=i<=MAX_I1)
IcU4(tempi,i<<24+0x6B00+j+(r&7)<<16+(r&7)<<19);
else {
IcU3(tempi,0x6900+j+(r&7)<<16+(r&7)<<19);
IcU4(tempi,i);
}
} else {
if (tempi->ic_class->sub_type&1)
i=0xE0F748;
else
i=0xE8F748;
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip);
r2=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p2->type,p2->reg,p2->disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p2->type,p2->reg,p2->disp,ip);
if (p1->type&TY_MASK!=TY_REG ||
p1->type&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip);
r2=CREG_RCX;
} else
r2=p1->reg;
}
if (r2>7) {
i++;
r2&=7;
}
IcU3(tempi,i+r2<<16);
}
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,r,0,ip);
}
void IcMulEqual(IntermediateCode *tempi,I8 ip)
{
I8 i=tempi->p2.disp,r=CREG_RAX,j;
if (!(tempi->ic_class->sub_type&1) &&
tempi->p2.type&TY_MASK==TY_IMM && MIN_I4<=i<=MAX_I4) {
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->p1.type==TY_REG+IT_I8)
r=tempi->p1.reg;
else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
if (r>7)
j=0xC0004D;
else
j=0xC00048;
if (MIN_I1<=i<=MAX_I1)
IcU4(tempi,i<<24+0x6B00+j+(r&7)<<16+(r&7)<<19);
else {
IcU3(tempi,0x6900+j+(r&7)<<16+(r&7)<<19);
IcU4(tempi,i);
}
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,r,0,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+tempi->p1.ptype,CREG_RCX,0,ip);
r=CREG_RBX;
if (MIN_I1<=i<=MAX_I1)
IcU4(tempi,i<<24+0xDB6B48);
else {
IcU3(tempi,0xDB6948);
IcU4(tempi,i);
}
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RCX,0,TY_REG+IT_I8,CREG_RBX,0,ip);
}
} else {
if (tempi->ic_class->sub_type&1)
i=0xE3F748;
else
i=0xEBF748;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
}
IcU3(tempi,i);
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+tempi->p1.ptype,CREG_RCX,0,ip);
IcU3(tempi,i);
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RCX,0,TY_REG+IT_I8,CREG_RAX,0,ip);
}
}
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,r,0,ip);
}
void IcDiv(IntermediateCode *tempi,I8 ip)
{
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
if (tempi->ic_class->sub_type&1) {
IcZero(tempi,CREG_RDX);
IcU3(tempi,0xF1F748);
} else {
IcU2(tempi,0x9948);
IcU3(tempi,0xF9F748);
}
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcDivEqual(IntermediateCode *tempi,BoolU4 is_mod,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
}
if (tempi->ic_class->sub_type&1) {
IcZero(tempi,CREG_RDX);
IcU3(tempi,0xF1F748);
} else {
IcU2(tempi,0x9948);
IcU3(tempi,0xF9F748);
}
if (is_mod)
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RDX,0,ip);
else
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcU3(tempi,0xD98748); //xchg bx,cx
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
//dangerous might trash RBX in Mov, but it doesn't
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,TY_DISP+tempi->p1.ptype,CREG_RBX,0,ip);
if (tempi->ic_class->sub_type&1) {
IcZero(tempi,CREG_RDX);
IcU3(tempi,0xF1F748);
} else {
IcU2(tempi,0x9948);
IcU3(tempi,0xF9F748);
}
if (is_mod)
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RBX,0,TY_REG+IT_I8,CREG_RDX,0,ip);
else
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RBX,0,TY_REG+IT_I8,CREG_RAX,0,ip);
}
if (tempi->r.type&TY_MASK) {
if (is_mod)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RDX,0,ip);
else
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
}
void IcMod(IntermediateCode *tempi,I8 ip)
{
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
if (tempi->ic_class->sub_type&1) {
IcZero(tempi,CREG_RDX);
IcU3(tempi,0xF1F748);
} else {
IcU2(tempi,0x9948);
IcU3(tempi,0xF9F748);
}
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RDX,0,ip);
}
void IcAddSubEctEqual(IntermediateCode *tempi,U8 ptype,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,U8 op,I8 ip)
{
BoolU4 done;
I8 result_reg,i;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (t3&TY_MASK==TY_IMM) {
IcAddConst(tempi,
t2,r2,d2,t2,r2,d2,d3,op,ip);
if (t1&TY_MASK)
IcMov(tempi,t1,r1,d1,t2,r2,d2,ip);
return;
} else {
done=FALSE;
if (ptype>=IT_I8 && t3&IT_MASK>=IT_I8) {
if (t3&TY_MASK==TY_REG ||
t3&TY_MASK==TY_DISP ||
t3&TY_MASK==TY_RIP_DISP32) {
if (t2&TY_MASK==TY_REG)
result_reg=r2;
else {
result_reg=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2&TY_MASK+ptype,r2,d2,ip);
}
i=IcModr(result_reg,t3&TY_MASK+ptype,r3,d3);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op.u1[0]);
if (i.u1[0]==1)
IcU1(tempi,d3);
else if (i.u1[0]==2)
IcU4(tempi,d3);
else if (i.u1[0]==4) {
IcU4(tempi,d3-(ip+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcMov(tempi,t2&TY_MASK+ptype,r2,d2,TY_REG+IT_I8,result_reg,0,ip);
done=TRUE;
}
}
if (!done) {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (t2&TY_MASK==TY_REG && r2!=CREG_RAX) {
result_reg=r2;
if (!GetOpt(OPTf_IGNORE_OVERFLOW))
IcMov(tempi,TY_REG+IT_I8,result_reg,0,
TY_REG+ptype,result_reg,0,ip);
} else {
result_reg=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2&TY_MASK+ptype,r2,d2,ip);
}
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
if (t2&TY_MASK==TY_REG && r2!=CREG_RAX) {
result_reg=r2;
if (!GetOpt(OPTf_IGNORE_OVERFLOW))
IcMov(tempi,TY_REG+IT_I8,result_reg,0,
TY_REG+ptype,result_reg,0,ip);
} else {
result_reg=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2&TY_MASK+ptype,r2,d2,ip);
}
}
if (result_reg>7)
IcU1(tempi,0x4C);
else
IcU1(tempi,0x48);
IcU2(tempi,0xC000+op.u1[0]+(result_reg&7)<<11);
IcMov(tempi,t2&TY_MASK+ptype,r2,d2,TY_REG+IT_I8,result_reg,0,ip);
}
}
} else {
done=FALSE;
if (t3&TY_MASK==TY_IMM && op.u1[2]) {
if (op.u1[2]==0x24) {//and
i=~d3;
if (!i.u4[1]) {
if (tempi->ic_flags&ICF_NO_DEPEND_RESULT &&
t2&TY_MASK==TY_REG && 0>d3>=MIN_I1) {
IcSlashOp(tempi,TY_DISP+ptype,r2,0,0x838000+op.u1[4],ip);
IcU1(tempi,d3);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,TY_DISP+ptype,CREG_RCX,0,ip);
result_reg=CREG_RAX;
if (i.u2[1]) {
IcU2(tempi,op.u1[3]<<8+0x40);
IcU4(tempi,d3);
} else if (i.u1[1]) {
IcU3(tempi,op.u1[3]<<16+0x4066);
IcU2(tempi,d3);
} else {
IcU2(tempi,op.u1[2]<<8+0x40);
IcU1(tempi,d3);
}
IcMov(tempi,TY_DISP+ptype,CREG_RCX,0,TY_REG+IT_I8,result_reg,0,ip);
}
done=TRUE;
}
} else if (!d3.u4[1]) { //xor or
if (tempi->ic_flags&ICF_NO_DEPEND_RESULT &&
t2&TY_MASK==TY_REG && d3><(U8)<=MAX_I1) {
IcSlashOp(tempi,TY_DISP+ptype,r2,0,0x838000+op.u1[4],ip);
IcU1(tempi,d3);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,TY_DISP+ptype,CREG_RCX,0,ip);
result_reg=CREG_RAX;
if (d3.u2[1]) {
IcU2(tempi,op.u1[3]<<8+0x40);
IcU4(tempi,d3);
} else if (d3.u1[1]) {
IcU3(tempi,op.u1[3]<<16+0x4066);
IcU2(tempi,d3);
} else {
IcU2(tempi,op.u1[2]<<8+0x40);
IcU1(tempi,d3);
}
IcMov(tempi,TY_DISP+ptype,CREG_RCX,0,TY_REG+IT_I8,result_reg,0,ip);
}
done=TRUE;
}
}
if (!done) {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
}
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+ptype,CREG_RCX,0,ip);
result_reg=CREG_RBX;
IcU1(tempi,0x48);
IcU2(tempi,0xC000+op.u1[0]+(result_reg&7)<<11);
IcMov(tempi,TY_DISP+ptype,CREG_RCX,0,TY_REG+IT_I8,result_reg,0,ip);
}
}
if (t1&TY_MASK)
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,result_reg,0,ip);
}
void IcShift(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,U8 us,U8 is,I8 ip)
{
if (tempi->ic_class->sub_type&1 || tempi->ic_flags & ICF_USE_UNSIGNED)
is=us;
if (t3&TY_MASK==TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t2,r2,d2,ip);
IcU3(tempi,0x00C148+is<<16);
IcU1(tempi,d3);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t2,r2,d2,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t2,r2,d2,ip);
}
IcU3(tempi,0x00D348+is<<16);
}
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcShiftEqual(IntermediateCode *tempi,U8 ptype,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,U8 us,U8 is,I8 ip)
{
I8 result_reg;
if (tempi->ic_class->sub_type&1 || tempi->ic_flags & ICF_USE_UNSIGNED)
is=us;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (t2&TY_MASK==TY_REG) {
result_reg=r2;
if (!GetOpt(OPTf_IGNORE_OVERFLOW))
IcMov(tempi,TY_REG+IT_I8,result_reg,0,
TY_REG+ptype,result_reg,0,ip);
} else {
result_reg=CREG_RAX;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t2&TY_MASK+ptype,r2,d2,ip);
}
if (t3&TY_MASK!=TY_IMM)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
} else {
if (t3&TY_MASK!=TY_IMM)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
if (t2&TY_MASK==TY_REG) {
result_reg=r2;
if (!GetOpt(OPTf_IGNORE_OVERFLOW))
IcMov(tempi,TY_REG+IT_I8,result_reg,0,
TY_REG+ptype,result_reg,0,ip);
} else {
result_reg=CREG_RAX;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t2&TY_MASK+ptype,r2,d2,ip);
}
}
if (result_reg>7)
IcU1(tempi,0x49);
else
IcU1(tempi,0x48);
if (t3&TY_MASK==TY_IMM) {
IcU2(tempi,0x00C1+(is+result_reg&7)<<8);
IcU1(tempi,d3);
} else
IcU2(tempi,0x00D3+(is+result_reg&7)<<8);
IcMov(tempi,t2&TY_MASK+ptype,r2,d2,TY_REG+IT_I8,result_reg,0,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,t2,r2,d2,ip);
if (t3&TY_MASK!=TY_IMM)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
} else {
if (t3&TY_MASK!=TY_IMM)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t3,r3,d3,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,t2,r2,d2,ip);
}
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,TY_DISP+ptype,CREG_RDX,0,ip);
result_reg=CREG_RAX;
IcU1(tempi,0x48);
if (t3&TY_MASK==TY_IMM) {
IcU2(tempi,0x00C1+(is+result_reg&7)<<8);
IcU1(tempi,d3);
} else
IcU2(tempi,0x00D3+(is+result_reg&7)<<8);
IcMov(tempi,TY_DISP+ptype,CREG_RDX,0,TY_REG+IT_I8,result_reg,0,ip);
}
if (t1&TY_MASK)
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,result_reg,0,ip);
}
void IcUnaries(IntermediateCode *tempi,U8 op,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcSlashOp(tempi,TY_REG+IT_I8,CREG_RAX,0,op,ip);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcNot(IntermediateCode *tempi,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcZero(tempi,CREG_RAX);
IcOr(tempi,CREG_RBX);
IcU2(tempi,0x0375);
IcU3(tempi,0xC0FF48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_U8,CREG_RAX,0,ip);
}
void IcAndAnd(IntermediateCode *tempi,I8 ip)
{
I8 i=0x48,r2;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW) ||
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW) ||
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
}
IcZero(tempi,CREG_RAX);
IcOr(tempi,r2);
IcU2(tempi,0x0874);
IcOr(tempi,CREG_RCX);
IcU2(tempi,0x0374);
IcU3(tempi,0xC0FF48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcOrOr(IntermediateCode *tempi,I8 ip)
{
I8 i=0x48,r2;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW) ||
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW) ||
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
}
if (r2>7) {
i++;
r2&=7;
}
IcZero(tempi,CREG_RAX);
IcU3(tempi,0xC80B00+i+r2<<16);
IcU2(tempi,0x0374);
IcU3(tempi,0xC0FF48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcXorXor(IntermediateCode *tempi,I8 ip)
{
I8 i=0x48,r2;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW)) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW)) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
}
IcZero(tempi,CREG_RBX);
IcOr(tempi,r2);
IcU2(tempi,0x0374);
IcU3(tempi,0xC3FF48);
IcZero(tempi,CREG_RAX);
IcOr(tempi,CREG_RCX);
IcU2(tempi,0x0374);
IcU3(tempi,0xC0FF48);
IcU3(tempi,0xC33348);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcColon(IntermediateCode *tempi,I8 ip)
{
I8 i=0x48,r2;
if (tempi->p1.type&TY_MASK==TY_REG &&
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else if (tempi->p2.type&TY_MASK==TY_REG &&
tempi->p2.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip);
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8 &&
!GetOpt(OPTf_IGNORE_OVERFLOW)) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->p1.type&TY_MASK!=TY_REG ||
tempi->p1.type&IT_MASK<IT_I8) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r2=CREG_RDX;
} else
r2=tempi->p1.reg;
}
IcOr(tempi,r2);
IcU2(tempi,0x0374);
IcU3(tempi,0xC18B48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcCmp(IntermediateCode *tempi,U8 us,U8 is,I8 ip)
{
I8 r1,d1,r2,i=0x48,j=tempi->p2.disp;
if (tempi->p2.type&TY_MASK==TY_IMM && MIN_I4<=j<=MAX_I4) {
if (!(tempi->ic_flags&(ICF_POP_CMP|ICF_PUSH_CMP|ICF_RCX_CMP|ICF_RCX_CMP2)) &&
tempi->p1.type&TY_MASK==TY_DISP &&
tempi->p1.type&IT_MASK>=IT_I8 && tempi->p1.reg!=CREG_RAX) {
r1=tempi->p1.reg;
d1=tempi->p1.disp;
IcZero(tempi,CREG_RAX);
if (r1>7)
i++;
if (MIN_I1<=j<=MAX_I1)
i+=0x388300;
else
i+=0x388100;
if (!d1) {
IcU3(tempi,0x000000+i+(r1&7)<<16);
} else if (MIN_I1<=d1<=MAX_I1) {
IcU3(tempi,0x400000+i+(r1&7)<<16);
IcU1(tempi,d1);
} else {
IcU3(tempi,0x800000+i+(r1&7)<<16);
IcU4(tempi,d1);
}
if (MIN_I1<=j<=MAX_I1)
IcU1(tempi,j);
else
IcU4(tempi,j);
} else {
if (tempi->ic_flags & ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RCX);
r1=CREG_RCX;
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r1=CREG_RCX;
}
}
IcZero(tempi,CREG_RAX);
if (r1>7)
i++;
if (MIN_I1<=j<=MAX_I1) {
IcU3(tempi,0xF88300+i+(r1&7)<<16);
IcU1(tempi,j);
} else {
IcU3(tempi,0xF88100+i+(r1&7)<<16);
IcU4(tempi,j);
}
}
if (tempi->ic_flags & ICF_PUSH_CMP)
IcPush(tempi,TY_IMM+IT_I8,0,j,ip);
if (tempi->ic_class->sub_type&1 || tempi->ic_flags & ICF_USE_UNSIGNED)
is=us;
IcU2(tempi,0x300+is);
IcU3(tempi,0xC0FF48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->ic_flags & ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RCX);
r1=CREG_RCX;
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r1=CREG_RCX;
}
}
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
r2=CREG_RBX;
}
} else {
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
r2=CREG_RCX;
}
if (tempi->ic_flags & ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RBX);
r1=CREG_RBX;
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r1=CREG_RBX;
}
}
}
IcZero(tempi,CREG_RAX);
if (r2>7)
i++;
if (r1>7)
i+=4;
if (tempi->ic_flags & ICF_PUSH_CMP)
IcPushRegs(tempi,1<<r2);
IcU3(tempi,0xC03B00+i+(r2&7)<<16+(r1&7)<<19);
if (tempi->ic_class->sub_type&1 || tempi->ic_flags & ICF_USE_UNSIGNED)
is=us;
IcU2(tempi,0x300+is);
IcU3(tempi,0xC0FF48);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
}
void IcBitOps(IntermediateCode *tempi,U8 op,U8 op_imm,BoolU4 locked,I8 ip)
{
IntermediateCode *tempi2=tempi+sizeof(IntermediateCode);
I8 r1=0,r2,i=0x48;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else if (tempi->p1.type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r1=CREG_RCX;
}
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
r2=CREG_RBX;
}
} else {
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
r2=CREG_RCX;
}
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else if (tempi->p1.type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r1=CREG_RBX;
}
}
if (!(tempi2->ic_flags&ICF_NO_DEPEND_RESULT))
IcZero(tempi,CREG_RAX);
if (r2>7) {
i++;
r2&=7;
}
if (r1>7) {
i+=4;
r1&=7;
}
if (locked) {
if (op!=0xA30F)
IcU1(tempi,0xF0);
}
IcU1(tempi,i);
if (tempi->p1.type&TY_MASK==TY_IMM) {
IcU3(tempi,0x000000+op_imm+r2<<16);
IcU1(tempi,tempi->p1.disp);
} else
IcU3(tempi,0x000000+op+r2<<16+r1<<19);
if (!(tempi2->ic_flags&ICF_NO_DEPEND_RESULT))
IcU4(tempi,0x00D08348);
}
void IcPreempt(IntermediateCode *tempi,I8 ip)
{
IntermediateCode *tempi2=tempi+sizeof(IntermediateCode);
if (tempi->p1.type&TY_MASK==TY_IMM) {
IcZero(tempi,CREG_RBX);
IcU4(tempi,0x1B8B4864);
if (!(tempi2->ic_flags&ICF_NO_DEPEND_RESULT))
IcZero(tempi,CREG_RAX);
if (tempi->p1.disp)
IcU3(tempi,0x6BBA0F);
else
IcU3(tempi,0x73BA0F);
IcU2(tempi,TSS_TASK_FLAGS+TSSf_PREEMPT<<8);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
if (!(tempi2->ic_flags&ICF_NO_DEPEND_RESULT))
IcZero(tempi,CREG_RAX);
IcZero(tempi,CREG_RBX);
IcU4(tempi,0x1B8B4864);
IcOr(tempi,CREG_RCX);
IcU2(tempi,0x0774);
IcU3(tempi,0x6BBA0F);
IcU2(tempi,TSS_TASK_FLAGS+TSSf_PREEMPT<<8);
IcU2(tempi,0x05EB);
IcU3(tempi,0x73BA0F);
IcU2(tempi,TSS_TASK_FLAGS+TSSf_PREEMPT<<8);
}
if (!(tempi2->ic_flags&ICF_NO_DEPEND_RESULT))
IcU4(tempi,0x00D08348);
}
void IcPreIncDec(IntermediateCode *tempi,U8 op,I8 ip)
{
I8 r;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
IcSlashOp(tempi,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,op,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
} else {
if (tempi->p1.type&TY_MASK==TY_REG)
r=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r=CREG_RCX;
}
IcSlashOp(tempi,
TY_DISP+tempi->p1.ptype,r,0,op,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_DISP+tempi->p1.ptype,r,0,ip);
}
}
void IcPostIncDec(IntermediateCode *tempi,U8 op,I8 ip)
{
I8 r;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->r.type&TY_MASK) {
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
}
IcSlashOp(tempi,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,op,ip);
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
!(tempi->r.type&TY_MASK==TY_REG && tempi->r.reg==tempi->p1.reg))
r=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
r=CREG_RCX;
}
if (tempi->r.type&TY_MASK) {
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_DISP+tempi->p1.ptype,r,0,ip);
}
IcSlashOp(tempi,
TY_DISP+tempi->p1.ptype,r,0,op,ip);
}
}
void IcCmpAndBranch(IntermediateCode *tempi,U8 ip,
U8 us,U8 is,U8 not_us,U8 not_is,
U1 *buf,I8 ip2)
{
I8 r1,d1,r2,i=0x48,j;
BoolU4 short_jmp=FALSE,done;
CbMiscStruct *lb,*lb1;
IcParam *p1=&tempi->p1,*p2=&tempi->p2,*swap;
if (tempi->ic_flags&ICF_RCX_CMP2) {
p1->type=TY_REG+IT_I8;
p1->reg=CREG_RCX;
p1->disp=0;
}
j=p1->disp;
if (p1->type&TY_MASK==TY_IMM && MIN_I4<=j<=MAX_I4) {
swap=p1; p1=p2; p2=swap;
us=not_us;
is=not_is;
}
if (tempi->ic_class->sub_type&1 || tempi->ic_flags & ICF_USE_UNSIGNED)
is=us;
j=p2->disp;
if (p2->type&TY_MASK==TY_IMM && MIN_I4<=j<=MAX_I4) {
if (!(tempi->ic_flags&(ICF_POP_CMP|ICF_PUSH_CMP|ICF_RCX_CMP|ICF_RCX_CMP2)) &&
p1->type&TY_MASK==TY_DISP &&
p1->type&IT_MASK>=IT_I8) {
r1=p1->reg;
d1=p1->disp;
if (r1>7) {
i++;
r1&=7;
}
if (MIN_I1<=j<=MAX_I1)
i+=0x388300;
else
i+=0x388100;
if (!d1) {
IcU3(tempi,0x000000+i+r1<<16);
} else if (MIN_I1<=d1<=MAX_I1) {
IcU3(tempi,0x400000+i+r1<<16);
IcU1(tempi,d1);
} else {
IcU3(tempi,0x800000+i+r1<<16);
IcU4(tempi,d1);
}
if (MIN_I1<=j<=MAX_I1)
IcU1(tempi,j);
else
IcU4(tempi,j);
} else {
if (tempi->ic_flags&ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RBX);
r1=CREG_RBX;
} else {
if (p1->type&TY_MASK==TY_REG &&
(p1->type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)))
r1=p1->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p1->type,p1->reg,p1->disp,ip2);
r1=CREG_RBX;
}
}
if (!j) {
if (is.u1[2]==0x7C) {
IcOr(tempi,r1);
is=0x78880F;
} else if (is.u1[2]==0x7D) {
IcOr(tempi,r1);
is=0x79890F;
} else if (is.u1[2]==0x74 || is.u1[2]==0x75)
IcOr(tempi,r1);
else {
if (r1>7)
i++;
IcU3(tempi,0xF88300+i+(r1&7)<<16);
IcU1(tempi,j);
}
} else {
if (r1>7)
i++;
if (MIN_I1<=j<=MAX_I1) {
IcU3(tempi,0xF88300+i+(r1&7)<<16);
IcU1(tempi,j);
} else {
IcU3(tempi,0xF88100+i+(r1&7)<<16);
IcU4(tempi,j);
}
}
}
if (tempi->ic_flags&ICF_PUSH_CMP) {
if (!swap)
IcPush(tempi,TY_IMM+IT_I8,0,j,ip2);
else
IcPush(tempi,TY_REG+IT_I8,r1,0,ip2);
} else if (tempi->ic_flags&ICF_RCX_CMP) {
if (!swap)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,TY_IMM+IT_I8,0,j,ip2);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,TY_REG+IT_I8,r1,0,ip2);
}
} else {
done=FALSE;
if (p1->type&IT_MASK>=IT_I8 &&
p2->type&IT_MASK>=IT_I8 &&
!(tempi->ic_flags&ICF_POP_CMP)) {
if (p1->type&TY_MASK==TY_REG &&
!(tempi->ic_flags&(ICF_PUSH_CMP|ICF_RCX_CMP)) &&
(p2->type&TY_MASK==TY_DISP ||
p2->type&TY_MASK==TY_RIP_DISP32)) {
i=IcModr(p1->reg,p2->type,p2->reg,p2->disp);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x3B);
if (i.u1[0]==1)
IcU1(tempi,p2->disp);
else if (i.u1[0]==2)
IcU4(tempi,p2->disp);
else if (i.u1[0]==4) {
IcU4(tempi,p2->disp-(ip2+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
done=TRUE;
} else if (p2->type&TY_MASK==TY_REG &&
(p1->type&TY_MASK==TY_REG ||
p1->type&TY_MASK==TY_DISP ||
p1->type&TY_MASK==TY_RIP_DISP32)) {
i=IcModr(p2->reg,p1->type,p1->reg,p1->disp);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x39);
if (i.u1[0]==1)
IcU1(tempi,p1->disp);
else if (i.u1[0]==2)
IcU4(tempi,p1->disp);
else if (i.u1[0]==4) {
IcU4(tempi,p1->disp-(ip2+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
if (tempi->ic_flags&ICF_PUSH_CMP)
IcPushRegs(tempi,1<<p2->reg);
else if (tempi->ic_flags&ICF_RCX_CMP)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,TY_REG+IT_I8,p2->reg,0,ip2);
done=TRUE;
}
}
if (!done) {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->ic_flags&ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RAX);
r1=CREG_RAX;
} else {
if (p1->type&TY_MASK==TY_REG &&
(p1->type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)))
r1=p1->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p1->type,p1->reg,p1->disp,ip2);
r1=CREG_RAX;
}
}
if (p2->type&TY_MASK==TY_REG &&
(p2->type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)))
r2=p2->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p2->type,p2->reg,p2->disp,ip2);
r2=CREG_RCX;
}
} else {
if (p2->type&TY_MASK==TY_REG &&
(p2->type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)))
r2=p2->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p2->type,p2->reg,p2->disp,ip2);
r2=CREG_RAX;
}
if (tempi->ic_flags&ICF_POP_CMP) {
IcPopRegs(tempi,1<<CREG_RCX);
r1=CREG_RCX;
} else {
if (p1->type&TY_MASK==TY_REG &&
(p1->type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)))
r1=p1->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip2);
r1=CREG_RCX;
}
}
}
if (r2>7)
i++;
if (r1>7)
i+=4;
IcU3(tempi,0xC03B00+i+(r2&7)<<16+(r1&7)<<19);
if (tempi->ic_flags&ICF_PUSH_CMP)
IcPushRegs(tempi,1<<r2);
else if (tempi->ic_flags&ICF_RCX_CMP)
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,TY_REG+IT_I8,r2,0,ip2);
}
}
ip+=tempi->ic_cnt;
lb=tempi->ic_data;
while (lb1=lb->forward)
lb=lb1;
if (lb->address!=INVALID_PTR) {
i=lb->address-ip;
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
if (MIN_I1+2<i<MAX_I1+2)
short_jmp=TRUE;
}
if (buf)
short_jmp=(tempi->ic_flags & ICF_SHORT_JMP) ? TRUE:FALSE;
if (short_jmp) {
tempi->ic_flags|=ICF_SHORT_JMP;
i=lb->address-(ip+2);
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
IcU2(tempi,i<<8+is.u1[2]);
} else {
tempi->ic_flags&=~ICF_SHORT_JMP;
i=lb->address-(ip+6);
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
IcU2(tempi,is.u2[0]);
IcU4(tempi,i);
}
}
void IcTestAndBranch(IntermediateCode *tempi,U8 ip,U8 is,U1 *buf,I8 ip2)
{
I8 i;
BoolU4 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (tempi->p1.type&TY_MASK!=TY_REG) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
IcOr(tempi,CREG_RAX);
} else
IcOr(tempi,tempi->p1.reg);
ip+=tempi->ic_cnt;
lb=tempi->ic_data;
while (lb1=lb->forward)
lb=lb1;
if (lb->address!=INVALID_PTR) {
i=lb->address-ip;
if (lb->flags&CBMF_POP_CMP)
i+=8;
if (MIN_I1+2<i<MAX_I1+2)
short_jmp=TRUE;
}
if (buf)
short_jmp=(tempi->ic_flags & ICF_SHORT_JMP) ? TRUE:FALSE;
if (short_jmp) {
tempi->ic_flags|=ICF_SHORT_JMP;
i=lb->address-(ip+2);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,i<<8+is.u1[2]);
} else {
tempi->ic_flags&=~ICF_SHORT_JMP;
i=lb->address-(ip+6);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,is.u2[0]);
IcU4(tempi,i);
}
}
void IcAndBranch(IntermediateCode *tempi,U8 ip,U8 is,U1 *buf,I8 ip2)
{
I8 i;
BoolU4 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
IcParam *p1,*p2;
if (tempi->p1.type&TY_MASK==TY_IMM) {
p1=&tempi->p2;
p2=&tempi->p1;
tempi->ic_flags|=ICF_P1_FIRST;
} else {
p1=&tempi->p1;
p2=&tempi->p2;
}
i=p2->disp;
if (p2->type&TY_MASK==TY_IMM && i>=0 && i<=MAX_U4) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p1->type,p1->reg,p1->disp,ip2);
if (i<=MAX_U1)
IcU2(tempi,i<<8+0x24);
else if (i<=MAX_U2)
IcU4(tempi,i<<16+0x2566);
else {
IcU1(tempi,0x25);
IcU4(tempi,i);
}
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p2->type,p2->reg,p2->disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,p2->type,p2->reg,p2->disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip2);
}
IcU3(tempi,0xC12348);
}
ip+=tempi->ic_cnt;
lb=tempi->ic_data;
while (lb1=lb->forward)
lb=lb1;
if (lb->address!=INVALID_PTR) {
i=lb->address-ip;
if (lb->flags&CBMF_POP_CMP)
i+=8;
if (MIN_I1+2<i<MAX_I1+2)
short_jmp=TRUE;
}
if (buf)
short_jmp=(tempi->ic_flags & ICF_SHORT_JMP) ? TRUE:FALSE;
if (short_jmp) {
tempi->ic_flags|=ICF_SHORT_JMP;
i=lb->address-(ip+2);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,i<<8+is.u1[2]);
} else {
tempi->ic_flags&=~ICF_SHORT_JMP;
i=lb->address-(ip+6);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,is.u2[0]);
IcU4(tempi,i);
}
}
void IcAssign(IntermediateCode *tempi,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->r.type&TY_MASK) {
if (tempi->p1.type&TY_MASK==TY_REG)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
else
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
}
} else {
if (tempi->p1.type&TY_MASK==TY_REG) {
IcMov(tempi,TY_DISP+tempi->p1.ptype,tempi->p1.reg,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RCX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
}
}
}
void IcFOp1(IntermediateCode *tempi,U8 op,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFOp2(IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFCmp(IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RDX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RDX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
}
if (tempi->ic_flags&ICF_PUSH_CMP)
IcPushRegs(tempi,1<<CREG_RAX);
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFOp2Equal(IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
}
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
TY_DISP+tempi->p1.ptype,CREG_RCX,0,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
TY_DISP+tempi->p1.ptype,CREG_RCX,0,ip);
}
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcMov(tempi,TY_DISP+tempi->p1.ptype,CREG_RCX,0,TY_REG+IT_I8,CREG_RAX,0,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
}
void IcFCmpAndBranch(IntermediateCode *tempi,U8 ip,U8 op,U1 *buf,I8 ip2)
{
I8 i;
BoolU4 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RDX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RDX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
}
if (tempi->ic_flags&ICF_PUSH_CMP)
IcPushRegs(tempi,1<<CREG_RAX);
// IcU2(tempi,op<<8+0x00CD);
IcCopyIrq(tempi,op);
IcOr(tempi,CREG_RAX);
ip+=tempi->ic_cnt;
lb=tempi->ic_data;
while (lb1=lb->forward)
lb=lb1;
if (lb->address!=INVALID_PTR) {
i=lb->address-ip;
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
if (MIN_I1+2<i<MAX_I1+2)
short_jmp=TRUE;
}
if (buf)
short_jmp=(tempi->ic_flags & ICF_SHORT_JMP) ? TRUE:FALSE;
if (short_jmp) {
tempi->ic_flags|=ICF_SHORT_JMP;
i=lb->address-(ip+2);
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
IcU2(tempi,i<<8+0x75);
} else {
tempi->ic_flags&=~ICF_SHORT_JMP;
i=lb->address-(ip+6);
if (lb->flags&CBMF_POP_CMP)
if(tempi->ic_flags&ICF_PUSH_CMP)
i+=4;
else
i+=8;
IcU2(tempi,0x850F);
IcU4(tempi,i);
}
}
void IcFPreIncDec(IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type&TY_MASK+IT_I8,tempi->p1.reg,tempi->p1.disp,ip);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
TY_DISP+IT_I8,CREG_RCX,0,ip);
IcCopyIrq(tempi,op);
IcMov(tempi,TY_DISP+IT_I8,CREG_RCX,0,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFPostIncDec(IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type&TY_MASK+IT_I8,tempi->p1.reg,tempi->p1.disp,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
TY_REG+IT_I8,CREG_RAX,0,ip);
IcCopyIrq(tempi,op);
IcMov(tempi,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
TY_DISP+IT_I8,CREG_RCX,0,ip);
if (tempi->r.type&TY_MASK)
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
TY_REG+IT_I8,CREG_RAX,0,ip);
IcCopyIrq(tempi,op);
IcMov(tempi,TY_DISP+IT_I8,CREG_RCX,0,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
if (tempi->r.type&TY_MASK)
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RDX,0,ip);
}
void IcBrBitOps(IntermediateCode *tempi,U8 ip,U8 op,U8 op_imm,U8 is,BoolU4 locked,U1 *buf,I8 ip2)
{
I8 i=0x48,r1=0,r2;
BoolU4 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else if (tempi->p1.type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RCX;
}
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RBX;
}
} else {
if (tempi->p2.type&TY_MASK==TY_REG &&
(tempi->p2.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p2.reg!=CREG_RAX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RCX;
}
if (tempi->p1.type&TY_MASK==TY_REG &&
(tempi->p1.type&IT_MASK>=IT_I8||GetOpt(OPTf_IGNORE_OVERFLOW)) &&
tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else if (tempi->p1.type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RBX;
}
}
if (r2>7) {
i++;
r2&=7;
}
if (r1>7) {
i+=4;
r1&=7;
}
if (locked) {
if (op!=0xA30F)
IcU1(tempi,0xF0);
}
IcU1(tempi,i);
if (tempi->p1.type&TY_MASK==TY_IMM) {
IcU3(tempi,0x000000+op_imm+r2<<16);
IcU1(tempi,tempi->p1.disp);
} else
IcU3(tempi,0x000000+op+r2<<16+r1<<19);
ip+=tempi->ic_cnt;
lb=tempi->ic_data;
while (lb1=lb->forward)
lb=lb1;
if (lb->address!=INVALID_PTR) {
i=lb->address-ip;
if (lb->flags&CBMF_POP_CMP)
i+=8;
if (MIN_I1+2<i<MAX_I1+2)
short_jmp=TRUE;
}
if (buf)
short_jmp=(tempi->ic_flags & ICF_SHORT_JMP) ? TRUE:FALSE;
if (short_jmp) {
tempi->ic_flags|=ICF_SHORT_JMP;
i=lb->address-(ip+2);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,i<<8+is.u1[2]);
} else {
tempi->ic_flags&=~ICF_SHORT_JMP;
i=lb->address-(ip+6);
if (lb->flags&CBMF_POP_CMP)
i+=8;
IcU2(tempi,is.u2[0]);
IcU4(tempi,i);
}
}