
$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