U0 ICAndBranch(CIntermediateCode *tmpi,I64 rip,I64 is,U8 *buf,I64 rip2)
{
	U64 i;
	I64 it,t1,r1,d1,r2;
	Bool short_jmp,swap,override;
	CCodeMisc *lb;
	CICArg *arg1,*arg2;

	if (tmpi->arg1.type&MDF_IMM) {
		swap=TRUE;
		arg1=&tmpi->arg2;
		arg2=&tmpi->arg1;
	} else {
		swap=FALSE;
		arg1=&tmpi->arg1;
		arg2=&tmpi->arg2;
	}

	if (arg2->type&MDF_IMM && arg2->disp>U32_MAX)
		override=TRUE;
	else
		override=FALSE;

	if (arg1->type.raw_type<arg2->type.raw_type)
		it=arg1->type.raw_type;
	else
		it=arg2->type.raw_type;

	i=arg2->disp;
	if (arg2->type&MDF_IMM && i<=U32_MAX) {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,arg1->type,arg1->reg,arg1->disp,rip2);
		if (i<=U8_MAX)
			ICU16(tmpi,i<<8+0xA8);
		else if (i<=U16_MAX)
			ICU32(tmpi,i<<16+0xA900+OC_OP_SIZE_PREFIX);
		else {
			ICU8(tmpi,0xA9);
			ICU32(tmpi,i);
		}
	} else {
		t1=MDF_REG+it;
		d1=0;
		if (swap && !override) {
			if (arg1->type&MDF_REG) {
				r1=arg1->reg;
				swap=TRUE;
			} else {
				r1=REG_RCX;
				swap=FALSE;
			}
			if (arg2->type&MDF_REG) {
				r2=arg2->reg;
				swap=FALSE;
			} else
				r2=REG_RDX;
			if (swap) {
				if (!(arg1->type&MDF_REG) || r1!=arg1->reg)
					ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2);
				if (arg2->type&MDG_REG_DISP_SIB_RIP) {
					t1=arg2->type&MDG_MASK+it;
					r2=arg2->reg;
					d1=arg2->disp;
				} else
					ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2);
				i=ICModr1(r1,t1,r2,d1);
			} else {
				if (arg1->type&MDG_REG_DISP_SIB_RIP) {
					t1=arg1->type&MDG_MASK+it;
					r1=arg1->reg;
					d1=arg1->disp;
				} else
					ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2);
				if (!(arg2->type&MDF_REG) || r2!=arg2->reg)
					ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2);
				i=ICModr1(r2,t1,r1,d1);
			}
		} else {
			if (arg2->type&MDF_REG) {
				r2=arg2->reg;
				swap=FALSE;
			} else {
				r2=REG_RDX;
				swap=TRUE;
			}
			if (arg1->type&MDF_REG) {
				r1=arg1->reg;
				swap=TRUE;
			} else
				r1=REG_RCX;
			if (override)
				swap=FALSE;
			if (swap) {
				if (arg2->type&MDG_REG_DISP_SIB_RIP) {
					t1=arg2->type&MDG_MASK+it;
					r2=arg2->reg;
					d1=arg2->disp;
				} else
					ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2);
				if (!(arg1->type&MDF_REG) || r1!=arg1->reg)
					ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2);
				i=ICModr1(r1,t1,r2,d1);
			} else {
				if (!(arg2->type&MDF_REG) || r2!=arg2->reg)
					ICMov(tmpi,MDF_REG+RT_I64,r2,0,arg2->type,arg2->reg,arg2->disp,rip2);
				if (arg1->type&MDG_REG_DISP_SIB_RIP) {
					t1=arg1->type&MDG_MASK+it;
					r1=arg1->reg;
					d1=arg1->disp;
				} else
					ICMov(tmpi,MDF_REG+RT_I64,r1,0,arg1->type,arg1->reg,arg1->disp,rip2);
				i=ICModr1(r2,t1,r1,d1);
			}
		}
		switch (it) {
			case RT_I8:
			case RT_U8:
				ICRex(tmpi,i.u8[1]);
				ICU16(tmpi,i.u8[2]<<8+0x84);
				break;
			case RT_U16:
			case RT_I16:
				ICOpSizeRex(tmpi,i.u8[1]);
				ICU16(tmpi,i.u8[2]<<8+0x85);
				break;
			default:
				ICRex(tmpi,i.u8[1]);
				ICU16(tmpi,i.u8[2]<<8+0x85);
		}
		ICModr2(tmpi,i,,d1,rip2);
	}

	rip+=tmpi->ic_count;
	lb=OptLabelFwd(tmpi->ic_data);
	short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP);
	if (!buf && lb->addr!=INVALID_PTR) {
		i=lb->addr-(rip+2);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		if (I8_MIN<=i<=I8_MAX)
			short_jmp=TRUE;
	}

	if (short_jmp) {
		tmpi->ic_flags|=ICF_SHORT_JMP;
		i=lb->addr-(rip+2);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		ICU16(tmpi,i<<8+is.u8[2]);
	} else {
		tmpi->ic_flags&=~ICF_SHORT_JMP;
		i=lb->addr-(rip+6);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		ICU16(tmpi,is.u16[0]);
		ICU32(tmpi,i);
	}
}

U0 ICAssign(CIntermediateCode *tmpi,I64 rip)
{
	CIntermediateCode *tmpi1;
	if (tmpi->ic_flags & ICF_BY_VAL) {
		ICMov(tmpi,tmpi->arg1.type&MDG_MASK+tmpi->arg1_type_pointed_to,
					tmpi->arg1.reg,tmpi->arg1.disp,
					tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
		if (tmpi->res.type.mode)
			ICMov(tmpi,tmpi->res.type&MDG_MASK+tmpi->arg1_type_pointed_to,
						tmpi->res.reg,tmpi->res.disp,
						tmpi->arg1.type&MDG_MASK+tmpi->arg1_type_pointed_to,
						tmpi->arg1.reg,tmpi->arg1.disp,rip);
	} else {
		if (tmpi->arg1.type&MDF_REG) {
			if (!(tmpi1=OptLag1(tmpi)) || tmpi1->ic_code!=IC_ADD_CONST ||
						tmpi1->res.type!=MDF_REG+RT_I64 || tmpi1->res.reg!=tmpi->arg1.reg ||
						tmpi1->arg1.type!=MDF_REG+RT_I64 ||
						tmpi1->arg1.reg!=tmpi->arg1.reg ||
						(tmpi->arg2.type&MDF_REG || tmpi->arg2.type&MDF_DISP) &&
						tmpi->arg2.reg==tmpi->arg1.reg ||
						tmpi->res.type.mode || tmpi1->ic_flags&~ICG_NO_CONVERT_MASK) {
				ICMov(tmpi,
							MDF_DISP+tmpi->arg1_type_pointed_to,
							tmpi->arg1.reg,tmpi->arg1.disp,
							tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
				if (tmpi->res.type.mode)
					ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
								tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
			} else {
				tmpi->ic_flags=(tmpi->ic_flags|tmpi1->ic_flags)&
							~ICF_CODE_FINAL|ICF_DONT_RESTORE;
				tmpi->arg1.disp=tmpi1->ic_data;
				OptSetNOP1(tmpi1); //This better not be last pass!
				ICMov(tmpi,MDF_DISP+tmpi->arg1_type_pointed_to,
							tmpi->arg1.reg,tmpi->arg1.disp,
							tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
			}
		} else {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,
						tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip);
			ICMov(tmpi,MDF_DISP+tmpi->arg1_type_pointed_to,REG_RCX,0,
						tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
			if (tmpi->res.type.mode)
				ICMov(tmpi,tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
							tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip);
		}
	}
}

U0 ICBrBitOps(CIntermediateCode *tmpi,I64 rip,
				I64 op,I64 op_imm,I64 is,U8 *buf,I64 rip2)
{
	I64 i,t,r1,r2,d1,d2,t1,t2;
	CICArg *arg1=&tmpi->arg1,*arg2=&tmpi->arg2;
	Bool short_jmp;
	CCodeMisc *lb;

	if (tmpi->ic_flags & ICF_BY_VAL) {
		if (tmpi->ic_flags&ICF_SWAP && !(arg2->type&MDF_REG) &&
					(!(arg2->type&MDF_IMM) ||arg2->disp>63)||
					!(tmpi->ic_flags&ICF_SWAP) && arg2->type&MDF_IMM &&
					arg2->disp<64 || arg2->type&MDF_STACK) {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,arg2->type,arg2->reg,arg2->disp,rip2);
			t2=MDF_REG+RT_I64;
			r2=REG_RCX;
			d2=0;
		} else {
			t2=arg2->type;
			if (t2&MDF_IMM && arg2->disp<64)
				r2=0;
			else
				r2=arg2->reg;
			d2=arg2->disp;
		}
		if (!(tmpi->ic_flags&ICF_SWAP) && !(arg1->type&MDF_REG) &&
					(!(arg1->type&MDF_IMM) || arg1->disp>63) ||
					tmpi->ic_flags&ICF_SWAP && arg1->type&MDF_IMM &&
					arg1->disp<64 || arg1->type&MDF_STACK) {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,arg1->type,arg1->reg,arg1->disp,rip2);
			t1=MDF_REG+RT_I64;
			r1=REG_RDX;
			d1=0;
		} else {
			t1=arg1->type;
			if (t1&MDF_IMM && arg1->disp<64)
				r1=0;
			else
				r1=arg1->reg;
			d1=arg1->disp;
		}
	} else {
		t1=MDF_DISP+RT_I64;
		t2=MDF_DISP+RT_I64;
		d1=0;
		d2=0;
		if (arg2->type&MDF_REG)
			r2=arg2->reg;
		else if (!(tmpi->ic_flags&ICF_SWAP) || !(arg2->type&MDF_IMM) ||
					arg2->disp>63) {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,arg2->type,arg2->reg,arg2->disp,rip2);
			r2=REG_RCX;
		} else
			r2=0;
		if (arg1->type&MDF_REG)
			r1=arg1->reg;
		else if (tmpi->ic_flags&ICF_SWAP ||
					!(arg1->type&MDF_IMM) || arg1->disp>63) {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,arg1->type,arg1->reg,arg1->disp,rip2);
			r1=REG_RDX;
		} else
			r1=0;
	}
	if (tmpi->ic_flags&ICF_LOCK && op!=0xA30F)
		ICU8(tmpi,OC_LOCK_PREFIX);
	if (tmpi->ic_flags&ICF_SWAP) {
		if (arg2->type&MDF_IMM && arg2->disp<32) {
			if (op==0xA30F && arg2->disp<8) {
				t=t1&MDG_MASK+RT_U8;
				op_imm=0xF6; //TEST
			} else
				t=t1&MDG_MASK+RT_U32;
		} else
			t=t1;
		i=ICModr1(r2,t,r1,d1);
		SwapI64(&arg1,&arg2);
	} else {
		if (arg1->type&MDF_IMM && arg1->disp<32) {
			if (op==0xA30F && arg1->disp<8) {
				t=t2&MDG_MASK+RT_U8;
				op_imm=0xF6; //TEST
			} else
				t=t2&MDG_MASK+RT_U32;
		} else
			t=t2;
		i=ICModr1(r1,t,r2,d2);
	}
	ICRex(tmpi,i.u8[1]);
	if (op_imm==0xF6) {//TEST
		ICU16(tmpi,i.u8[2]<<8+op_imm);
		ICModr2(tmpi,i,,arg2->disp,rip2+1);
		ICU8(tmpi,1<<arg1->disp);
		if (is==0x72820F)
			is=0x75850F;
		else
			is=0x74840F;
	} else if (arg1->type&MDF_IMM && arg1->disp<64) {
		ICU24(tmpi,i.u8[2]<<16+op_imm);
		ICModr2(tmpi,i,,arg2->disp,rip2+1);
		ICU8(tmpi,arg1->disp);
	} else {
		ICU24(tmpi,i.u8[2]<<16+op);
		ICModr2(tmpi,i,,arg2->disp,rip2);
	}

	rip+=tmpi->ic_count;
	lb=OptLabelFwd(tmpi->ic_data);
	short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP);
	if (!buf && lb->addr!=INVALID_PTR) {
		i=lb->addr-(rip+2);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		if (I8_MIN<=i<=I8_MAX)
			short_jmp=TRUE;
	}

	if (short_jmp) {
		tmpi->ic_flags|=ICF_SHORT_JMP;
		i=lb->addr-(rip+2);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		ICU16(tmpi,i<<8+is.u8[2]);
	} else {
		tmpi->ic_flags&=~ICF_SHORT_JMP;
		i=lb->addr-(rip+6);
		if (lb->flags&CMF_POP_CMP)
			i+=8;
		ICU16(tmpi,is.u16[0]);
		ICU32(tmpi,i);
	}
}

U0 ICQueueInit(CIntermediateCode *tmpi,I64 rip2)
{
	I64 r1;
	if (tmpi->arg1.type==MDF_REG+RT_I64)
		r1=tmpi->arg1.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
		r1=REG_RAX;
	}
	ICMov(tmpi,MDF_DISP+RT_I64,r1,0,MDF_REG+RT_I64,r1,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r1,sizeof(U8 *),MDF_REG+RT_I64,r1,0,rip2);
}

U0 ICQueueInsert(CIntermediateCode *tmpi,I64 rip2)
{
	I64 r1,r2;
	if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RDX)
		r2=tmpi->arg2.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
					tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
		r2=REG_RAX;
	}
	if (tmpi->arg1.type==MDF_REG+RT_I64)
		r1=tmpi->arg1.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
		r1=REG_RDX;
	}
	ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r1,0,MDF_REG+RT_I64,r2,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r2,0,MDF_REG+RT_I64,REG_RBX,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r2,sizeof(U8 *),MDF_REG+RT_I64,r1,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,REG_RBX,sizeof(U8 *),MDF_REG+RT_I64,r2,0,rip2);
}

U0 ICQueueInsertRev(CIntermediateCode *tmpi,I64 rip2)
{
	I64 r1,r2;
	if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RDX)
		r2=tmpi->arg2.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
					tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
		r2=REG_RAX;
	}
	if (tmpi->arg1.type==MDF_REG+RT_I64)
		r1=tmpi->arg1.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
		r1=REG_RDX;
	}
	ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,sizeof(U8 *),rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,REG_RBX,0,MDF_REG+RT_I64,r2,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r2,0,MDF_REG+RT_I64,r1,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r2,sizeof(U8 *),MDF_REG+RT_I64,REG_RBX,0,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,r1,sizeof(U8 *),MDF_REG+RT_I64,r2,0,rip2);
}

U0 ICQueueRemove(CIntermediateCode *tmpi,I64 rip2)
{
	I64 r1;
	if (tmpi->arg1.type==MDF_REG+RT_I64)
		r1=tmpi->arg1.reg;
	else {
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
		r1=REG_RAX;
	}
	ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,MDF_DISP+RT_I64,r1,0,rip2);
	ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_I64,r1,sizeof(U8 *),rip2);
	ICU24(tmpi,0x1A8948);
	ICU32(tmpi,sizeof(U8 *)<<24+0x538948);
}

U0 ICMinMax(CIntermediateCode *tmpi,I64 op,I64 rip2)
{
	I64 r1,i1=0x48;
	if (tmpi->arg2.type==MDF_REG+RT_I64 && tmpi->arg2.reg!=REG_RAX) {
		r1=tmpi->arg2.reg;
		if (r1>7) {
			i1++;
			r1&=7;
		}
		ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
	} else {
		if (tmpi->arg1.reg==REG_RAX && tmpi->arg1.type&MDG_REG_DISP_SIB) {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,
						tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
			r1=REG_RDX;
			ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
						tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
		} else {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
						tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
			if (tmpi->arg1.type==MDF_REG+RT_I64) {
				r1=tmpi->arg1.reg;
				if (r1>7) {
					i1++;
					r1&=7;
				}
			} else {
				r1=REG_RDX;
				ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,
							tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
			}
		}
	}
	ICU24(tmpi,0xC03B00+r1<<16+i1);
	ICU32(tmpi,0xC0000F00+op<<16+r1<<24+i1);
}

U0 ICSqr(CIntermediateCode *tmpi,I64 op,I64 rip2)
{
	ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
				tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
	ICSlashOp(tmpi,MDF_REG+RT_I64,REG_RAX,0,op,rip2);
}

U0 ICModU64(CIntermediateCode *tmpi,I64 rip2)
{
	CICType t1;
	I64 r1,d1;
	ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,
				tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
	if (tmpi->arg1.reg!=REG_RAX && tmpi->arg1.reg!=REG_RDX &&
				tmpi->arg1.type&MDG_REG_DISP_SIB &&
				tmpi->arg1.type.raw_type>=RT_I64) {
		t1=tmpi->arg1.type;
		r1=tmpi->arg1.reg;
		d1=tmpi->arg1.disp;
	} else {
		t1=MDF_REG+RT_I64;
		r1=REG_RBX;
		d1=0;
		ICMov(tmpi,MDF_REG+RT_I64,REG_RBX,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
	}
	ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,MDF_DISP+RT_I64,REG_RCX,0,rip2);
	ICZero(tmpi,REG_RDX);
	ICSlashOp(tmpi,t1,r1,d1,SLASH_OP_DIV,rip2);
	ICMov(tmpi,MDF_DISP+RT_I64,REG_RCX,0,MDF_REG+RT_I64,REG_RAX,0,rip2);
	ICMov(tmpi,MDF_REG+RT_I64,REG_RAX,0,
				MDF_REG+RT_I64,REG_RDX,0,rip2);
}

U0 ICSwap(CIntermediateCode *tmpi,I64 rip2)
{
	I64 r1,r2;
	if (tmpi->arg1.type&MDF_REG)
		r1=tmpi->arg1.reg;
	else
		r1=REG_RAX;
	if (tmpi->arg2.type&MDF_REG)
		r2=tmpi->arg2.reg;
	else
		r2=REG_RAX;
	if (r1==r2) {
		if (r1==REG_RAX)
			r1=REG_RBX;
		else
			r2=REG_RAX;
	}
	ICMov(tmpi,MDF_REG+RT_I64,r2,0,
				tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
	ICMov(tmpi,MDF_REG+RT_I64,r1,0,
				tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
	switch (tmpi->ic_code) {
		case IC_SWAP_U8:
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U8,r1,0,rip2);
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U8,r2,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U8,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U8,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2);
			break;
		case IC_SWAP_U16:
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U16,r1,0,rip2);
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U16,r2,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U16,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U16,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2);
			break;
		case IC_SWAP_U32:
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U32,r1,0,rip2);
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U32,r2,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U32,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U32,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2);
			break;
		case IC_SWAP_I64:
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,MDF_DISP+RT_U64,r1,0,rip2);
			ICMov(tmpi,MDF_REG+RT_I64,REG_RDX,0,MDF_DISP+RT_U64,r2,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U64,r2,0,MDF_REG+RT_I64,REG_RCX,0,rip2);
			ICMov(tmpi,MDF_DISP+RT_U64,r1,0,MDF_REG+RT_I64,REG_RDX,0,rip2);
			break;
	}
}

U0 ICAndEqu(CIntermediateCode *tmpi,I64 rip2)
{
	I64 i,bit;
	if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STACK) &&
				tmpi->ic_flags&ICF_RES_NOT_USED) {
		i=~tmpi->arg2.disp;
		bit=Bsf(i);
		if (0<=bit==Bsr(i)) {
			tmpi->arg2.disp=bit;
			tmpi->arg2.reg=0;
			tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64;
			ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xB30F,0x30BA0F,rip2);
			return;
		}
	}
	ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to,
				tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
				tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,
				tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x210425240423,rip2);
}

U0 ICOrEqu(CIntermediateCode *tmpi,I64 rip2)
{
	I64 i,bit;
	if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STACK) &&
				tmpi->ic_flags&ICF_RES_NOT_USED) {
		i=tmpi->arg2.disp;
		bit=Bsf(i);
		if (0<=bit==Bsr(i) && i>I8_MAX) {
			tmpi->arg2.disp=bit;
			tmpi->arg2.reg=0;
			tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64;
			ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xAB0F,0x28BA0F,rip2);
			return;
		}
	}
	ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to,
				tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
				tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,
				tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x09010D0C010B,rip2);
}

U0 ICXorEqu(CIntermediateCode *tmpi,I64 rip2)
{
	I64 i,bit;
	if (tmpi->arg2.type&MDF_IMM && !(tmpi->arg1.type&MDF_STACK) &&
				tmpi->ic_flags&ICF_RES_NOT_USED) {
		i=tmpi->arg2.disp;
		bit=Bsf(i);
		if (0<=bit==Bsr(i)) {
			tmpi->arg2.disp=bit;
			tmpi->arg2.reg=0;
			tmpi->arg1.type=tmpi->arg1.type&MDG_MASK+RT_I64;
			ICBitOps(tmpi,&tmpi->arg2,&tmpi->arg1,tmpi,0xBB0F,0x38BA0F,rip2);
			return;
		}
	}
	ICAddSubEctEqu(tmpi,tmpi->arg1_type_pointed_to,
				tmpi->res.type,tmpi->res.reg,tmpi->res.disp,
				tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,
				tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,0x310635340633,rip2);
}

U0 ICSwitch(CIntermediateCode *tmpi,I64 rip,
				Bool nobound,CCompCtrl *cc,U8 *buf,I64 rip2)
{
	I64 i,j,count,min,max,begin,r;
	CCodeMisc *lb;
	Bool short_jmp;
	CAOTAbsAddr *tmpa;
	if (!(tmpi->arg1.type&MDF_REG) || tmpi->arg1.reg&7==REG_RSP)
		r=REG_RDX;
	else
		r=tmpi->arg1.reg;
	if (nobound)
		ICMov(tmpi,MDF_REG+RT_I64,r,0,
					tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
	else {
		if (tmpi->arg2.type&MDF_IMM) {
			j=tmpi->arg2.disp;
			ICMov(tmpi,MDF_REG+RT_I64,r,0,
						tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
			if (I8_MIN<=j<=I8_MAX) {
				i=0xF88348+(r&7)<<16;
				if (r>7) i++;
				ICU24(tmpi,i);
				ICU8(tmpi,j);
			} else if (I32_MIN<=j<=I32_MAX) {
				i=0xF88148+(r&7)<<16;
				if (r>7) i++;
				ICU24(tmpi,i);
				ICU32(tmpi,j);
			} else {
				ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,
							tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
				i=0xC13B48+(r&7)<<19;
				if (r>7) i+=4;
				ICU24(tmpi,i);
			}
		} else {
			ICMov(tmpi,MDF_REG+RT_I64,REG_RCX,0,
						tmpi->arg2.type,tmpi->arg2.reg,tmpi->arg2.disp,rip2);
			ICMov(tmpi,MDF_REG+RT_I64,r,0,
						tmpi->arg1.type,tmpi->arg1.reg,tmpi->arg1.disp,rip2);
			i=0xC13B48+(r&7)<<19;
			if (r>7) i+=4;
			ICU24(tmpi,i);
		}

		rip+=tmpi->ic_count;
		lb=tmpi->ic_data(CCodeMisc *)->default;
		short_jmp=ToBool(tmpi->ic_flags&ICF_SHORT_JMP);
		if (!buf && lb->addr!=INVALID_PTR) {
			i=lb->addr-(rip+2);
			if (I8_MIN<=i<=I8_MAX)
				short_jmp=TRUE;
		}
		if (short_jmp) {
			tmpi->ic_flags|=ICF_SHORT_JMP;
			ICU16(tmpi,(lb->addr-(rip+2))<<8+0x73);
		} else {
			tmpi->ic_flags&=~ICF_SHORT_JMP;
			ICU16(tmpi,0x830F);
			ICU32(tmpi,lb->addr-(rip+6));
		}
	}

	lb=tmpi->ic_data;
	begin=lb->begin->addr;
	if (!buf && begin!=INVALID_PTR) {
		min=I64_MAX;
		max=I64_MIN;
		for (i=0;i<lb->range;i++) {
			if (lb->jmp_table[i]->addr==INVALID_PTR) {
				min=I64_MIN;
				max=I64_MAX;
				break;
			} else {
				j=lb->jmp_table[i]->addr-begin;
				min=MinI64(min,j);
				max=MaxI64(max,j);
			}
		}
		if (I8_MIN<=min<=max<=I8_MAX)
			lb->flags|=CMF_I8_JMP_TABLE;
		else if (U8_MIN<=min<=max<=U8_MAX)
			lb->flags|=CMF_U8_JMP_TABLE;
		else if (I16_MIN<=min<=max<=I16_MAX)
			lb->flags|=CMF_I16_JMP_TABLE;
		else if (U16_MIN<=min<=max<=U16_MAX)
			lb->flags|=CMF_U16_JMP_TABLE;
	}

	if (lb->flags&CMF_I8_JMP_TABLE) {
		if (r<8)
			ICU8(tmpi,0x48);
		else
			ICU8(tmpi,0x49);
		ICU24(tmpi,0x98BE0F+(r&7)<<16);
		count=1;
	} else if (lb->flags&CMF_U8_JMP_TABLE) {
		if (r<8)
			count=2;
		else {
			ICU8(tmpi,0x49);
			count=1;
		}
		ICU24(tmpi,0x98B60F+(r&7)<<16);
	} else if (lb->flags&CMF_I16_JMP_TABLE) {
		if (r<8)
			ICU8(tmpi,0x48);
		else
			ICU8(tmpi,0x4A);
		ICU32(tmpi,0x451CBF0F+(r&7)<<27);
		count=0;
	} else if (lb->flags&CMF_U16_JMP_TABLE) {
		if (r<8)
			count=1;
		else {
			ICU8(tmpi,0x4A);
			count=0;
		}
		ICU32(tmpi,0x451CB70F+(r&7)<<27);
	} else {
		if (r<8)
			count=2;
		else {
			ICU8(tmpi,0x42);
			count=1;
		}
		ICU24(tmpi,0x851C8B+(r&7)<<19);
	}
	if (buf && cc->flags&CCF_AOT_COMPILE) {
		tmpa=CAlloc(sizeof(CAOTAbsAddr));
		tmpa->next=cc->aotc->abss;
		tmpa->type=AAT_ADD_U32;
		cc->aotc->abss=tmpa;
		tmpa->rip=rip2+tmpi->ic_count;
		ICU32(tmpi,lb->addr+cc->aotc->rip);
	} else
		ICU32(tmpi,lb->addr+buf);

	if (lb->flags&(CMF_I8_JMP_TABLE|CMF_U8_JMP_TABLE|
				CMF_I16_JMP_TABLE|CMF_U16_JMP_TABLE)) {
		ICU16(tmpi,0xC381); //ADD EBX,0x12345678
		if (buf && cc->flags&CCF_AOT_COMPILE) {
			tmpa=CAlloc(sizeof(CAOTAbsAddr));
			tmpa->next=cc->aotc->abss;
			tmpa->type=AAT_ADD_U32;
			cc->aotc->abss=tmpa;
			tmpa->rip=rip2+tmpi->ic_count;
			ICU32(tmpi,begin+cc->aotc->rip);
		} else
			ICU32(tmpi,begin+buf);
	} else
		count+=6;
	ICU16(tmpi,0xE3FF); //JMP EBX
	for (i=0;i<count;i++) //Code must always shrink, not expand
		ICU8(tmpi,OC_NOP);
	tmpi->ic_flags&=~ICF_CODE_FINAL;
}

U0 ICLocalVarInit(CIntermediateCode *tmpi)
{
	ICU24(tmpi,0xC48B48);
	ICU16(tmpi,0x5748);
	ICU24(tmpi,0xF88B48);
	ICU24(tmpi,0xC1C748);
	ICU32(tmpi,tmpi->ic_data);
	ICU16(tmpi,sys_var_init_val<<8+0xB0);
	ICU24(tmpi,0xAA48F3);
	ICU16(tmpi,0x5F48);
}