U0 ICAddEct(CIntermediateCode *tmpi,
			CICType t1, I64 r1, I64 d1,
			CICType t2, I64 r2, I64 d2,
			CICType t3, I64 r3, I64 d3,
			I64 op, I64 rip)
{
	I64  i, tmp,res_reg = REG_RAX;
	Bool swap = FALSE;

	if (r3 != res_reg)
	{
		swap ^= TRUE;
		SwapI64(&t2, &t3);
		SwapI64(&r2, &r3);
		SwapI64(&d2, &d3);
	}
	if (t2.raw_type >= RT_I64 && r2 != res_reg && t2 & MDG_REG_DISP_SIB_RIP)
	{
		if (t1 & MDF_REG && !(r2 == r1 && t2 & MDG_REG_DISP_SIB))
			res_reg = r1;
		ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
		i=ICModr1(res_reg, t2, r2, d2);
		if (tmpi->ic_flags & ICF_LOCK)
			ICU8(tmpi, OC_LOCK_PREFIX);
		ICRex(tmpi, i.u8[1]);
		ICU16(tmpi, i.u8[2] << 8 + op);
		ICModr2(tmpi, i,, d2, rip);
	}
	else
	{
		if (t2 & MDF_REG)
			tmp = r2;
		else
			tmp = REG_RCX;

		if (t1 & MDF_REG)
			res_reg = r1;

		if (tmp == res_reg)
			res_reg = REG_RDX;
		if (swap)
		{
			if (r3 == tmp && t3 & MDG_REG_DISP_SIB)
				tmp = REG_RCX;
			ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t2, r2, d2, rip);
			ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
		}
		else
		{
			if (r2 == res_reg && t2 & MDG_REG_DISP_SIB)
				res_reg = REG_RDX;
			ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
			ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t2, r2, d2, rip);
		}
		i = 0x48;
		if (res_reg > 7)
			i += 4;
		if (tmp > 7)
			i++;
		if (tmpi->ic_flags & ICF_LOCK)
			ICU8(tmpi, OC_LOCK_PREFIX);
		ICU24(tmpi, 0xC00000 + i + (tmp & 7) << 16 + (res_reg & 7) << 19 + op << 8);
	}
	ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICAddSubEctImm(CIntermediateCode *tmpi,
				  CICType t1, I64 r1, I64 d1,
				  CICType t2, I64 r2, I64 d2,
				  I64 d, I64 op, I64 rip)
{
	I64 i;

	if (op.u8[0] == 0x2B)
	{
		op = 0x0003;
		d = -d;
	}
	if (t1 & MDF_REG)
	{
		if (!(t2 & MDF_REG))
		{
			ICMov(tmpi, t1, r1, d1, t2, r2, d2, rip);
			t2 = t1;
			r2 = r1;
			d2 = d1;
		}
		if (r1 == r2)
		{
			if (r1 > 7)
				i = 0x49;
			else
				i = 0x48;
			if (!d && (op.u8[0] == 0x03 || op.u8[0] == 0x2B || op.u8[0] == 0x33 || op.u8[0] == 0x0B))
				return;
			else if (d == 1 && op.u8[0] == 0x03)
			{
				ICU24(tmpi, 0xC0FF00 + op.u8[1] << 19 + i + (r1 & 7) << 16);
				return;
			}
			else if (d == -1 && op.u8[0] == 0x03)
			{
				ICU24(tmpi, 0xC8FF00 + i + (r1 & 7) << 16);
				return;
			}
			else if (I8_MIN <= d <= I8_MAX)
			{
				ICU24(tmpi, 0xC08300 + op.u8[1] << 19 + i + (r1 & 7) << 16);
				ICU8(tmpi, d);
				return;
			}
			else if (I32_MIN <= d <= I32_MAX)
			{
				ICU24(tmpi, 0xC08100 + op.u8[1] << 19 + i + (r1 & 7) << 16);
				ICU32(tmpi, d);
				return;
			}
		}
		if (op.u8[0] == 0x03 && I32_MIN <= d <= I32_MAX && !Bt(&cmp.non_ptr_vars_mask, r2))
		{
			i = ICModr1(r1, MDF_DISP + RT_I64, r2, d);
			i.u8[1] |= 0x48;
			ICU24(tmpi, i.u8[2] << 16 + 0x8D00 + i.u8[1]);
			ICModr2(tmpi, i,, d, rip);
			return;
		}
	}
	switch (Bsr(t1))
	{
		case MDf_REG:
		case MDf_DISP:
		case MDf_SIB:
		case MDf_RIP_DISP32:
			if (t1 != t2 || r1 != r2 || d1 != d2)
			{
				ICMov(tmpi, t1, r1, d1, t2, r2, d2, rip);
				t2 = t1;
				r2 = r1;
				d2 = d1;
			}

			if (!d &&(op.u8[0] == 0x03 || op.u8[0] == 0x2B || op.u8[0] == 0x33 || op.u8[0] == 0x0B))
				return;

			if (op.u8[0] == 0x03 && d == -1) //add -1
				op.u8[1] = 1; //Decrement slash val

			if (op.u8[0] == 0x03 && (d == 1 || d == -1)) { //Add
				i = ICModr1(op.u8[1], t1, r1, d1);
				if (!(t1 & MDF_REG) && tmpi->ic_flags & ICF_LOCK)
					ICU8(tmpi, OC_LOCK_PREFIX);
				switch (t1.raw_type)
				{
					case RT_I8:
					case RT_U8:
						ICRex(tmpi, i.u8[1]);
						ICU16(tmpi, i.u8[2] << 8 + 0xFE);
						break;

					case RT_I16:
					case RT_U16:
						ICOpSizeRex(tmpi, i.u8[1]);
						ICU16(tmpi, i.u8[2] << 8 + 0xFF);
						break;

					default:
						ICRex(tmpi, i.u8[1]);
						ICU16(tmpi, i.u8[2] << 8 + 0xFF);
				}
				ICModr2(tmpi, i,, d1, rip);
				return;
			}
			if (I8_MIN <= d <= I8_MAX || t1 & (RTG_MASK - RTF_UNSIGNED) == RT_I8)
			{
				ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_IMM_U8 + op.u8[1], rip + 1);
				ICU8(tmpi, d);
				return;
			}
			if (I32_MIN <= d <= I32_MAX || t1.raw_type < RT_I64)
			{
				ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_IMM_U32 + op.u8[1], rip);
				if (t1 & (RTG_MASK - RTF_UNSIGNED) == RT_I16)
					ICU16(tmpi, d);
				else
					ICU32(tmpi, d);
				return;
			}
			break;

		case MDf_STACK:
			ICAddSubEctImm(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t2, r2, d2, d, op, rip);
			ICPushRegs(tmpi, 1 << REG_RAX);
			return;
	}
	ICAddEct(tmpi, t1, r1, d1, MDF_IMM + RT_I64, 0, d, t2, r2, d2, op.u8[0], rip);
}

U0 ICSub(CIntermediateCode *tmpi,
		 CICType t1, I64 r1, I64 d1,
		 CICType t2, I64 r2, I64 d2,
		 CICType t3, I64 r3, I64 d3,
		 I64 rip)
{
	I64  i = 0x48, op = 0x2B;
	Bool swap = FALSE;

	if (r3 != REG_RAX)
	{
		swap = TRUE;
		SwapI64(&t2, &t3);
		SwapI64(&r2, &r3);
		SwapI64(&d2, &d3);
	}
	if (t2.raw_type >= RT_I64 && r2.u8[0] != REG_RAX &&
		(!(t2 & MDF_SIB) || r2.u8[1] & 15 != REG_RAX) &&
		t2 & MDG_REG_DISP_SIB_RIP)
	{
		ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
		if (!swap)
		{
			op = 0x03;
			ICU24(tmpi, 0xD8F748);
		}
		i = ICModr1(REG_RAX, t2, r2, d2);
		if (tmpi->ic_flags & ICF_LOCK)
			ICU8(tmpi, OC_LOCK_PREFIX);
		ICRex(tmpi, i.u8[1]);
		ICU16(tmpi, i.u8[2] << 8 + op);
		ICModr2(tmpi, i,, d2, rip);
		ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, REG_RAX, 0, rip);
	}
	else
	{
		if (!(t3 & MDF_REG) || t3.raw_type < RT_I64)
		{
			if (swap)
			{
				swap = FALSE;
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
				ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
				r2 = REG_RAX;
				r3 = REG_RCX;
			}
			else
			{
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
				ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
				r3 = REG_RAX;
				r2 = REG_RCX;
			}
		}
		else
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
			r2 = REG_RCX;
		}
		if (swap)
		{
			op = 0x03;
			ICU24(tmpi, 0xD9F748);
		}
		if (r3 > 7)
			i++;
		if (r2 > 7)
			i += 4;
		if (tmpi->ic_flags & ICF_LOCK)
			ICU8(tmpi, OC_LOCK_PREFIX);
		ICU24(tmpi, 0xC00000 + i + (r3 & 7) << 16 + (r2 & 7) << 19 + op << 8);
		ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, r2, 0, rip);
	}
}

U0 ICMul(CIntermediateCode *tmpi, I64 rip)
{
	I64		 i, r2, r = REG_RAX, j;
	CICArg	*arg1, *arg2;
	Bool	 alt;

	if (tmpi->arg1.type & MDF_IMM)
	{
		arg1 = &tmpi->arg2;
		arg2 = &tmpi->arg1;
		alt = TRUE;
	}
	else
	{
		arg1 = &tmpi->arg1;
		arg2 = &tmpi->arg2;
		alt = FALSE;
	}
	i = arg2->disp;
	if (!(tmpi->ic_class->raw_type & RTF_UNSIGNED) && arg2->type & MDF_IMM && I32_MIN <= i <= I32_MAX)
	{
		if (tmpi->res.type == MDF_REG + RT_I64)
		{
			ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, arg1->type, arg1->reg, arg1->disp, rip);
			r = tmpi->res.reg;
		}
		else
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg1->type, arg1->reg, arg1->disp, rip);
		if (r > 7)
			j = 0xC0004D;
		else
			j = 0xC00048;
		if (I8_MIN <= i <= I8_MAX)
			ICU32(tmpi, i << 24 + 0x6B00 + j + (r & 7) << 16 + (r & 7) << 19);
		else
		{
			ICU24(tmpi, 0x6900 + j + (r & 7) << 16 + (r & 7) << 19);
			ICU32(tmpi, i);
		}
	}
	else
	{
		if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
			i = 0xE0F748;
		else
			i = 0xE8F748;
		if (alt)
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg1->type, arg1->reg, arg1->disp, rip);
			r2 = REG_RCX;
			ICMov(tmpi, MDF_REG + RT_I64,REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
		}
		else
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
			if (!(arg1->type & MDF_REG) || arg1->type.raw_type < RT_I64)
			{
				ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg1->type, arg1->reg, arg1->disp, rip);
				r2 = REG_RCX;
			}
			else
				r2 = arg1->reg;
		}
		if (r2 > 7)
		{
			i++;
			r2 &= 7;
		}
		ICU24(tmpi, i + r2 << 16);
	}
	ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, r, 0, rip);
}

U0 ICMulEqu(CIntermediateCode *tmpi, I64 rip)
{
	I64 i = tmpi->arg2.disp, r = REG_RAX, j;

	if (!(tmpi->ic_class->raw_type & RTF_UNSIGNED) && tmpi->arg2.type & MDF_IMM && I32_MIN <= i <= I32_MAX)
	{
		if (tmpi->ic_flags & ICF_BY_VAL)
		{
			if (tmpi->arg1.type == MDF_REG + RT_I64)
				r = tmpi->arg1.reg;
			else
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0,
					  tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
					  tmpi->arg1.reg, tmpi->arg1.disp, rip);
			if (r > 7)
				j = 0xC0004D;
			else
				j = 0xC00048;
			if (I8_MIN <= i <= I8_MAX)
				ICU32(tmpi, i << 24 + 0x6B00 + j + (r & 7) << 16 + (r & 7) << 19);
			else
			{
				ICU24(tmpi, 0x6900 + j + (r & 7) << 16 + (r & 7) << 19);
				ICU32(tmpi, i);
			}
			ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, r, 0, rip);
		}
		else
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0,
				  tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0,
				  MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
			r = REG_RBX;
			if (I8_MIN <= i <= I8_MAX)
				ICU32(tmpi, i << 24 + 0xDB6B48);
			else
			{
				ICU24(tmpi, 0xDB6948);
				ICU32(tmpi, i);
			}
			ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, REG_RBX, 0, rip);
		}
	}
	else
	{
		if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
			i = 0xE3F748;
		else
			i = 0xEBF748;
		if (tmpi->ic_flags & ICF_BY_VAL)
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0,
				  tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, rip);
			ICU24(tmpi, i);
			ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
		}
		else
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
			ICU24(tmpi, i);
			ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, REG_RAX, 0, rip);
		}
	}
	if (tmpi->res.type.mode)
		ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, r, 0, rip);
}

U0 ICDiv(CIntermediateCode *tmpi, I64 rip)
{
	ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
	ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
	if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
	{
		ICZero(tmpi, REG_RDX);
		ICU24(tmpi, 0xF1F748);
	}
	else
	{
		ICU16(tmpi, 0x9948);
		ICU24(tmpi, 0xF9F748);
	}
	ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
}

U0 ICDivEqu(CIntermediateCode *tmpi, Bool is_mod, I64 rip)
{
	if (tmpi->ic_flags & ICF_BY_VAL)
	{
		ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
		ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0,
			  tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
			  tmpi->arg1.reg, tmpi->arg1.disp, rip);
		if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
		{
			ICZero(tmpi, REG_RDX);
			ICU24(tmpi, 0xF1F748);
		}
		else
		{
			ICU16(tmpi, 0x9948);
			ICU24(tmpi, 0xF9F748);
		}
		if (is_mod)
			ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
		else
			ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
	}
	else
	{
		ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
		ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
//dangerous might clobber RBX in Mov, but it doesn't
		ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, rip);
		if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
		{
			ICZero(tmpi, REG_RDX);
			ICU24(tmpi, 0xF1F748);
		}
		else
		{
			ICU16(tmpi, 0x9948);
			ICU24(tmpi, 0xF9F748);
		}
		if (is_mod)
			ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, MDF_REG + RT_I64, REG_RDX, 0, rip);
		else
			ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, MDF_REG + RT_I64, REG_RAX, 0, rip);
	}
	if (tmpi->res.type.mode)
	{
		if (is_mod)
			ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
		else
			ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
	}
}

U0 ICMod(CIntermediateCode *tmpi, I64 rip)
{
	ICMov(tmpi, MDF_REG +RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
	ICMov(tmpi, MDF_REG +RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
	if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
	{
		ICZero(tmpi, REG_RDX);
		ICU24(tmpi, 0xF1F748);
	}
	else
	{
		ICU16(tmpi, 0x9948);
		ICU24(tmpi, 0xF9F748);
	}
	ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
}

U0 ICAddSubEctEqu(CIntermediateCode *tmpi, U8 type_pointed_to,
				  CICType t1, I64 r1, I64 d1,
				  CICType t2, I64 r2, I64 d2,
				  CICType t3, I64 r3, I64 d3,
				  I64 op, I64 rip)
{
	Bool done;
	I64  res_reg, tmp, i;

	if (tmpi->ic_flags & ICF_BY_VAL)
	{
		if (t3 & MDF_IMM)
		{
			ICAddSubEctImm(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2,
						   t2 & MDG_MASK + type_pointed_to, r2, d2, d3, op, rip);
			if (t1.mode)
				ICMov(tmpi, t1, r1, d1, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
			return;
		}
		else
		{
			done = FALSE;
			if (type_pointed_to >= RT_I64)
			{
				if (!t1.mode && t2 & MDG_REG_DISP_SIB_RIP)
				{
					if (t3 & MDF_REG)
						tmp = r3;
					else
					{
						tmp = REG_RCX;
						ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t3, r3, d3, rip);
					}
					i = ICModr1(tmp, t2 & MDG_MASK + type_pointed_to, r2, d2);
					if (tmpi->ic_flags & ICF_LOCK)
						ICU8(tmpi, OC_LOCK_PREFIX);
					ICRex(tmpi, i.u8[1]);
					ICU16(tmpi, i.u8[2] << 8 + op.u8[5]);
					ICModr2(tmpi, i,, d2, rip);
					return;
				}
				if (t3.raw_type >= RT_I64 && t3 & MDG_REG_DISP_SIB_RIP)
				{
					if (t2 & MDF_REG)
						res_reg = r2;
					else
					{
						res_reg = REG_RCX;
						ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
					}
					i = ICModr1(res_reg, t3 & MDG_MASK + type_pointed_to, r3, d3);
					if (tmpi->ic_flags & ICF_LOCK)
						ICU8(tmpi, OC_LOCK_PREFIX);
					ICRex(tmpi, i.u8[1]);
					ICU16(tmpi, i.u8[2] << 8 + op.u8[0]);
					ICModr2(tmpi, i,, d3, rip);
					ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
					done = TRUE;
				}
			}
			if (!done)
			{
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
				if (t2 & MDF_REG && r2 != REG_RAX)
					res_reg = r2;
				else
				{
					res_reg = REG_RCX;
					ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
				}
				if (tmpi->ic_flags & ICF_LOCK)
					ICU8(tmpi, OC_LOCK_PREFIX);
				if (res_reg > 7)
					ICU8(tmpi, 0x4C);
				else
					ICU8(tmpi, 0x48);
				ICU16(tmpi, 0xC000 + op.u8[0] + (res_reg & 7) << 11);
				ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
			}
		}
	}
	else
	{
		done = FALSE;
		if (t3 & MDF_IMM && op.u8[2])
		{
			if (!d3.u32[1])
			{
				if (tmpi->ic_flags & ICF_RES_NOT_USED && t2 & MDF_REG && d3(U64) <= I8_MAX)
				{
					ICSlashOp(tmpi, MDF_DISP + type_pointed_to, r2, 0, 0x838000 + op.u8[4], rip);
					ICU8(tmpi, d3);
					done = TRUE;
				}
				else if (op.u8[2] == 0x24)
				{//AND
					ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
					ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
					res_reg = REG_RAX;
					if (tmpi->ic_flags & ICF_LOCK)
						ICU8(tmpi, OC_LOCK_PREFIX);
					ICU16(tmpi, op.u8[3] << 8 + 0x40);
					ICU32(tmpi, d3);
					ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
					done = TRUE;
				}
				else if (type_pointed_to < RT_I64)
				{//OR/XOR
					ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
					ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
					res_reg = REG_RAX;
					if (tmpi->ic_flags & ICF_LOCK)
						ICU8(tmpi, OC_LOCK_PREFIX);
					if (d3.u16[1])
					{
						ICU16(tmpi, op.u8[3] << 8 + 0x40);
						ICU32(tmpi, d3);
					}
					else if (d3.u8[1])
					{
						ICU24(tmpi, op.u8[3] << 16 + 0x4000 + OC_OP_SIZE_PREFIX);
						ICU16(tmpi, d3);
					}
					else
					{
						ICU16(tmpi, op.u8[2] << 8 + 0x40);
						ICU8(tmpi, d3);
					}
					ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
					done = TRUE;
				}
			}
		}
		if (!done)
		{
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
			ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
			res_reg = REG_RBX;
			if (tmpi->ic_flags & ICF_LOCK)
				ICU8(tmpi, OC_LOCK_PREFIX);
			ICU8(tmpi, 0x48);
			ICU16(tmpi, 0xC000 + op.u8[0] + (res_reg & 7) << 11);
			ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
		}
	}
	if (t1.mode)
		ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICShift(CIntermediateCode *tmpi,
		   CICType t1, I64 r1, I64 d1,
		   CICType t2, I64 r2, I64 d2,
		   CICType t3, I64 r3, I64 d3,
		   I64 us, I64 is, I64 rip)
{
	I64 i = 0x48, res_reg;

	if (tmpi->ic_class->raw_type & RTF_UNSIGNED || tmpi->ic_flags & ICF_USE_UNSIGNED)
		is = us;
	if (t1 & MDF_REG)
	{
		res_reg = r1;
		if (res_reg > 7)
			i++;
	}
	else
		res_reg = REG_RAX;
	if (t3 & MDF_IMM)
	{
		ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t2, r2, d2, rip);
		if (d3 == 1)
			ICU24(tmpi, i + is.u16[2] << 8 + (res_reg & 7) << 16);
		else
		{
			ICU24(tmpi, i + is.u16[0] << 8 + (res_reg & 7) << 16);
			ICU8(tmpi, d3);
		}
	}
	else
	{
		ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
		ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t2, r2, d2, rip);
		ICU24(tmpi, i + is.u16[1] << 8 + (res_reg & 7) << 16);
	}
	ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICShiftEqu(CIntermediateCode *tmpi,U8 type_pointed_to,
			  CICType t1, I64 r1, I64 d1,
			  CICType t2, I64 r2, I64 d2,
			  CICType t3, I64 r3, I64 d3,
			  I64 us, I64 is, I64 rip)
{
	I64 res_reg;

	if (tmpi->ic_class->raw_type & RTF_UNSIGNED || tmpi->ic_flags & ICF_USE_UNSIGNED)
		is = us;
	if (tmpi->ic_flags & ICF_BY_VAL)
	{
		if (!(t3 & MDF_IMM))
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
		if (t2 & MDF_REG)
			res_reg = r2;
		else
		{
			res_reg = REG_RAX;
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
		}
		if (res_reg > 7)
			ICU8(tmpi, 0x49);
		else
			ICU8(tmpi, 0x48);
		if (t3 & MDF_IMM)
		{
			if (d3 == 1)
				ICU16(tmpi, is.u16[2] + (res_reg & 7) << 8);
			else
			{
				ICU16(tmpi, is.u16[0] + (res_reg & 7) << 8);
				ICU8(tmpi, d3);
			}
		}
		else
			ICU16(tmpi, is.u16[1] + (res_reg & 7) << 8);
		ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
	}
	else
	{
		if (!(t3 & MDF_IMM))
			ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
		ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, t2, r2, d2, rip);
		ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RDX, 0, rip);
		res_reg = REG_RAX;
		ICU8(tmpi, 0x48);
		if (t3 & MDF_IMM)
		{
			if (d3 == 1)
				ICU16(tmpi, is.u16[2] + (res_reg & 7) << 8);
			else
			{
				ICU16(tmpi, is.u16[0] + (res_reg & 7) << 8);
				ICU8(tmpi, d3);
			}
		}
		else
			ICU16(tmpi, is.u16[1] + (res_reg & 7) << 8);
		ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RDX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
	}
	if (t1.mode)
		ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}
