#define CN_A2 	0
#define CN_A1 	1
#define CN_INST 2
#define CN_RES	3

U0 CompNoteFloatOp(CCompCtrl *cc, CIntermediateCode *tmpi, Bool dont_pushable, Bool dont_popable, I64 pos)
{
	Bool link = FALSE;

	if (cc->pass == 7 && cc->last_float_op_ic && cc->last_dont_popable && dont_pushable)
	{
		switch [pos]
		{
			case CN_A2:
				if (cc->last_float_op_ic != tmpi && cc->dont_push_float)
					link = TRUE;
				break;

			case CN_A1:
				if (cc->last_float_op_ic != tmpi && cc->dont_push_float)
					link = TRUE;
				break;

			case CN_INST:
				if (cc->last_float_op_ic != tmpi)
				{
					if (cc->dont_push_float)
					{
						if (intermediate_code_table[tmpi->ic_code].arg_count == IS_2_ARG &&
								cc->last_float_op_ic->res.reg != REG_R8)
							tmpi->ic_flags |= ICF_ALT_TEMPLATE;
						else
							tmpi->ic_flags &= ~ICF_ALT_TEMPLATE;
						link = TRUE;
					}
				}
				else
				{
					if (intermediate_code_table[tmpi->ic_code].arg_count == IS_2_ARG && cc->last_float_op_pos != CN_A1)
						tmpi->ic_flags |= ICF_ALT_TEMPLATE;
					else
						tmpi->ic_flags &= ~ICF_ALT_TEMPLATE;
					link = TRUE;
				}
				break;

			case CN_RES:
				if (cc->last_float_op_ic == tmpi && cc->last_float_op_pos == CN_INST)
					link = TRUE;
				break;
		}
		if (link)
		{
			if (!Bts(&cc->last_float_op_ic->ic_flags, ICf_DONT_POP_FLOAT0 + cc->last_ic_float_op_num))
				cc->last_float_op_ic->ic_flags &= ~ICF_CODE_FINAL;
			if (!Bts(&tmpi->ic_flags, ICf_DONT_PUSH_FLOAT0 + cc->cur_ic_float_op_num))
				tmpi->ic_flags &= ~ICF_CODE_FINAL;
		}
	}
	cc->last_float_op_ic	 = tmpi;
	cc->last_dont_pushable	 = dont_pushable;
	cc->last_dont_popable	 = dont_popable;
	cc->last_ic_float_op_num = cc->cur_ic_float_op_num++;
	cc->last_float_op_pos	 = pos;
	if (cc->cur_ic_float_op_num > 4)
		throw('Compiler');
}

U0 CompSetFloatOpPushPop(CCompCtrl *cc, CIntermediateCode *tmpi, Bool *dont_push_float, Bool *dont_pop_float)
{
	if (cc->pass == 7)
	{
		*dont_push_float = FALSE;
		*dont_pop_float  = FALSE;
		tmpi->ic_flags &= ~ICF_CODE_FINAL;
	}
	else
	{
		*dont_push_float = Bt(&tmpi->ic_flags, ICf_DONT_PUSH_FLOAT0 + cc->cur_ic_float_op_num);
		*dont_pop_float  = Bt(&tmpi->ic_flags, ICf_DONT_POP_FLOAT0  + cc->cur_ic_float_op_num);
	}
}

U0 ICCopyTemplate(CCompCtrl *cc, CIntermediateCode *tmpi, I64 op,
				  Bool off_the_record, Bool dont_pushable, Bool dont_popable, I64 pos)
{
	Bool dont_push_float, dont_pop_float, alt;
	U8  *ptr;
	I64  i = 0;

	if (!off_the_record)
	{
		if (tmpi->ic_flags & ICF_ALT_TEMPLATE)
			alt = TRUE;
		else
			alt = FALSE;
		CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	}
	else
	{
		dont_push_float = FALSE;
		dont_pop_float  = FALSE;
		alt = FALSE;
	}
	if (alt && dont_push_float && !dont_pop_float)
	{
		ptr = comp_templates_dont_push2[op];
		i   = comp_templates_dont_push2[op + 1] - ptr;
	}
	if (!i)
	{
		if (dont_push_float)
		{
			if (dont_pop_float)
			{
				ptr = comp_templates_dont_push_pop[op];
				i   = comp_templates_dont_push_pop[op + 1] - ptr;
			}
			else
			{
				ptr = comp_templates_dont_push[op];
				i   = comp_templates_dont_push[op + 1] - ptr;
			}
		}
		else
		{
			if (dont_pop_float)
			{
				ptr = comp_templates_dont_pop[op];
				i   = comp_templates_dont_pop[op + 1] - ptr;
			}
			else
			{
				ptr = comp_templates[op];
				i   = comp_templates[op + 1] - ptr;
			}
		}
	}
	MemCopy(&tmpi->ic_body[tmpi->ic_count], ptr, i);
	if (!off_the_record)
		CompNoteFloatOp(cc, tmpi, dont_pushable, dont_popable, pos);
	tmpi->ic_count += i;
}

U0 ICFConvert(CCompCtrl *cc, CIntermediateCode *tmpi, I64 r1, CICType t2, I64 r2, I64 d2, Bool to_int, I64 pos, I64 rip)
{
	I64  rsp_size = 0, op1, op2;
	Bool dont_push_float, dont_pop_float;

	if (to_int)
	{
		op1 = SLASH_OP_FLD;
		op2 = SLASH_OP_FISTTP;
	}
	else
	{
		op1 = SLASH_OP_FILD;
		op2 = SLASH_OP_FSTP;
	}

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (!dont_push_float)
	{
		if (!(t2.raw_type >= RT_I64 && t2 & MDG_DISP_SIB_RIP))
		{
			ICPush(tmpi, t2, r2, d2, rip);
			t2 = MDF_SIB + RT_I64;
			r2 = REG_RSP + REG_RSP << 8;
			d2 = 0;
			rsp_size = 8;
		}
		else
		{
			if (!dont_pop_float)
			{
				rsp_size = 8;
				ICAddRSP(tmpi, -8);
			}
		}
		ICSlashOp(tmpi, t2, r2, d2, op1, rip);
	}
	else
	{
		if (!dont_pop_float)
		{
			rsp_size = 8;
			ICAddRSP(tmpi, -8);
		}
	}
	if (to_int)
		CompNoteFloatOp(cc, tmpi, TRUE, FALSE, pos);
	else
		CompNoteFloatOp(cc, tmpi, FALSE, TRUE, pos);
	if (dont_pop_float)
	{
		if (rsp_size)
			ICAddRSP(tmpi, rsp_size);
	}
	else
	{
		ICSlashOp(tmpi, MDF_SIB + RT_I64, REG_RSP + REG_RSP << 8, 0, op2, rip);
		ICPop(tmpi, MDF_REG + RT_I64, r1, 0, rip);
	}
}

U0 ICFConvert2(CCompCtrl *cc, CIntermediateCode *tmpi, I64 r1, CICType t2, I64 r2, I64 d2, Bool to_int, I64 rip)
{
	I64 rsp_size = 0, op1, op2;

	if (to_int)
	{
		op1 = SLASH_OP_FLD;
		op2 = SLASH_OP_FISTTP;
	}
	else
	{
		op1 = SLASH_OP_FILD;
		op2 = SLASH_OP_FSTP;
	}
	if (!(t2.raw_type >= RT_I64 && t2 & MDG_DISP_SIB_RIP))
	{
		ICPush(tmpi, t2, r2, d2, rip);
		t2 = MDF_SIB + RT_I64;
		r2 = REG_RSP + REG_RSP << 8;
		d2 = 0;
		rsp_size = 8;
	}
	else
	{
		rsp_size = 8;
		ICAddRSP(tmpi, -8);
	}
	ICSlashOp(tmpi, t2, r2, d2, op1, rip);
	ICSlashOp(tmpi, MDF_SIB + RT_I64, REG_RSP + REG_RSP << 8, 0, op2, rip);
	ICPop(tmpi, MDF_REG + RT_I64, r1, 0, rip);
	cc->last_dont_pushable = cc->last_dont_popable = FALSE; //TODO: improve this
}

U0 ICFUnaryMinus(CCompCtrl *cc, CIntermediateCode *tmpi, U8 *buf2, I64 rip)
{
	CICArg	*arg1 = &tmpi->arg1;
	I64		 rsp_size = 0, builtin1 = 0, t1, r1, d1;
	Bool	 dont_push_float, dont_pop_float;

	if (cc->flags & CCF_AOT_COMPILE)
		buf2 = cc->aotc->rip;

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (!dont_push_float)
	{
		if (arg1->type.raw_type >= RT_I64 && arg1->type & MDG_DISP_SIB_RIP)
		{
			t1 = arg1->type;
			r1 = arg1->reg;
			d1 = arg1->disp;
		}
		else
		{
			if (arg1->type & MDF_IMM)
			{
				if (!(builtin1 = ICBuiltInFloatConst(arg1->disp(F64))))
				{
					t1 = MDF_RIP_DISP32 + RT_I64;
					r1 = REG_RIP;
					d1 = COCFloatConstFind(cc, arg1->disp(F64)) + buf2;
				}
			}
			else
			{
				ICPush(tmpi, arg1->type, arg1->reg, arg1->disp, rip);
				t1 = MDF_SIB + RT_I64;
				r1 = REG_RSP + REG_RSP << 8;
				d1 = 0;
				rsp_size += 8;
			}
		}
		if (builtin1)
			ICU16(tmpi, builtin1);
		else
			ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_FLD, rip);
	}
	if (!dont_pop_float && !rsp_size)
	{
		rsp_size = 8;
		ICAddRSP(tmpi, -8);
	}
	ICU16(tmpi, 0xE0D9); //FCHS
	CompNoteFloatOp(cc, tmpi, TRUE, TRUE, CN_INST);
	if (dont_pop_float)
	{
		if (rsp_size)
			ICAddRSP(tmpi, rsp_size);
	}
	else
	{
		ICSlashOp(tmpi, MDF_SIB + RT_I64, REG_RSP + REG_RSP << 8, 0, SLASH_OP_FSTP, rip);
		ICPop(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, rip);
	}
}

U0 ICFMod(CCompCtrl *cc, CIntermediateCode *tmpi, I64 rip)
{//for MOD
	Bool dont_push_float, dont_pop_float;

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (dont_push_float)
	{
		if (tmpi->ic_flags & ICF_ALT_TEMPLATE)
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
		else
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, 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_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
	}
//TODO: unpushable,unpop?  Not sure
	ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_MOD, FALSE, FALSE, FALSE, CN_INST);
	if (!dont_pop_float)
		ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
}

U0 ICFPow(CCompCtrl *cc, CIntermediateCode *tmpi, U8 *buf, I64 rip)
{//for POW
	I64					 i;
	CAOTImportExport	*tmpie;
	CHashExport			*tmpex = HashFind("SYS_POW", cc->htc.hash_table_list, HTT_EXPORT_SYS_SYM);

	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_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
	if (cc->flags & CCF_AOT_COMPILE)
	{
		if (!tmpex)
		{
			tmpex		= CAlloc(sizeof(CHashExport));
			tmpex->str	= StrNew("SYS_POW");
			tmpex->type	= HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED | HTF_IMPORT;
			HashAdd(tmpex, cc->htc.global_hash_table);
		}
		if (tmpex->type & HTF_IMPORT)
		{
			if (OptionGet(OPTf_USE_IMM64))
			{
				ICU16(tmpi, 0xBB48);
				ICU64(tmpi, 0);
				if (buf)
				{
					tmpie		= CAlloc(sizeof(CAOTImportExport));
					tmpie->type	= IET_IMM_I64;
					tmpie->rip	= rip + tmpi->ic_count - 8;
					tmpie->next	= tmpex->ie_list;
					tmpex->ie_list = tmpie;
				}
				ICU16(tmpi, 0xD3FF);
			}
			else
			{
				ICU8(tmpi, 0xE8);
				ICU32(tmpi, -(rip + tmpi->ic_count + 4));
				if (buf)
				{
					tmpie		= CAlloc(sizeof(CAOTImportExport));
					tmpie->type	= IET_REL_I32;
					tmpie->rip	= rip + tmpi->ic_count - 4;
					tmpie->next	= tmpex->ie_list;
					tmpex->ie_list = tmpie;
				}
			}
		}
		else
		{//Kernel
			if (tmpex->type & HTF_UNRESOLVED)
				throw('Compiler');
			else
			{
				i = tmpex->val - (rip + tmpi->ic_count + 5);
				if (!(I32_MIN <= i <= I32_MAX))
				{
					throw('Compiler');
					// ICU16(tmpi, 0xBB48);
					// ICU64(tmpi, tmpex->val);
					// ICU16(tmpi, 0xD3FF);
				}
				else
				{
					ICU8(tmpi, 0xE8);
					ICU32(tmpi, i);
				}
			}
		}
	}
	else
	{
		i = tmpex->val - (rip + tmpi->ic_count + 5);
		if (!(I32_MIN <= i <= I32_MAX))
		{
			ICU16(tmpi, 0xBB48);
			ICU64(tmpi, tmpex->val);
			ICU16(tmpi, 0xD3FF);
		}
		else
		{
			ICU8(tmpi, 0xE8);
			ICU32(tmpi, i);
		}
	}
	tmpi->ic_flags &= ~ICF_CODE_FINAL;
	ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
}

U0 ICFOp(CCompCtrl *cc, CIntermediateCode *tmpi, I64 op, U8 *buf2, I64 rip)
{//for ADD,SUB,DIV,MUL
	CICArg	*arg1, *arg2;
	Bool	 dont_push_float, dont_pop_float, alt;
	I64		 rsp_size = 0, builtin1 = 0, builtin2 = 0, t1, r1, d1, t2, r2, d2;

	if (tmpi->ic_flags & ICF_ALT_TEMPLATE)
	{
		arg1 = &tmpi->arg2;
		arg2 = &tmpi->arg1;
		alt = TRUE;
	}
	else
	{
		arg1 = &tmpi->arg1;
		arg2 = &tmpi->arg2;
		alt = FALSE;
	}

	if (cc->flags & CCF_AOT_COMPILE)
		buf2 = cc->aotc->rip;

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (dont_push_float)
	{
		if (arg2->type.raw_type >= RT_I64 && arg2->type & MDG_DISP_SIB_RIP)
		{
			t2 = arg2->type;
			r2 = arg2->reg;
			d2 = arg2->disp;
		}
		else
		{
			if (arg2->type & MDF_IMM)
			{
				if (!(builtin2 = ICBuiltInFloatConst(arg2->disp(F64))))
				{
					t2 = MDF_RIP_DISP32 + RT_I64;
					r2 = REG_RIP;
					d2 = COCFloatConstFind(cc, arg2->disp(F64)) + buf2;
				}
			}
			else
			{
				ICPush(tmpi,arg2->type, arg2->reg, arg2->disp, rip);
				t2 = MDF_SIB + RT_I64;
				r2 = REG_RSP + REG_RSP << 8;
				d2 = 0;
				rsp_size += 8;
			}
		}
	}
	else
	{
		if (alt)
		{
			if (!(arg2->type & MDF_STACK))
			{
				if (arg1->type.raw_type >= RT_I64 && arg1->type & MDG_DISP_SIB_RIP)
				{
					t1 = arg1->type;
					r1 = arg1->reg;
					d1 = arg1->disp;
				}
				else
				{
					if (arg1->type & MDF_IMM)
					{
						if (!(builtin1 = ICBuiltInFloatConst(arg1->disp(F64))))
						{
							t1 = MDF_RIP_DISP32 + RT_I64;
							r1 = REG_RIP;
							d1 = COCFloatConstFind(cc, arg1->disp(F64)) + buf2;
						}
					}
					else
					{
						ICPush(tmpi, arg1->type, arg1->reg, arg1->disp, rip);
						t1 = MDF_SIB + RT_I64;
						r1 = REG_RSP + REG_RSP << 8;
						d1 = 0;
						rsp_size+=8;
					}
				}
				if (arg2->type.raw_type >= RT_I64 && arg2->type & MDG_DISP_SIB_RIP)
				{
					t2 = arg2->type;
					r2 = arg2->reg;
					d2 = arg2->disp;
				}
				else
				{
					if (arg2->type & MDF_IMM)
					{
						if (!(builtin2 = ICBuiltInFloatConst(arg2->disp(F64))))
						{
							t2 = MDF_RIP_DISP32 + RT_I64;
							r2 = REG_RIP;
							d2 = COCFloatConstFind(cc, arg2->disp(F64)) + buf2;
						}
					}
					else
					{
						ICPush(tmpi, arg2->type, arg2->reg, arg2->disp, rip);
						t2 = MDF_SIB + RT_I64;
						r2 = REG_RSP + REG_RSP << 8;
						d2 = 0;
						rsp_size += 8;
						if (r1 == REG_RSP + REG_RSP << 8)
							d1 += 8;
					}
				}
			}
			else
			{
				ICMov(tmpi, MDF_REG +RT_I64, REG_RDX, 0, arg1->type, arg1->reg, arg1->disp, rip);
				ICMov(tmpi, MDF_REG +RT_I64, REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
				ICU16(tmpi, 0x5052); //PUSH EDX PUSH EAX
				rsp_size = 16;
				t1 = MDF_SIB + RT_I64;
				r1 = REG_RSP + REG_RSP << 8;
				d1 = 8;
				t2 = MDF_SIB + RT_I64;
				r2 = REG_RSP + REG_RSP << 8;
				d2 = 0;
			}
		}
		else
		{
			if (!(arg1->type & MDF_STACK))
			{
				if (arg2->type.raw_type >= RT_I64 && arg2->type & MDG_DISP_SIB_RIP)
				{
					t2 = arg2->type;
					r2 = arg2->reg;
					d2 = arg2->disp;
				}
				else
				{
					if (arg2->type & MDF_IMM)
					{
						if (!(builtin2 = ICBuiltInFloatConst(arg2->disp(F64))))
						{
							t2 = MDF_RIP_DISP32 + RT_I64;
							r2 = REG_RIP;
							d2 = COCFloatConstFind(cc, arg2->disp(F64)) + buf2;
						}
					}
					else
					{
						ICPush(tmpi, arg2->type, arg2->reg, arg2->disp, rip);
						t2 = MDF_SIB + RT_I64;
						r2 = REG_RSP + REG_RSP << 8;
						d2 = 0;
						rsp_size += 8;
					}
				}
				if (arg1->type.raw_type >= RT_I64 && arg1->type & MDG_DISP_SIB_RIP)
				{
					t1 = arg1->type;
					r1 = arg1->reg;
					d1 = arg1->disp;
				}
				else
				{
					if (arg1->type & MDF_IMM)
					{
						if (!(builtin1 = ICBuiltInFloatConst(arg1->disp(F64))))
						{
							t1 = MDF_RIP_DISP32 + RT_I64;
							r1 = REG_RIP;
							d1 = COCFloatConstFind(cc, arg1->disp(F64)) + buf2;
						}
					}
					else
					{
						ICPush(tmpi, arg1->type, arg1->reg, arg1->disp, rip);
						t1 = MDF_SIB + RT_I64;
						r1 = REG_RSP + REG_RSP << 8;
						d1 = 0;
						rsp_size += 8;
						if (r2 == REG_RSP + REG_RSP << 8)
							d2 += 8;
					}
				}
			}
			else
			{
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
				ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, arg1->type, arg1->reg, arg1->disp, rip);
				ICU16(tmpi, 0x5052); //PUSH EDX PUSH EAX
				rsp_size = 16;
				t1 = MDF_SIB + RT_I64;
				r1 = REG_RSP + REG_RSP << 8;
				d1 = 8;
				t2 = MDF_SIB + RT_I64;
				r2 = REG_RSP + REG_RSP << 8;
				d2 = 0;
			}
		}
	}
	if (!dont_pop_float && !rsp_size)
	{
		rsp_size = 8;
		ICAddRSP(tmpi, -8);
	}
	if (!dont_push_float)
	{
		if (builtin2 && !builtin1)
		{
			alt = !alt;
			SwapI64(&t1, &t2);
			SwapI64(&r1, &r2);
			SwapI64(&d1, &d2);
			SwapI64(&builtin1, &builtin2);
		}
		if (builtin1)
			ICU16(tmpi, builtin1);
		else
			ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_FLD, rip);
	}
	if (alt)
		switch (op.u8[0])
		{
			case 4:
				op = SLASH_OP_FSUBR;
				break;

			case 6:
				op = SLASH_OP_FDIVR;
				break;
		}
	if (builtin2)
	{
		ICU16(tmpi, builtin2);
		ICU16(tmpi, op.u16[2]);
	}
	else
		ICSlashOp(tmpi, t2, r2, d2, op, rip);
	CompNoteFloatOp(cc, tmpi, TRUE, TRUE, CN_INST);
	if (dont_pop_float)
	{
		if (rsp_size)
			ICAddRSP(tmpi, rsp_size);
	}
	else
	{
		if (rsp_size == 8)
			ICSlashOp(tmpi, MDF_SIB + RT_I64, REG_RSP + REG_RSP << 8, 0, SLASH_OP_FSTP, rip);
		else if (rsp_size > 8)
		{
			ICSlashOp(tmpi, MDF_SIB + RT_I64, REG_RSP + REG_RSP << 8, rsp_size - 8, SLASH_OP_FSTP, rip);
			ICAddRSP(tmpi, rsp_size - 8);
		}
		ICPop(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, rip);
	}
}

U0 ICFCmp(CCompCtrl *cc, CIntermediateCode *tmpi, I64 op, I64 rip)
{
	Bool dont_push_float, dont_pop_float;

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (dont_push_float)
	{
		if (tmpi->ic_flags & ICF_ALT_TEMPLATE)
		{
			if (tmpi->ic_flags & ICF_POP_CMP)
				ICPopRegs(tmpi, 1 << REG_RAX);
			else
				ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
		}
		else
			ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
	}
	else
	{
		ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
		if (tmpi->ic_flags & ICF_POP_CMP)
			ICPopRegs(tmpi, 1 << REG_RDX);
		else
			ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
	}
	if (tmpi->ic_flags & ICF_PUSH_CMP)
		ICPushRegs(tmpi, 1 << REG_RAX);
	ICCopyTemplate(cc, tmpi, op, FALSE, TRUE, FALSE, CN_INST);
	ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
}

U0 ICFModEqu(CCompCtrl *cc, CIntermediateCode *tmpi, I64 rip)
{
	Bool dont_push_float, dont_pop_float;

	CompSetFloatOpPushPop(cc, tmpi, &dont_push_float, &dont_pop_float);
	if (tmpi->ic_flags & ICF_BY_VAL)
	{
		if (dont_push_float)
		{
			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->arg1_type_pointed_to != RT_F64)
				ICFConvert2(cc, tmpi, REG_RAX, MDF_REG + RT_I64, REG_RAX, 0, FALSE, 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_RDX, 0,
				  tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
				  tmpi->arg1.reg, tmpi->arg1.disp, rip);
			if (tmpi->arg1_type_pointed_to != RT_F64)
				ICFConvert2(cc, tmpi, REG_RDX, MDF_REG + RT_I64, REG_RDX, 0, FALSE, rip);
		}
//TODO: unpushable,unpop?  Not sure
		ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_MOD, FALSE, FALSE, FALSE, CN_INST);
		if (tmpi->arg1_type_pointed_to != RT_F64)
			ICFConvert2(cc, tmpi, REG_RAX, MDF_REG + RT_I64, REG_RAX, 0, TRUE, rip);
		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);
		if (tmpi->res.type.mode)
			ICMov(tmpi, tmpi->res.type, 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 (dont_push_float)
		{
			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_RAX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
			if (tmpi->arg1_type_pointed_to != RT_F64)
				ICFConvert2(cc, tmpi, REG_RAX, MDF_REG + RT_I64, REG_RAX, 0, FALSE, 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_RDX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
			if (tmpi->arg1_type_pointed_to != RT_F64)
				ICFConvert2(cc, tmpi, REG_RDX, MDF_REG + RT_I64, REG_RDX, 0, FALSE, rip);
		}
//TODO: unpushable,unpop?  Not sure
		ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_MOD, FALSE, FALSE, FALSE, CN_INST);
		if (tmpi->arg1_type_pointed_to != RT_F64)
			ICFConvert2(cc, tmpi, REG_RAX, MDF_REG + RT_I64, REG_RAX, 0, TRUE, rip);
		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, REG_RAX, 0, rip);
	}
}
