$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;
 }
}
Home

Kernel
StartUp
Scheduler
Memory
MultiCore
Interrupts
BitMaps
Screen
Plot
Compiler Frontend
Compiler Mid
Compiler Backend
Compiler Back End
Historical capture: 2008-10-15. Home | Power on LoseThos | Sources and changes