
$PJ,"Project: OSMain2.SPZ","/LT/OSMain2/OSMain2.SPZ"$
$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 arg and result type
specifications in the $LK,"IcArg","MN:IcArg"$. $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.
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 IcCopyTemplate(LexStruct *lx,IntermediateCode *tempi,U8 op,
BoolI1 override=FALSE,BoolI1 dont_push=FALSE,BoolI1 dont_pop=FALSE,BoolI1 alt=FALSE)
{
U1 *ptr;
I8 i=0;
if (!override) {
if (tempi->ic_flags&ICF_ALTERNATE_TEMPLATE)
alt=TRUE;
else
alt=FALSE;
dont_push=Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt);
dont_pop=Bt(&tempi->ic_flags,ICf_DONT_POP_FLOAT0+lx->float_template_cnt);
}
if (alt) {
if (dont_push) {
if (dont_pop) {
ptr=cmp_templates_dont_push_pop2[op];
i=cmp_templates_dont_push_pop2[op+1]-ptr;
} else {
ptr=cmp_templates_dont_push2[op];
i=cmp_templates_dont_push2[op+1]-ptr;
}
}
}
if (!i) {
if (dont_push) {
if (dont_pop) {
ptr=cmp_templates_dont_push_pop[op];
i=cmp_templates_dont_push_pop[op+1]-ptr;
} else {
ptr=cmp_templates_dont_push[op];
i=cmp_templates_dont_push[op+1]-ptr;
}
} else {
if (dont_pop) {
ptr=cmp_templates_dont_pop[op];
i=cmp_templates_dont_pop[op+1]-ptr;
} else {
ptr=cmp_templates[op];
i=cmp_templates[op+1]-ptr;
}
}
}
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);
if (!override) {
if (++lx->float_template_cnt>4)
Debugger("Internal Compiler Error: float template");
}
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
//result.u[3] is SIB
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;
}
switch (t2>>4) {
case TY_RIP_DISP32>>4:
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;
break;
case TY_REG>>4:
if (r2>7) {
result.u1[1]++;
r2&=7;
}
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;
break;
case TY_DISP>>4:
if (r2>7) {
result.u1[1]++;
r2&=7;
}
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;
break;
case TY_SIB>>4:
if (7<r2.u1[0]<16)
result.u1[1]++;
if (r2.u1[1]&15>7)
result.u1[1]+=2;
if (r2.u1[0]==16) {
result.u1[3]=CREG_RBP+(r2.u1[1]&7)<<3+r2.u1[1]&0xC0;
result.u1[2]=4+r<<3;
result.u1[0]=2;
} else {
result.u1[3]=r2.u1[0]&7+(r2.u1[1]&7)<<3+r2.u1[1]&0xC0;
if (!d2 && r2.u1[0]&7!=CREG_RBP) {
result.u1[2]=4+r<<3;
result.u1[0]=0;
} else if (MIN_I1<=d2<=MAX_I1) {
result.u1[2]=0x44+r<<3;
result.u1[0]=1;
} else {
result.u1[2]=0x84+r<<3;
result.u1[0]=2;
}
}
if (result.u1[1]==0x40 &&
(t2&IT_MASK>=IT_I2 ||
r<4))
result.u1[1]=0;
break;
}
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 (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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-1;
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);
IcU1(tempi,0x50+CREG_RBX);
} else {
if (r1>7)
IcU2(tempi,0x5049+(r1&7)<<8);
else
IcU1(tempi,0x50+r1);
}
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_SIB>>4:
i=0x48;
switch (t1&IT_MASK) {
case IT_I8:
case IT_U8:
case IT_DOUBLE:
if (7<r1.u1[0]<16)
i++;
if (r1.u1[1]&15>7)
i+=2;
if (r1.u1[0]==16) {
r1=CREG_RBP+(r1.u1[1]&7)<<3+r1.u1[1]&0xC0;
IcU4(tempi,0x34FF00+r1<<24+i);
IcU4(tempi,d1);
} else {
r1=r1.u1[0]&7+(r1.u1[1]&7)<<3+r1.u1[1]&0xC0;
if (!d1 && r1.u1[0]&7!=CREG_RBP)
IcU4(tempi,0x34FF00+r1<<24+i);
else if (MIN_I1<=d1<=MAX_I1) {
IcU4(tempi,0x74FF00+r1<<24+i);
IcU1(tempi,d1);
} else {
IcU4(tempi,0xB4FF00+r1<<24+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);
}
}
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
IcU1(tempi,0x50+i);
}
}
}
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
IcU1(tempi,0x58+r1);
break;
case TY_NULL>>4:
break;
default:
IcU1(tempi,0x58+CREG_RBX);
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
IcU1(tempi,0x58+i);
}
}
}
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;
BoolI1 copy_from_rbx;
switch (t1>>4) {
case TY_REG>>4:
if (t2&TY_MASK==TY_IMM) {
if (!d2)
IcZero(tempi,r1);
else if (0<=d2<=MAX_U1) {
IcZero(tempi,r1);
if (r1>7)
IcU3(tempi,d2<<16+(0xB0+r1&7)<<8+0x41);
else if (r1>3)
IcU3(tempi,d2<<16+(0xB0+r1)<<8+0x40);
else
IcU2(tempi,d2<<8+0xB0+r1);
} 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 {
IcU2(tempi,d2<<8+0xB0+r1);
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 {
IcU1(tempi,0xB8+r1);
IcU4(tempi,d2);
IcU3(tempi,0xC06348+r1<<16+r1<<19);
}
} 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 && t2&TY_MASK==TY_REG)
return;
if (t2&TY_MASK==TY_REG) {
t2=TY_REG+IT_I8;
i=tempi->ic_cnt;
if (tempi->ic_last_cnt==i-3 && i>=3 &&
tempi->ic_body[i-2]==0x8B &&
tempi->ic_body[i-1]==0xC0+r1&7+(r2&7)<<3 &&
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 {
if (r2!=CREG_RBX)
IcZero(tempi,CREG_RBX);
else
throw(EXCEPT_COMPILER,19); //internal error, fatal, out of registers
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 (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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);
}
goto done1;
default:
IcU2(tempi,i.u1[2]<<8+0x8B);
}
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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;
}
done1:
}
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:
case TY_SIB>>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);
}
if (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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);
}
} 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 (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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,temp,result_reg=CREG_RAX;
BoolI1 swap=FALSE;
if (r3!=result_reg) {
swap^=TRUE;
temp=t2; t2=t3; t3=temp;
temp=r2; r2=r3; r3=temp;
temp=d2; d2=d3; d3=temp;
}
if (t2&IT_MASK>=IT_I8 && r2!=result_reg &&
TY_REG<=t2&TY_MASK<=TY_RIP_DISP32) {
if (t1&TY_MASK==TY_REG && !(r2==r1 && TY_REG<=t2&TY_MASK<=TY_SIB))
result_reg=r1;
IcMov(tempi,TY_REG+IT_I8,result_reg,0,t3,r3,d3,ip);
i=IcModr(result_reg,t2,r2,d2);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op);
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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 {
if (t2&TY_MASK==TY_REG)
temp=r2;
else
temp=CREG_RCX;
if (t1&TY_MASK==TY_REG)
result_reg=r1;
if (temp==result_reg)
result_reg=CREG_RDX;
if (swap ^^ tempi->ic_flags & ICF_P1_FIRST) {
if (r3==temp && TY_REG<=t3&TY_MASK<=TY_SIB)
temp=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,temp,0,t2,r2,d2,ip);
IcMov(tempi,TY_REG+IT_I8,result_reg,0,t3,r3,d3,ip);
} else {
if (r2==result_reg && TY_REG<=t2&TY_MASK<=TY_SIB)
result_reg=CREG_RDX;
IcMov(tempi,TY_REG+IT_I8,result_reg,0,t3,r3,d3,ip);
IcMov(tempi,TY_REG+IT_I8,temp,0,t2,r2,d2,ip);
}
i=0x48;
if (result_reg>7)
i+=4;
if (temp>7)
i++;
IcU3(tempi,0xC00000+i+(temp&7)<<16+(result_reg&7)<<19+op<<8);
}
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,result_reg,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_SIB>>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);
}
if (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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);
}
if (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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 (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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 IcSub(IntermediateCode *tempi,U8 t1,U8 r1,I8 d1,
U8 t2,U8 r2,I8 d2,U8 t3,U8 r3,I8 d3,I8 ip)
{
I8 i=0x48,temp,op=0x2B;
BoolI1 swap=FALSE;
if (r3!=CREG_RAX) {
swap=TRUE;
temp=t2; t2=t3; t3=temp;
temp=r2; r2=r3; r3=temp;
temp=d2; d2=d3; d3=temp;
}
if (t2&IT_MASK>=IT_I8 && r2.u1[0]!=CREG_RAX && (t2&TY_MASK!=TY_SIB || r2.u1[1]&15!=CREG_RAX) &&
TY_REG<=t2&TY_MASK<=TY_RIP_DISP32) {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,t3,r3,d3,ip);
if (!swap) {
op=0x03;
IcU3(tempi,0xD8F748);
}
i=IcModr(CREG_RAX,t2,r2,d2);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op);
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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;
}
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,CREG_RAX,0,ip);
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (t3&TY_MASK!=TY_REG || t3&IT_MASK<IT_I8) {
if (swap) {
swap=FALSE;
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);
r3=CREG_RCX;
r2=CREG_RAX;
} else {
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);
r2=CREG_RCX;
r3=CREG_RAX;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
r2=CREG_RCX;
}
} else {
if (t3&TY_MASK!=TY_REG || t3&IT_MASK<IT_I8) {
if (swap) {
swap=FALSE;
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);
r2=CREG_RAX;
r3=CREG_RCX;
} 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);
r3=CREG_RAX;
r2=CREG_RCX;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
r2=CREG_RCX;
}
}
if (swap) {
op=0x03;
IcU3(tempi,0xD9F748);
}
if (r3>7)
i++;
if (r2>7)
i+=4;
IcU3(tempi,0xC00000+i+(r3&7)<<16+(r2&7)<<19+op<<8);
IcMov(tempi,t1,r1,d1,TY_REG+IT_I8,r2,0,ip);
}
}
void IcMul(IntermediateCode *tempi,I8 ip)
{
I8 i,r2,r=CREG_RAX,j;
IcArg *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,i
p);
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,i
p);
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,i
p);
}
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,BoolI1 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,i
p);
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,i
p);
}
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)
{
BoolI1 done;
I8 result_reg,temp,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) {
if (!(t1&TY_MASK) &&
TY_REG<=t2&TY_MASK<=TY_RIP_DISP32) {
if (t3&TY_MASK==TY_REG)
temp=r3;
else {
temp=CREG_RCX;
IcMov(tempi,TY_REG+IT_I8,temp,0,t3,r3,d3,ip);
}
i=IcModr(temp,t2&TY_MASK+ptype,r2,d2);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+op.u1[5]);
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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;
}
return;
}
if (t3&IT_MASK>=IT_I8 &&
TY_REG<=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,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 (t3&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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;
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;
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 (!d3.u4[1]) {
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);
done=TRUE;
} else if (op.u1[2]==0x24) { //AND
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;
IcU2(tempi,op.u1[3]<<8+0x40);
IcU4(tempi,d3);
IcMov(tempi,TY_DISP+ptype,CREG_RCX,0,TY_REG+IT_I8,result_reg,0,ip);
done=TRUE;
} else if (ptype&IT_MASK<IT_I8) { //OR/XOR
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;
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;
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)
{
I8 i;
if (tempi->p1.type&IT_MASK<=IT_U1 &&
TY_DISP<=tempi->p1.type&TY_MASK<=TY_RIP_DISP32) {
IcZero(tempi,CREG_RAX);
i=IcModr(tempi,tempi->p1.type,tempi->p1.reg,tempi->p1.disp);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xF6);
if (tempi->p1.type&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
if (i.u1[0]==1)
IcU1(tempi,tempi->p1.disp);
else if (i.u1[0]==2)
IcU4(tempi,tempi->p1.disp);
else if (i.u1[0]==4) {
IcU4(tempi,tempi->p1.disp-(ip+tempi->ic_cnt+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,0xFF);
} else {
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.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.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.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.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) {
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) {
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) {
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 && //TODO
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.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.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.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.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.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,IcArg *p1,IcArg *p2,IntermediateCode *tempi2,
U8 op,U8 op_imm,BoolI1 locked,I8 ip)
{ //TODO:not fully utilizing Modr
BoolI1 no_depend= tempi2->ic_flags&ICF_NO_DEPEND_RESULT ?TRUE:FALSE;
I8 r1,t2,r2,d2,i=0x48;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
t2=p2->type&TY_MASK+IT_I8; //TODO: check overflow
r2=p2->reg;
d2=p2->disp;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (p1->type&TY_MASK==TY_REG &&
(p1->reg!=CREG_RAX||no_depend))
r1=p1->reg;
else if (p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip);
r1=CREG_RCX;
} else
r1=0;
if (!(TY_REG<=t2&TY_MASK<=TY_RIP_DISP32) ||
!(r2.u1[0]!=CREG_RAX&&(t2&TY_MASK!=TY_SIB||r2.u1[1]&15!=CREG_RAX)||no_depend)) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,t2,r2,d2,ip);
t2=TY_REG+IT_I8;
r2=CREG_RBX;
d2=0;
}
} else {
if (!(TY_REG<=t2&TY_MASK<=TY_RIP_DISP32) ||
!(r2.u1[0]!=CREG_RAX&&(t2&TY_MASK!=TY_SIB||r2.u1[1]&15!=CREG_RAX)||no_depend)) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,t2,r2,d2,ip);
t2=TY_REG+IT_I8;
r2=CREG_RCX;
d2=0;
}
if (p1->type&TY_MASK==TY_REG &&
(p1->reg!=CREG_RAX||no_depend))
r1=p1->reg;
else if (p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p1->type,p1->reg,p1->disp,ip);
r1=CREG_RBX;
} else
r1=0;
}
} else {
t2=TY_DISP+IT_I8;
d2=0;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (p1->type&TY_MASK==TY_REG &&
(p1->reg!=CREG_RAX||no_depend))
r1=p1->reg;
else if (p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip);
r1=CREG_RCX;
} else
r1=0;
if (p2->type&TY_MASK==TY_REG &&
(p2->reg!=CREG_RAX||no_depend))
r2=p2->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p2->type,p2->reg,p2->disp,ip);
r2=CREG_RBX;
}
} else {
if (p2->type&TY_MASK==TY_REG &&
(p2->reg!=CREG_RAX||no_depend))
r2=p2->reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p2->type,p2->reg,p2->disp,ip);
r2=CREG_RCX;
}
if (p1->type&TY_MASK==TY_REG &&
(p1->reg!=CREG_RAX||no_depend))
r1=p1->reg;
else if (p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p1->type,p1->reg,p1->disp,ip);
r1=CREG_RBX;
} else
r1=0;
}
}
if (!no_depend)
IcZero(tempi,CREG_RAX);
if (locked) {
if (op!=0xA30F)
IcU1(tempi,0xF0);
}
i=IcModr(r1,t2,r2,d2);
IcRex(tempi,i.u1[1]);
if (p1->type&TY_MASK==TY_IMM) {
IcU3(tempi,i.u1[2]<<16+op_imm);
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,p1->disp);
} else {
IcU3(tempi,i.u1[2]<<16+op);
if (t2&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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 (!no_depend) {
IcU4(tempi,0x00D08348);
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 IcAssignBit(IntermediateCode *tempi,IntermediateCode *tempi2,
BoolI1 locked,I8 ip)
{
I8 i,cnt;
//This might be paranoid.
if (tempi->p2.type&TY_MASK==TY_REG &&
tempi->p2.reg==CREG_RAX)
tempi->ic_flags|=ICF_P1_FIRST; //p2 is the p1 of Bts or Btr
if (tempi->p1.type&TY_MASK==TY_REG)
IcOr(tempi,tempi->p1.reg);
else {
if (tempi->p1.type&IT_MASK<=IT_U1 &&
TY_DISP<=tempi->p1.type&TY_MASK<=TY_RIP_DISP32) {
i=IcModr(tempi,tempi->p1.type,tempi->p1.reg,tempi->p1.disp);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xF6);
if (tempi->p1.type&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
if (i.u1[0]==1)
IcU1(tempi,tempi->p1.disp);
else if (i.u1[0]==2)
IcU4(tempi,tempi->p1.disp);
else if (i.u1[0]==4) {
IcU4(tempi,tempi->p1.disp-(ip+tempi->ic_cnt+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,0xFF);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcOr(tempi,CREG_RBX);
}
}
cnt=tempi->ic_cnt;
IcBitOps(tempi,&tempi->p2,&tempi->p3,tempi2,
0xAB0F,0x28BA0F,locked,ip);
i=tempi->ic_cnt+2-cnt;
tempi->ic_cnt=cnt;
IcU2(tempi,i<<8+0x74);
IcBitOps(tempi,&tempi->p2,&tempi->p3,tempi2,
0xAB0F,0x28BA0F,locked,ip);
cnt=tempi->ic_cnt;
IcBitOps(tempi,&tempi->p2,&tempi->p3,tempi2,
0xB30F,0x30BA0F,locked,ip);
i=tempi->ic_cnt-cnt;
tempi->ic_cnt=cnt;
IcU2(tempi,i<<8+0xEB);
IcBitOps(tempi,&tempi->p2,&tempi->p3,tempi2,
0xB30F,0x30BA0F,locked,ip);
}
void IcPreempt(IntermediateCode *tempi,I8 ip)
{
IntermediateCode *tempi2=tempi+1;
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 IcToUpper(IntermediateCode *tempi,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcU4(tempi,0x61F88348);
IcU2(tempi,0x0A7C);
IcU4(tempi,0x7AF88348);
IcU2(tempi,0x047F);
IcU4(tempi,0xE0C08348);
}
void IcToI8(LexStruct *lx,IntermediateCode *tempi,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_INT_RAX);
}
void IcToDouble(LexStruct *lx,IntermediateCode *tempi,I8 ip)
{
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RAX);
}
void IcPreIncDec(IntermediateCode *tempi,U8 op,I8 ip)
{
I8 r;
ClassStruct *tempc=tempi->ic_class,*tempc1=tempc-1;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempc->ptr_cnt && tempc1->size!=1) {
IcAddConst(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
tempc1->size,op==SLASH_OP_INC ? 0x0003:0x052B,ip);
} else
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;
}
if (tempc->ptr_cnt &&
tempc1->size!=1) {
IcAddConst(tempi,TY_DISP+tempi->p1.ptype,r,0,
TY_DISP+tempi->p1.ptype,r,0,
tempc1->size,op==SLASH_OP_INC ? 0x0003:0x052B,ip);
} else
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;
ClassStruct *tempc=tempi->ic_class,*tempc1=tempc-1;
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);
}
if (tempc->ptr_cnt &&
tempc1->size!=1) {
IcAddConst(tempi,tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
tempi->p1.type&TY_MASK+tempi->p1.ptype,tempi->p1.reg,tempi->p1.disp,
tempc1->size,op==SLASH_OP_INC ? 0x0003:0x052B,ip);
} else
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);
}
if (tempc->ptr_cnt &&
tempc1->size!=1) {
IcAddConst(tempi,TY_DISP+tempi->p1.ptype,r,0,
TY_DISP+tempi->p1.ptype,r,0,
tempc1->size,op==SLASH_OP_INC ? 0x0003:0x052B,ip);
} else
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;
BoolI1 short_jmp=FALSE,done;
CbMiscStruct *lb,*lb1;
IcArg *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 && //TODO
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)
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)) &&
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 (p2->type&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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 &&
TY_REG<=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 (p1->type&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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)
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)
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)
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)
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;
BoolI1 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (tempi->p1.type&TY_MASK!=TY_REG) {
if (tempi->p1.type&IT_MASK<=IT_U1 &&
TY_DISP<=tempi->p1.type&TY_MASK<=TY_RIP_DISP32) {
i=IcModr(tempi,tempi->p1.type,tempi->p1.reg,tempi->p1.disp);
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0xF6);
if (tempi->p1.type&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
if (i.u1[0]==1)
IcU1(tempi,tempi->p1.disp);
else if (i.u1[0]==2)
IcU4(tempi,tempi->p1.disp);
else if (i.u1[0]==4) {
IcU4(tempi,tempi->p1.disp-(ip2+tempi->ic_cnt+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,0xFF);
} else {
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)
{
U8 i,it,t1,r1,d1,r2;
BoolI1 short_jmp=FALSE,swap,override;
CbMiscStruct *lb,*lb1;
IcArg *p1,*p2;
if (tempi->p1.type&TY_MASK==TY_IMM) {
swap=TRUE;
p1=&tempi->p2;
p2=&tempi->p1;
} else {
swap=FALSE;
p1=&tempi->p1;
p2=&tempi->p2;
}
if (p2->type&TY_MASK==TY_IMM && p2->disp>MAX_U4)
override=TRUE;
else
override=FALSE;
if (p1->type&IT_MASK<p2->type&IT_MASK)
it=p1->type&IT_MASK;
else
it=p2->type&IT_MASK;
i=p2->disp;
if (p2->type&TY_MASK==TY_IMM && 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+0xA8);
else if (i<=MAX_U2)
IcU4(tempi,i<<16+0xA966);
else {
IcU1(tempi,0xA9);
IcU4(tempi,i);
}
} else {
t1=TY_REG+it;
d1=0;
if ((tempi->ic_flags&ICF_P1_FIRST ^^swap)&&!override) {
if (p1->type&TY_MASK==TY_REG) {
r1=p1->reg;
swap=TRUE;
} else {
r1=CREG_RCX;
swap=FALSE;
}
if (p2->type&TY_MASK==TY_REG) {
r2=p2->reg;
swap=FALSE;
} else
r2=CREG_RDX;
if (swap) {
if (p1->type&TY_MASK!=TY_REG || r1!=p1->reg)
IcMov(tempi,TY_REG+IT_I8,r1,0,p1->type,p1->reg,p1->disp,ip2);
if (TY_REG<=p2->type&TY_MASK<=TY_RIP_DISP32) {
t1=p2->type&TY_MASK+it;
r2=p2->reg;
d1=p2->disp;
} else
IcMov(tempi,TY_REG+IT_I8,r2,0,p2->type,p2->reg,p2->disp,ip2);
i=IcModr(r1,t1,r2,d1);
} else {
if (TY_REG<=p1->type&TY_MASK<=TY_RIP_DISP32) {
t1=p1->type&TY_MASK+it;
r1=p1->reg;
d1=p1->disp;
} else
IcMov(tempi,TY_REG+IT_I8,r1,0,p1->type,p1->reg,p1->disp,ip2);
if (p2->type&TY_MASK!=TY_REG || r2!=p2->reg)
IcMov(tempi,TY_REG+IT_I8,r2,0,p2->type,p2->reg,p2->disp,ip2);
i=IcModr(r2,t1,r1,d1);
}
} else {
if (p2->type&TY_MASK==TY_REG) {
r2=p2->reg;
swap=FALSE;
} else {
r2=CREG_RDX;
swap=TRUE;
}
if (p1->type&TY_MASK==TY_REG) {
r1=p1->reg;
swap=TRUE;
} else
r1=CREG_RCX;
if (override)
swap=FALSE;
if (swap) {
if (TY_REG<=p2->type&TY_MASK<=TY_RIP_DISP32) {
t1=p2->type&TY_MASK+it;
r2=p2->reg;
d1=p2->disp;
} else
IcMov(tempi,TY_REG+IT_I8,r2,0,p2->type,p2->reg,p2->disp,ip2);
if (p1->type&TY_MASK!=TY_REG || r1!=p1->reg)
IcMov(tempi,TY_REG+IT_I8,r1,0,p1->type,p1->reg,p1->disp,ip2);
i=IcModr(r1,t1,r2,d1);
} else {
if (p2->type&TY_MASK!=TY_REG || r2!=p2->reg)
IcMov(tempi,TY_REG+IT_I8,r2,0,p2->type,p2->reg,p2->disp,ip2);
if (TY_REG<=p1->type&TY_MASK<=TY_RIP_DISP32) {
t1=p1->type&TY_MASK+it;
r1=p1->reg;
d1=p1->disp;
} else
IcMov(tempi,TY_REG+IT_I8,r1,0,p1->type,p1->reg,p1->disp,ip2);
i=IcModr(r2,t1,r1,d1);
}
}
switch (it) {
case IT_I1:
case IT_U1:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x84);
break;
case IT_U2:
case IT_I2:
Ic66Rex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x85);
break;
default:
IcRex(tempi,i.u1[1]);
IcU2(tempi,i.u1[2]<<8+0x85);
}
if (t1&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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-(ip2+tempi->ic_cnt+4));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
}
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(LexStruct *lx,IntermediateCode *tempi,U8 op,I8 ip)
{
if (!Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt))
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
IcCopyTemplate(lx,tempi,op);
if (!Bt(&tempi->ic_flags,ICf_DONT_POP_FLOAT0+lx->float_template_cnt-1))
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFOp2(LexStruct *lx,IntermediateCode *tempi,U8 op,I8 ip)
{
if (Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt)) {
if (tempi->ic_flags&ICF_ALTERNATE_TEMPLATE)
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
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);
}
}
IcCopyTemplate(lx,tempi,op);
if (!Bt(&tempi->ic_flags,ICf_DONT_POP_FLOAT0+lx->float_template_cnt-1))
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFCmp(LexStruct *lx,IntermediateCode *tempi,U8 op,I8 ip)
{
if (Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt)) {
if (tempi->ic_flags&ICF_ALTERNATE_TEMPLATE) {
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RAX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
} else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else {
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);
IcCopyTemplate(lx,tempi,op);
IcMov(tempi,tempi->r.type,tempi->r.reg,tempi->r.disp,
TY_REG+IT_I8,CREG_RAX,0,ip);
}
void IcFOp2Equal(LexStruct *lx,IntermediateCode *tempi,U8 op,I8 ip)
{
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt)) {
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->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RAX,TRUE);
} else 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);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RDX,TRUE);
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);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RDX,TRUE);
}
IcCopyTemplate(lx,tempi,op);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_INT_RAX,TRUE);
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 (Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt)) {
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+tempi->p1.ptype,CREG_RCX,0,ip);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RAX,TRUE);
} 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);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RDX,TRUE);
} 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);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_DOUBLE_RDX,TRUE);
}
IcCopyTemplate(lx,tempi,op);
if (tempi->p1.ptype!=IT_DOUBLE)
IcCopyTemplate(lx,tempi,CMP_TEMPLATE_TO_INT_RAX,TRUE);
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(LexStruct *lx,IntermediateCode *tempi,U8 ip,U8 op,U1 *buf,I8 ip2)
{
I8 i;
BoolI1 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (Bt(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0+lx->float_template_cnt)) {
if (tempi->ic_flags&ICF_ALTERNATE_TEMPLATE) {
if (tempi->ic_flags&ICF_POP_CMP)
IcPopRegs(tempi,1<<CREG_RAX);
else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip);
} else
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip);
} else 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);
IcCopyTemplate(lx,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(LexStruct *lx,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);
IcCopyTemplate(lx,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);
IcCopyTemplate(lx,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(LexStruct *lx,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);
IcCopyTemplate(lx,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);
IcCopyTemplate(lx,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,BoolI1 locked,U1 *buf,I8 ip2)
{
I8 i,ty,r1,r2,d1,d2,t1,t2;
IcArg *p1=&tempi->p1,*p2=&tempi->p2,*tempp;
BoolI1 short_jmp=FALSE;
CbMiscStruct *lb,*lb1;
if (tempi->ic_flags & ICF_NOT_ADDRESS) {
if (tempi->ic_flags & ICF_P1_FIRST) {
if (!(tempi->ic_flags&ICF_SWAP) && p1->type&TY_MASK!=TY_REG && p1->type&TY_MASK!=TY_IMM ||
tempi->ic_flags&ICF_SWAP && p1->type&TY_MASK==TY_IMM ||
p1->type&TY_MASK==TY_STK) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip2);
t1=TY_REG+IT_I8;
r1=CREG_RCX;
d1=0;
} else {
t1=p1->type;
if (t1&TY_MASK==TY_IMM)
r1=0;
else
r1=p1->reg;
d1=p1->disp;
}
if (tempi->ic_flags&ICF_SWAP && p2->type&TY_MASK!=TY_REG && p2->type&TY_MASK!=TY_IMM ||
!(tempi->ic_flags&ICF_SWAP) && p2->type&TY_MASK==TY_IMM ||
p2->type&TY_MASK==TY_STK) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p2->type,p2->reg,p2->disp,ip2);
t2=TY_REG+IT_I8;
r2=CREG_RBX;
d2=0;
} else {
t2=p2->type;
if (t2&TY_MASK==TY_IMM)
r2=0;
else
r2=p2->reg;
d2=p2->disp;
}
} else {
if (tempi->ic_flags&ICF_SWAP && p2->type&TY_MASK!=TY_REG && p2->type&TY_MASK!=TY_IMM ||
!(tempi->ic_flags&ICF_SWAP) && p2->type&TY_MASK==TY_IMM ||
p2->type&TY_MASK==TY_STK) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p2->type,p2->reg,p2->disp,ip2);
t2=TY_REG+IT_I8;
r2=CREG_RCX;
d2=0;
} else {
t2=p2->type;
if (t2&TY_MASK==TY_IMM)
r2=0;
else
r2=p2->reg;
d2=p2->disp;
}
if (!(tempi->ic_flags&ICF_SWAP) && p1->type&TY_MASK!=TY_REG && p1->type&TY_MASK!=TY_IMM ||
tempi->ic_flags&ICF_SWAP && p1->type&TY_MASK==TY_IMM ||
p1->type&TY_MASK==TY_STK) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p1->type,p1->reg,p1->disp,ip2);
t1=TY_REG+IT_I8;
r1=CREG_RBX;
d1=0;
} else {
t1=p1->type;
if (t1&TY_MASK==TY_IMM)
r1=0;
else
r1=p1->reg;
d1=p1->disp;
}
}
} else {
t1=TY_DISP+IT_I8;
t2=TY_DISP+IT_I8;
d1=0;
d2=0;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (p1->type&TY_MASK==TY_REG)
r1=p1->reg;
else if (tempi->ic_flags&ICF_SWAP || p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p1->type,p1->reg,p1->disp,ip2);
r1=CREG_RCX;
} else
r1=0;
if (p2->type&TY_MASK==TY_REG)
r2=p2->reg;
else if (!(tempi->ic_flags&ICF_SWAP) || p2->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p2->type,p2->reg,p2->disp,ip2);
r2=CREG_RBX;
} else
r2=0;
} else {
if (p2->type&TY_MASK==TY_REG)
r2=p2->reg;
else if (!(tempi->ic_flags&ICF_SWAP) || p2->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,p2->type,p2->reg,p2->disp,ip2);
r2=CREG_RCX;
} else
r2=0;
if (p1->type&TY_MASK==TY_REG)
r1=p1->reg;
else if (tempi->ic_flags&ICF_SWAP || p1->type&TY_MASK!=TY_IMM) {
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,p1->type,p1->reg,p1->disp,ip2);
r1=CREG_RBX;
} else
r1=0;
}
}
if (locked) {
if (op!=0xA30F)
IcU1(tempi,0xF0);
}
if (tempi->ic_flags&ICF_SWAP) {
i=IcModr(r2,t1,r1,d1);
tempp=p1; p1=p2; p2=tempp;
ty=t1;
} else {
i=IcModr(r1,t2,r2,d2);
ty=t2;
}
IcRex(tempi,i.u1[1]);
if (p1->type&TY_MASK==TY_IMM) {
IcU3(tempi,i.u1[2]<<16+op_imm);
if (ty&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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+5));
tempi->ic_flags&=~ICF_CODE_FINAL;
}
IcU1(tempi,p1->disp);
} else {
IcU3(tempi,i.u1[2]<<16+op);
if (ty&TY_MASK==TY_SIB)
IcU1(tempi,i.u1[3]);
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;
}
}
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 IcInsQue(IntermediateCode *tempi,I8 ip2)
{
I8 r1,r2;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type==TY_REG+IT_I8 && tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
if (tempi->p2.type==TY_REG+IT_I8)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RAX;
}
} else {
if (tempi->p2.type==TY_REG+IT_I8 && tempi->p2.reg!=CREG_RDX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RAX;
}
if (tempi->p1.type==TY_REG+IT_I8)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
}
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+IT_I8,r1,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r1,0,TY_REG+IT_I8,r2,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r2,0,TY_REG+IT_I8,CREG_RBX,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r2,sizeof(void *),TY_REG+IT_I8,r1,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,CREG_RBX,sizeof(void *),TY_REG+IT_I8,r2,0,ip2);
}
void IcInsQueRev(IntermediateCode *tempi,I8 ip2)
{
I8 r1,r2;
if (tempi->ic_flags & ICF_P1_FIRST) {
if (tempi->p1.type==TY_REG+IT_I8 && tempi->p1.reg!=CREG_RAX)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
if (tempi->p2.type==TY_REG+IT_I8)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RAX;
}
} else {
if (tempi->p2.type==TY_REG+IT_I8 && tempi->p2.reg!=CREG_RDX)
r2=tempi->p2.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RAX;
}
if (tempi->p1.type==TY_REG+IT_I8)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
}
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+IT_I8,r1,sizeof(void *),ip2);
IcMov(tempi,TY_DISP+IT_I8,CREG_RBX,0,TY_REG+IT_I8,r2,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r2,0,TY_REG+IT_I8,r1,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r2,sizeof(void *),TY_REG+IT_I8,CREG_RBX,0,ip2);
IcMov(tempi,TY_DISP+IT_I8,r1,sizeof(void *),TY_REG+IT_I8,r2,0,ip2);
}
void IcRemQue(IntermediateCode *tempi,I8 ip2)
{
I8 r1;
if (tempi->p1.type==TY_REG+IT_I8)
r1=tempi->p1.reg;
else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RAX;
}
IcMov(tempi,TY_REG+IT_I8,CREG_RBX,0,TY_DISP+IT_I8,r1,0,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,TY_DISP+IT_I8,r1,sizeof(void *),ip2);
IcU3(tempi,0x1A8948);
IcU4(tempi,sizeof(void *)<<24+0x538948);
}
void IcLimitI8(IntermediateCode *tempi,I8 ip2)
{
I8 r2,r1,i2=0x48,i1=0x48;
if (tempi->ic_flags & ICF_P1_FIRST) { //TODO--does this come-up? checks for only 2 param before
setting flag
if (tempi->p1.type==TY_REG+IT_I8 && tempi->p1.reg!=CREG_RAX) {
r1=tempi->p1.reg;
if (r1>7) {
i1++;
r1&=7;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
if (tempi->p2.type==TY_REG+IT_I8 && tempi->p2.reg!=CREG_RAX) {
r2=tempi->p2.reg;
if (r2>7) {
i2++;
r2&=7;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
r2=CREG_RCX;
}
} else {
if (tempi->p2.type==TY_REG+IT_I8 && tempi->p2.reg!=CREG_RAX) {
r2=tempi->p2.reg;
if (r2>7) {
i2++;
r2&=7;
}
} 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_REG+IT_I8 && tempi->p1.reg!=CREG_RAX) {
r1=tempi->p1.reg;
if (r1>7) {
i1++;
r1&=7;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
r1=CREG_RDX;
}
}
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcU3(tempi,0xC03B00+r2<<16+i2);
IcU2(tempi,0x037D);
IcU3(tempi,0xC08B00+r2<<16+i2);
IcU3(tempi,0xC03B00+r1<<16+i1);
IcU2(tempi,0x037E);
IcU3(tempi,0xC08B00+r1<<16+i1);
}
void IcAndEqual(IntermediateCode *tempi,I8 ip2)
{
I8 i,bit;
if (tempi->p2.type&TY_MASK==TY_IMM &&
tempi->p1.type&TY_MASK!=TY_STK &&
tempi->ic_flags&ICF_NO_DEPEND_RESULT) {
i=~tempi->p2.disp;
bit=Bsf(i);
if (0<=bit==Bsr(i)) {
tempi->p2.disp=bit;
tempi->p2.reg=0;
tempi->p1.type=tempi->p1.type&TY_MASK+IT_I8;
IcBitOps(tempi,&tempi->p2,&tempi->p1,tempi,
0xB30F,0x30BA0F,FALSE,ip2);
return;
}
}
IcAddSubEctEqual(tempi,tempi->p1.ptype,
tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,0x210425240423,ip2);
}
void IcOrEqual(IntermediateCode *tempi,I8 ip2)
{
I8 i,bit;
if (tempi->p2.type&TY_MASK==TY_IMM &&
tempi->p1.type&TY_MASK!=TY_STK &&
tempi->ic_flags&ICF_NO_DEPEND_RESULT) {
i=tempi->p2.disp;
bit=Bsf(i);
if (0<=bit==Bsr(i)) {
tempi->p2.disp=bit;
tempi->p2.reg=0;
tempi->p1.type=tempi->p1.type&TY_MASK+IT_I8;
IcBitOps(tempi,&tempi->p2,&tempi->p1,tempi,
0xAB0F,0x28BA0F,FALSE,ip2);
return;
}
}
IcAddSubEctEqual(tempi,tempi->p1.ptype,
tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,0x09010D0C010B,ip2);
}
void IcXorEqual(IntermediateCode *tempi,I8 ip2)
{
I8 i,bit;
if (tempi->p2.type&TY_MASK==TY_IMM &&
tempi->p1.type&TY_MASK!=TY_STK &&
tempi->ic_flags&ICF_NO_DEPEND_RESULT) {
i=tempi->p2.disp;
bit=Bsf(i);
if (0<=bit==Bsr(i)) {
tempi->p2.disp=bit;
tempi->p2.reg=0;
tempi->p1.type=tempi->p1.type&TY_MASK+IT_I8;
IcBitOps(tempi,&tempi->p2,&tempi->p1,tempi,
0xBB0F,0x38BA0F,FALSE,ip2);
return;
}
}
IcAddSubEctEqual(tempi,tempi->p1.ptype,
tempi->r.type,tempi->r.reg,tempi->r.disp,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,0x310635340633,ip2);
}
void IcSwitch(IntermediateCode *tempi,LexStruct *lx,U1 *buf,I8 ip2)
{
I8 i,j;
CbMiscStruct *lb;
ExeAbsoluteAddressStruct *tempa;
if (tempi->p2.type&TY_MASK==TY_IMM) {
j=tempi->p2.disp;
IcMov(tempi,TY_REG+IT_U2,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
if (MIN_I1<=j<=MAX_I1) {
IcU3(tempi,0xFA8348);
IcU1(tempi,j);
} else if (MIN_I4<=j<=MAX_I4) {
IcU3(tempi,0xFA8148);
IcU4(tempi,j);
} else {
IcMov(tempi,TY_REG+IT_U2,CREG_RCX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcU3(tempi,0xD13B48);
}
} else {
if (tempi->ic_flags & ICF_P1_FIRST) {
IcMov(tempi,TY_REG+IT_U2,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
IcMov(tempi,TY_REG+IT_U2,CREG_RCX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_U2,CREG_RCX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_U2,CREG_RDX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
}
IcU3(tempi,0xD13B48);
}
IcU2(tempi,0x0873);
IcU4(tempi,0xD524FF48);
lb=tempi->ic_data;
if (lx->flags&LF_STATIC_COMPILE)
i=lb->address+lx->a->ip;
else
i=lb->address+buf;
if (lx->flags&LF_STATIC_COMPILE)
j=ip2+tempi->ic_cnt;
IcU4(tempi,i);
if (buf && lx->flags&LF_STATIC_COMPILE) {
tempa=MAllocZ(sizeof(ExeAbsoluteAddressStruct));
tempa->next=lx->a->absolutes;
lx->a->absolutes=tempa;
tempa->ip=j;
}
tempi->ic_flags&=~ICF_CODE_FINAL;
}
void IcLocalVarInit(IntermediateCode *tempi)
{
IcU3(tempi,0xC48B48);
IcU2(tempi,0x5748);
IcU3(tempi,0xF88B48);
IcU3(tempi,0xC1C748);
IcU4(tempi,tempi->ic_data);
IcU2(tempi,sys_var_init_val<<8+0xB0);
IcU2(tempi,0xAAF3);
IcU2(tempi,0x5F48);
}
void IcMemCpy(IntermediateCode *tempi,I8 ip2)
{
I8 i,j,cnt;
if (tempi->p1.type&TY_MASK==TY_IMM) {
if (!(cnt=tempi->p1.disp)) return;
if (tempi->p2.type&TY_MASK==TY_REG &&
tempi->p2.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
}
if (!(cnt&7))
i=3;
else if (!(cnt&3))
i=2;
else if (!(cnt&1))
i=1;
else
i=0;
cnt>>=i;
if (cnt<=2) {
j=0;
while (cnt--) {
switch (i) {
case 0:
IcMov(tempi,TY_REG+IT_I1,CREG_RCX,0,TY_DISP+IT_I1,CREG_RDX,j,ip2);
IcMov(tempi,TY_DISP+IT_I1,CREG_RAX,j,TY_REG+IT_I8,CREG_RCX,0,ip2);
break;
case 1:
IcMov(tempi,TY_REG+IT_I2,CREG_RCX,0,TY_DISP+IT_I2,CREG_RDX,j,ip2);
IcMov(tempi,TY_DISP+IT_I2,CREG_RAX,j,TY_REG+IT_I8,CREG_RCX,0,ip2);
break;
case 2:
IcMov(tempi,TY_REG+IT_I4,CREG_RCX,0,TY_DISP+IT_I4,CREG_RDX,j,ip2);
IcMov(tempi,TY_DISP+IT_I4,CREG_RAX,j,TY_REG+IT_I8,CREG_RCX,0,ip2);
break;
case 3:
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,TY_DISP+IT_I8,CREG_RDX,j,ip2);
IcMov(tempi,TY_DISP+IT_I8,CREG_RAX,j,TY_REG+IT_I8,CREG_RCX,0,ip2);
break;
}
j+=1<<i;
}
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,cnt,ip2);
IcPushRegs(tempi,1<<CREG_RSI+1<<CREG_RDI);
IcMov(tempi,TY_REG+IT_I8,CREG_RSI,0,
TY_REG+IT_I8,CREG_RDX,0,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDI,0,
TY_REG+IT_I8,CREG_RAX,0,ip2);
switch (i) {
case 0: IcU2(tempi,0xA4F3); break;
case 1: IcU3(tempi,0xA5F366); break;
case 2: IcU2(tempi,0xA5F3); break;
case 3: IcU4(tempi,0xA548F348); break;
}
IcPopRegs(tempi,1<<CREG_RSI+1<<CREG_RDI);
}
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
} else if (tempi->p2.type&TY_MASK==TY_REG &&
tempi->p2.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
}
IcPushRegs(tempi,1<<CREG_RSI+1<<CREG_RDI);
IcMov(tempi,TY_REG+IT_I8,CREG_RSI,0,
TY_REG+IT_I8,CREG_RDX,0,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDI,0,
TY_REG+IT_I8,CREG_RAX,0,ip2);
IcU2(tempi,0xA4F3);
IcPopRegs(tempi,1<<CREG_RSI+1<<CREG_RDI);
}
}
void IcMemSet(IntermediateCode *tempi,I8 ip2)
{
I8 i,cnt;
if (tempi->p1.type&TY_MASK==TY_IMM &&
tempi->p2.type&TY_MASK==TY_IMM && !tempi->p2.disp ) {
if (!(cnt=tempi->p1.disp)) return;
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
if (!(cnt&7))
i=3;
else if (!(cnt&3))
i=2;
else if (!(cnt&1))
i=1;
else
i=0;
cnt>>=i;
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,cnt,ip2);
IcPushRegs(tempi,1<<CREG_RDI);
IcMov(tempi,TY_REG+IT_I8,CREG_RDI,0,
TY_REG+IT_I8,CREG_RAX,0,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
switch (i) {
case 0: IcU2(tempi,0xAAF3); break;
case 1: IcU3(tempi,0xABF366); break;
case 2: IcU2(tempi,0xABF3); break;
case 3: IcU4(tempi,0xAB48F348); break;
}
IcPopRegs(tempi,1<<CREG_RDI);
} else {
if (tempi->p1.type&TY_MASK==TY_REG &&
tempi->p1.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
} else if (tempi->p2.type&TY_MASK==TY_REG &&
tempi->p2.reg==CREG_RAX) {
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
} else {
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
tempi->p3.type,tempi->p3.reg,tempi->p3.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RDX,0,
tempi->p2.type,tempi->p2.reg,tempi->p2.disp,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RCX,0,
tempi->p1.type,tempi->p1.reg,tempi->p1.disp,ip2);
}
IcPushRegs(tempi,1<<CREG_RDI);
IcMov(tempi,TY_REG+IT_I8,CREG_RDI,0,
TY_REG+IT_I8,CREG_RAX,0,ip2);
IcMov(tempi,TY_REG+IT_I8,CREG_RAX,0,
TY_REG+IT_I8,CREG_RDX,0,ip2);
IcU2(tempi,0xAAF3);
IcPopRegs(tempi,1<<CREG_RDI);
}
}
void IcRetEnd(IntermediateCode *tempi,I8 sub_type)
{
switch (sub_type) {
case IT_I1:
IcU4(tempi,0xC0BE0F48);
break;
case IT_U1:
IcU4(tempi,0xC0B60F48);
break;
case IT_I2:
IcU4(tempi,0xC0BF0F48);
break;
case IT_U2:
IcU4(tempi,0xC0B70F48);
break;
case IT_I4:
IcU3(tempi,0xC06348);
break;
case IT_U4:
IcU4(tempi,0xD88BDB33);
IcU3(tempi,0xC38B48);
break;
}
}
Compiler Back End