I64 InstEntriesCompare(CInst *tmpins1, CInst *tmpins2)
{
	I64 i1, i2, j = 0, res = 0, oc_count1 = tmpins1->opcode_count, oc_count2 = tmpins2->opcode_count;

	if (tmpins1->flags & IEF_STI_LIKE)
		oc_count1--;
	if (tmpins2->flags & IEF_STI_LIKE)
		oc_count2--;
	while (TRUE)
	{
		if (j < oc_count1 && j < oc_count2)
		{
			if (res = tmpins1->opcode[j] - tmpins2->opcode[j])
				return res;
			j++;
		}
		else
		{
			if (res = oc_count1 - oc_count2)
				return res;

			if (tmpins1->flags & IEF_STI_LIKE && tmpins2->flags & IEF_STI_LIKE)
				return tmpins1->opcode[j] - tmpins2->opcode[j];

			if (res = tmpins1->flags & IEF_STI_LIKE - tmpins2->flags & IEF_STI_LIKE)
				return res;

			if (res = tmpins1->slash_val - tmpins2->slash_val)
				return res;

			if (res = tmpins1->flags & IEF_OP_SIZE32 - tmpins2->flags & IEF_OP_SIZE32)
				return res;

			i1 = Bt(&uasm.ins64_arg_mask, tmpins1->arg1) || Bt(&uasm.ins64_arg_mask, tmpins1->arg2);
			i2 = Bt(&uasm.ins64_arg_mask, tmpins2->arg1) || Bt(&uasm.ins64_arg_mask, tmpins2->arg2);
			if (res = i1 - i2)
				return res;

			if (res = tmpins1->flags & IEF_48_REX - tmpins2->flags & IEF_48_REX)
				return res;

			i1 = tmpins1->arg2 == ARGT_IMM64 || tmpins1->arg2 == ARGT_UIMM64;
			i2 = tmpins2->arg2 == ARGT_IMM64 || tmpins2->arg2 == ARGT_UIMM64;
			return i1 - i2;
		}
	}
}

/*
U0 DumpUAsmIns(CInst *tmpins)
{
	CHashOpcode *tmpo = tmpins(U8 *) - tmpins->ins_entry_num * sizeof(CInst) - offset(CHashOpcode.ins);
	"%10s:%02d,%02d SV:%02d\n", tmpo->str, tmpins->arg1, tmpins->arg2, tmpins->slash_val;
}
U0 DumpUAsmTables()
{
	I64 k;
	"16/32 Bit Table\n";
	for (k = 0; k < uasm.table_16_32_entries; k++)
		DumpUAsmIns(uasm.table_16_32[k]);
	"\n\n\n\n64 Bit Table\n";
	for (k = 0; k < uasm.table_64_entries; k++)
		DumpUAsmIns(uasm.table_64[k]);
}
*/

CInst *InstEntryFind(U8 *rip, I64 opsize, I64 seg_size)
{//Binary Search
	I64		 i, j, n, m, k, arg1, arg2, o1, o2, oc_count;
	CInst	*tmpins, **table;

	i = 0;
	if (seg_size == 64)
	{
		table = uasm.table_64;
		j = uasm.table_64_entries - 1;
	}
	else
	{
		table = uasm.table_16_32;
		j = uasm.table_16_32_entries - 1;
	}
	while (TRUE)
	{
		k = (i + j) >> 1;  //binary search
		tmpins = table[k];
//DumpUAsmIns(tmpins);
		m = 0;
		n = 0;
		while (TRUE)
		{ //ief_compare_start
			arg1 = tmpins->arg1;
			arg2 = tmpins->arg2;
			oc_count = tmpins->opcode_count;
			if (tmpins->flags & IEF_STI_LIKE)
				oc_count--;
			if (n < oc_count)
			{
				o1 = rip[n];
				if (n == tmpins->opcode_count - 1 && tmpins->flags & IEF_PLUS_OPCODE)
					o1 &= -8;
				o2 = tmpins->opcode[n++];
				if (m = o1 - o2)
					goto ief_compare_done;
			}
			else
				switch [tmpins->uasm_slash_val]
				{
					case 0...7:
						if (!(m = rip[n] >> 3 & 7 - tmpins->slash_val))
						{
							if ((Bt(&uasm.mem_arg_mask, arg1) || Bt(&uasm.mem_arg_mask, arg2)) && rip[n] & 0xC0 == 0xC0)
							{
								m = 1;
								goto ief_compare_done;
							}
							if (opsize == 16)
							{
								if (tmpins->flags & IEF_OP_SIZE32)
								{
									m = -1;
									goto ief_compare_done;
								}
							}
							else
							{
								if (tmpins->flags & IEF_OP_SIZE16)
								{
									m = 1;
									goto ief_compare_done;
								}
							}
							if (opsize == 64 || arg1 == ARGT_M64 || arg2 == ARGT_M64)
							{
								if (!Bt(&uasm.ins64_arg_mask, arg1) && !Bt(&uasm.ins64_arg_mask, arg2) &&
										!(tmpins->flags & IEF_48_REX))
									m = 1;
							}
							else
							{
								if (Bt(&uasm.ins64_arg_mask, arg1) || Bt(&uasm.ins64_arg_mask, arg2) ||
										tmpins->flags & IEF_48_REX)
									m = -1;
							}
						}
						else if ((Bt(&uasm.mem_arg_mask, arg1) || Bt(&uasm.mem_arg_mask, arg2)) && rip[n] & 0xC0 == 0xC0)
							m = 1;
						goto ief_compare_done;

					case SV_I_REG:
						m = rip[n] >> 3 - tmpins->opcode[tmpins->opcode_count - 1] >> 3;
						goto ief_compare_done;

					case SV_STI_LIKE:
						if (!(m = rip[n] >> 3 - tmpins->opcode[tmpins->opcode_count - 1] >> 3))
							m = rip[n] - tmpins->opcode[tmpins->opcode_count - 1];
						goto ief_compare_done;

					case SV_R_REG:
					case SV_NONE:
						m = 0;
						if (opsize == 16)
						{
							if (tmpins->flags & IEF_OP_SIZE32)
							{
								m = -1;
								goto ief_compare_done;
							}
						}
						else
						{
							if (tmpins->flags & IEF_OP_SIZE16)
							{
								m = 1;
								goto ief_compare_done;
							}
						}
						if (opsize == 64 || arg1 == ARGT_M64 || arg2 == ARGT_M64)
						{
							if (!Bt(&uasm.ins64_arg_mask, arg1) && !Bt(&uasm.ins64_arg_mask, arg2) &&
									!(tmpins->flags & IEF_48_REX) && !(arg2 == ARGT_NONE &&
									(ARGT_UIMM8 <= arg1 <= ARGT_UIMM64 || ARGT_IMM8 <= arg1 <= ARGT_IMM64)))
								m = 1;
							else if (tmpins->arg2 == ARGT_IMM64 || tmpins->arg2 == ARGT_UIMM64)
							{
								if (arg2 != ARGT_IMM64 && arg2 != ARGT_UIMM64)
									m = 1;
							}
							else if (arg2 == ARGT_IMM64 || arg2 == ARGT_UIMM64)
								m = -1;
						}
						else
						{
							if (Bt(&uasm.ins64_arg_mask, arg1) || Bt(&uasm.ins64_arg_mask, arg2) ||
									tmpins->flags & IEF_48_REX)
								m = -1;
						}
						goto ief_compare_done;
				}
		}
ief_compare_done:
		if (m > 0)
		{
			if (k == i)
			{
				k = j;
				break;
			}
			else
				i = k;
		}
		else if (m < 0)
		{
			if (k - i <= 1)
			{
				k = i;
				break;
			}
			else
				j = k;
		}
		else
			break;
	}
	return table[k];
}

U0 UAsmHashLoad()
{
	CHashOpcode	*tmph;
	CInst		*tmpins;
	I64			 i, j1, j2, k;

	uasm.ins64_arg_mask = 0x0880888880 + 1 << ARGT_ST0 + 1 << ARGT_STI;
	uasm.signed_arg_mask = 1 << ARGT_REL8 + 1 << ARGT_REL16 + 1 << ARGT_REL32+
						   1 << ARGT_IMM8 + 1 << ARGT_IMM16 + 1 << ARGT_IMM32 + 1 << ARGT_IMM64;
	uasm.mem_arg_mask = 1 << ARGT_M8 + 1 << ARGT_M16 + 1 << ARGT_M32 + 1 << ARGT_M64;

	uasm.table_16_32_entries = uasm.table_64_entries = 0;
	for (i = 0; i <= cmp.asm_hash->mask; i++)
	{
		tmph = cmp.asm_hash->body[i];
		while (tmph)
		{
			if (tmph->type == HTT_OPCODE && !(tmph->oc_flags & OCF_ALIAS))
			{
				tmpins = &tmph->ins;
				for (k = 0; k < tmph->inst_entry_count; k++)
				{
					uasm.table_16_32_entries++;
					if (!(tmpins->flags & IEF_NOT_IN_64_BIT))
						uasm.table_64_entries++;
					tmpins++;
				}
			}
			tmph = tmph->next;
		}
	}

	j1 = j2 = 0;
	uasm.table_16_32 = MAlloc(uasm.table_16_32_entries * sizeof(U8 *));
	uasm.table_64	 = MAlloc(uasm.table_64_entries    * sizeof(U8 *));
	for (i = 0; i <= cmp.asm_hash->mask; i++)
	{
		tmph = cmp.asm_hash->body[i];
		while (tmph)
		{
			if (tmph->type == HTT_OPCODE && !(tmph->oc_flags & OCF_ALIAS))
			{
				tmpins = &tmph->ins;
				for (k = 0; k < tmph->inst_entry_count; k++)
				{
					uasm.table_16_32[j1++] = tmpins;
					if (!(tmpins->flags & IEF_NOT_IN_64_BIT))
						uasm.table_64[j2++] = tmpins;
					tmpins++;
				}
			}
			tmph = tmph->next;
		}
	}
	QuickSortI64(uasm.table_16_32, uasm.table_16_32_entries,  &InstEntriesCompare);
	QuickSortI64(uasm.table_64	 , uasm.table_64_entries 	, &InstEntriesCompare);
}

U0 Ui(U8 *buf, U8 **_rip, I64 seg_size=64, I64 *_jmp_dst=NULL, Bool just_ins=FALSE)
{//Unassembles one inst
	I64			 i, disp, imm, opsize, opadd, arg1, arg2, reloced_arg1, reloced_arg2,
				 arg1_size = 0, arg2_size = 0, reloced_arg1_size, reloced_arg2_size,
				 ModrM = -1, SIB = -1, scale, r1, r2, Mod = -1, RM1 = -1, RM2 = -1, REX = -1, REX_r = 0, REX_x = 0, REX_b = 0;
	Bool		 cont;
	CInst		*tmpins, *tmpins2;
	CHashOpcode	*tmpo;
	U8			*rip = *_rip, *ptr, *reloced_arg1_st, *reloced_arg2_st, *bin_data_area1, *bin_data_area2,
				 line1[512], line2[512], buf2[512], arg1_st[512], arg2_st[512], seg_overrides[32];

	if (_jmp_dst)
		*_jmp_dst = -1;
	if (seg_size == 16)
	{
		opsize = 16;
		opadd = 16;
	}
	else if (seg_size == 32)
	{
		opsize = 32;
		opadd = 32;
	}
	else
	{
		opsize = 32;
		opadd = 64;
	}
	*arg1_st = 0;
	*arg2_st = 0;
	if (!IsRaw && PutSrcLink(rip, 1, line1))
		CatPrint(line1, "\n");
	else
		*line1 = 0;

	StrPrint(line1 + StrLen(line1), "%24tp ", rip);
	bin_data_area1 = line1 + StrLen(line1);
	for (i = 0; i < 6; i++)
		CatPrint(line1, "%02X", rip[i]);
	CatPrint(line1, " ");

	StrPrint(line2, "%24tp ", rip + 6);
	bin_data_area2 = line2 + StrLen(line2);
	for (i = 6; i < 12; i++)
		CatPrint(line2, "%02X", rip[i]);

	*seg_overrides = 0;
	cont = TRUE;
	while (TRUE)
	{
		switch (*rip)
		{
			case 0x2E:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "CS:");
				break;

			case 0x36:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "SS:");
				break;

			case 0x3E:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "DS:");
				break;

			case 0x26:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "ES:");
				break;

			case 0x64:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "FS:");
				break;

			case 0x65:
				if (StrLen(seg_overrides) < 24)
					CatPrint(seg_overrides, "GS:");
				break;

			case OC_OP_SIZE_PREFIX:
				if (opsize == 16)
					opsize = 32;
				else
					opsize = 16;
				break;

			case OC_ADDR_SIZE_PREFIX:
				if (opadd == 16)
					opadd = 32;
				else
					opadd = 16;
				break;

			case 0x40...0x4F:
				if (seg_size == 64)
				{
					REX = *rip;
					if (REX >= 0x48)
						opsize = 64;
					REX_b = Bt(&REX, 0) << 3;
					REX_x = Bt(&REX, 1) << 3;
					REX_r = Bt(&REX, 2) << 3;
					break;
				} //Fall thru if !64
			default:
				cont = FALSE;
		}
		if (cont)
			rip++;
		else
			break;
	}

	tmpins = InstEntryFind(rip, opsize, seg_size);
	if (opsize == 32 && seg_size == 64)
	{
		tmpins2 = InstEntryFind(rip, 64, seg_size);
		if (tmpins2 != tmpins && tmpins2->flags & IEF_REX_ONLY_R8_R15 || tmpins2->flags & IEF_REX_XOR_LIKE &&
				rip[1] >> 3 & 7 == rip[1] & 7)
			tmpins = tmpins2;
	}

	rip += tmpins->opcode_count;
	tmpo = tmpins(U8 *) - tmpins->ins_entry_num * sizeof(CInst)
	-offset(CHashOpcode.ins);
	if (just_ins)
		*line1 = 0;
	CatPrint(line1, tmpo->str);

	arg1 = tmpins->arg1;
	arg2 = tmpins->arg2;

	if (arg1_size = tmpins->size1)
	{
		if (Bt(&uasm.signed_arg_mask, arg1))
			CatPrint(arg1_st, "I%d ", arg1_size);
		else
			CatPrint(arg1_st, "U%d ", arg1_size);
	}

	if (arg2_size = tmpins->size2)
	{
		if (Bt(&uasm.signed_arg_mask, arg2))
			CatPrint(arg2_st, "I%d ", arg2_size);
		else
			CatPrint(arg2_st, "U%d ", arg2_size);
	}

	if (tmpins->flags & IEF_PLUS_OPCODE)
	{
		rip--;
		RM1 = *rip++ - tmpins->opcode[tmpins->opcode_count - 1] + REX_b;
		ptr = NULL;
		if (ARGT_R8 <= arg1 <= ARGT_R64)
		{
			if (arg1_size == 8)
			{
				if (REX != -1)
					ptr = "ST_U8_REX_REGS";
				else
					ptr = "ST_U8_REGS";
			}
			else if (arg1_size == 16)
				ptr = "ST_U16_REGS";
			else if (arg1_size == 32)
				ptr="ST_U32_REGS";
			else if (arg1_size == 64)
				ptr = "ST_U64_REGS";
			if (ptr)
				CatPrint(arg1_st, "%Z", RM1, ptr);
		}
		else
		{
			if (arg2_size == 8)
			{
				if (REX != -1)
					ptr = "ST_U8_REX_REGS";
				else
					ptr = "ST_U8_REGS";
			}
			else if (arg2_size == 16)
				ptr = "ST_U16_REGS";
			else if (arg2_size == 32)
				ptr = "ST_U32_REGS";
			else if (arg2_size == 64)
				ptr = "ST_U64_REGS";
			if (ptr)
				CatPrint(arg2_st, "%Z", RM1, ptr);
		}
	}

	if (ARGT_RM8 <= arg1 <= ARGT_RM64 || ARGT_M8 <= arg1 <= ARGT_M64 ||
		ARGT_RM8 <= arg2 <= ARGT_RM64 || ARGT_M8 <= arg2 <= ARGT_M64)
	{
		if (ARGT_RM8 <= arg2 <= ARGT_RM64 || ARGT_M8 <= arg2 <= ARGT_M64)
		{
			reloced_arg1 = arg2;
			reloced_arg2 = arg1;
			reloced_arg1_size = arg2_size;
			reloced_arg2_size = arg1_size;
			reloced_arg1_st = arg2_st;
			reloced_arg2_st = arg1_st;
		}
		else
		{
			reloced_arg1 = arg1;
			reloced_arg2 = arg2;
			reloced_arg1_size = arg1_size;
			reloced_arg2_size = arg2_size;
			reloced_arg1_st = arg1_st;
			reloced_arg2_st = arg2_st;
		}

		CatPrint(reloced_arg1_st, seg_overrides);
		ModrM = *rip++;
		Mod = ModrM >> 6 & 3;
		RM1 = ModrM & 7 + REX_b;
		RM2 = ModrM >> 3 & 7 + REX_r;
		if (Mod < 3 && RM1 & 7 == 4)
			SIB = *rip++;
		if (Mod == 1) {
			disp = *rip(U8 *)++;
			CatPrint(reloced_arg1_st, "%02X", disp);
		}
		else if (Mod == 2)
		{
			disp = *rip(U32 *)++;
			CatPrint(reloced_arg1_st, "%08X", disp);
		}
		if (tmpins->slash_val < 8)
			RM2 = -1;
		else
		{
			ptr = NULL;
			if (reloced_arg2 == ARGT_SREG)
			{
				if (RM2 <= 5)
					ptr = "ST_SEG_REGS";
			}
			else if (!(ARGT_IMM8 <= reloced_arg2 <= ARGT_IMM64) && !(ARGT_UIMM8 <= reloced_arg2 <= ARGT_UIMM64))
			{
				if (reloced_arg2_size == 8)
				{
					if (REX != -1)
						ptr = "ST_U8_REX_REGS";
					else
						ptr = "ST_U8_REGS";
				}
				else if (reloced_arg2_size == 16)
					ptr = "ST_U16_REGS";
				else if (reloced_arg2_size == 32)
					ptr = "ST_U32_REGS";
				else if (reloced_arg2_size == 64)
					ptr = "ST_U64_REGS";
			}
			if (ptr)
				CatPrint(reloced_arg2_st, "%Z", RM2, ptr);
		}
		if (RM1 & 7 == 5 && !Mod)
		{
			disp = *rip(I32 *)++;
			if (seg_size == 64)
			{
				disp += rip;
				if (reloced_arg2 == ARGT_IMM8 || reloced_arg2 == ARGT_UIMM8)
					disp++;
				else if (reloced_arg2 == ARGT_IMM16 || reloced_arg2 == ARGT_UIMM16)
					disp += 2;
				else if (reloced_arg2 == ARGT_IMM32 || reloced_arg2 == ARGT_UIMM32)
					disp += 4;
				else if (reloced_arg2 == ARGT_IMM64 || reloced_arg2 == ARGT_UIMM64)
					disp += 8;
			}
			CatPrint(reloced_arg1_st, "[%X]", disp);
			RM1 = -1;
		}
		else
		{
			if (Mod < 3)
			{
				if (RM1 & 7 == 4)
				{
					RM1 = -1;
					r1 = SIB & 7 + REX_b;
					r2 = SIB >> 3 & 7 + REX_x;
					scale = SIB >> 6 & 3;
					if (scale == 3)
						scale = 8;
					else if (scale == 2)
						scale = 4;
					else if (scale == 1)
						scale = 2;
					else
						scale = 1;
					if (seg_size == 64)
						ptr = "ST_U64_REGS";
					else
						ptr = "ST_U32_REGS";
					if (r1 == REG_RBP && !Mod)
					{
						disp = *rip(U32 *)++;
						CatPrint(reloced_arg1_st, "%08X[%Z*%d]", disp, r2, ptr, scale);
					}
					else if (r2 == 4)
						CatPrint(reloced_arg1_st, "[%Z]", r1, ptr);
					else
						CatPrint(reloced_arg1_st, "[%Z+%Z*%d]", r1, ptr, r2, ptr, scale);
				}
				else
				{
					if (opadd == 16)
						ptr = "ST_U16_REGS";
					else if (opadd == 32)
						ptr = "ST_U32_REGS";
					else
						ptr = "ST_U64_REGS";
					CatPrint(reloced_arg1_st, "[%Z]", RM1, ptr);
				}
			}
			else
			{
				ptr = NULL;
				if (reloced_arg1_size == 8)
				{
					if (REX != -1)
						ptr = "ST_U8_REX_REGS";
					else
						ptr = "ST_U8_REGS";
				}
				else if (reloced_arg1_size == 16)
					ptr = "ST_U16_REGS";
				else if (reloced_arg1_size == 32)
					ptr = "ST_U32_REGS";
				else if (reloced_arg1_size == 64)
					ptr = "ST_U64_REGS";
				if (ptr)
					CatPrint(reloced_arg1_st, DefineSub(RM1, ptr));
			}
		}
	}

	switch (arg1)
	{
		case ARGT_IMM8:
		case ARGT_UIMM8:
			imm = *rip(U8 *)++;
			CatPrint(arg1_st, "%02X", imm);
			if (tmpins->opcode[0] == 0xCD && (ptr = DefineSub(imm, "ST_INT_NAMES")))
				CatPrint(arg1_st, " %s", ptr);
			break;

		case ARGT_IMM16:
		case ARGT_UIMM16:
			CatPrint(arg1_st, "%04X", *rip(U16 *)++);
			break;

		case ARGT_IMM32:
		case ARGT_UIMM32:
			CatPrint(arg1_st, "%08X", *rip(U32 *)++);
			break;

		case ARGT_IMM64:
		case ARGT_UIMM64:
			CatPrint(arg1_st, "%016X", *rip(I64 *)++);
			break;
		start:
			case ARGT_REL8:
				disp = *rip(I8 *)++;
				break;

			case ARGT_REL16:
				disp = *rip(I16 *)++;
				break;

			case ARGT_REL32:
				disp = *rip(I32 *)++;
				break;
		end:
			disp += rip;
			if (IsDebugMode)
				CatPrint(arg1_st, "%p ", disp);
			else if (PutSrcLink(disp, 512, buf2))
				CatPrint(arg1_st, "%s ", buf2);
			else
				CatPrint(arg1_st, "%P ", disp);
			if (_jmp_dst)
				*_jmp_dst = disp;
			break;

		case ARGT_MOFFS8...ARGT_MOFFS64:
			CatPrint(arg1_st, seg_overrides);
			if (arg1_size == 8)
				disp = *rip(U8 *)++;
			else if (opadd == 16)
				disp = *rip(U16 *)++;
			else
				disp = *rip(U32 *)++;
			CatPrint(arg1_st, "[%X]",disp);
			break;

		case ARGT_AL ... ARGT_DX:
		case ARGT_SS ... ARGT_ST0:
			CatPrint(arg1_st, "%z", arg1 - ARGT_AL, "AL\0AX\0EAX\0RAX\0CL\0DX\0 \0 \0SS\0DS\0ES\0FS\0GS\0CS\0ST0\0");
			break;

		case ARGT_STI:
			rip--;
			CatPrint(arg1_st, "%Z", *rip++ - tmpins->opcode[tmpins->opcode_count - 1], "ST_FSTACK_REGS");
			break;
	}

	switch (arg2)
	{
		case ARGT_IMM8:
		case ARGT_UIMM8:
			CatPrint(arg2_st, "%02X", *rip(U8 *)++);
			break;

		case ARGT_IMM16:
		case ARGT_UIMM16:
			CatPrint(arg2_st, "%04X", *rip(U16 *)++);
			break;

		case ARGT_IMM32:
		case ARGT_UIMM32:
			CatPrint(arg2_st, "%08X", *rip(U32 *)++);
			break;

		case ARGT_IMM64:
		case ARGT_UIMM64:
			CatPrint(arg2_st, "%016X", *rip(I64 *)++);
			break;

		case ARGT_MOFFS8...ARGT_MOFFS64:
			CatPrint(arg2_st, seg_overrides);
			if (arg2_size == 8)
				disp = *rip(U8 *)++;
			else if (opadd == 16)
				disp = *rip(U16 *)++;
			else
				disp = *rip(U32 *)++;
			CatPrint(arg2_st, "[%X]", disp);
			break;

		case ARGT_AL ... ARGT_DX:
		case ARGT_SS ... ARGT_ST0:
			CatPrint(arg2_st, "%z",arg2 - ARGT_AL, "AL\0AX\0EAX\0RAX\0CL\0DX\0 \0 \0SS\0DS\0ES\0FS\0GS\0CS\0ST0\0");
			break;

		case ARGT_STI:
			rip--;
			CatPrint(arg2_st, "%Z", *rip++ - tmpins->opcode[tmpins->opcode_count - 1], "ST_FSTACK_REGS");
			break;
	}
	if (tmpins->flags & IEF_ENDING_ZERO)
		rip++;

	if (*arg1_st)
		CatPrint(line1, "\t%s", arg1_st);
	if (*arg2_st)
		CatPrint(line1, ",%s", arg2_st);
	CatPrint(line1, "\n");
	CatPrint(line2, "\n");
	if (!just_ins)
	{
		for (i = rip - (*_rip)(I64); i < 6; i++)
		{
			bin_data_area1[i << 1]	   = CH_SPACE;
			bin_data_area1[i << 1 + 1] = CH_SPACE;
		}
		for (i = rip - (*_rip)(I64); i < 12; i++)
		{
			bin_data_area2[(i - 6) << 1]     = CH_SPACE;
			bin_data_area2[(i - 6) << 1 + 1] = CH_SPACE;
		}
	}
	StrCopy(buf, line1);
	if (!just_ins && rip - (*_rip)(I64) > 6)
		CatPrint(buf, line2);
	*_rip = rip;
}

U8 *U(U8 *rip, I64 count=20, I64 seg_size=64)
{//Unassembles a num of insts.
	I64 i;
	U8  buf[1024];

	if (seg_size == 16)
		PrintWarn("16-bit unassembly is not well supported.\n");
	"$$HL,1$$";
	for (i = 0; i < count; i++)
	{
		Ui(buf, &rip, seg_size);
		"%s", buf;
	}
	"$$HL,0$$";

	return rip;
}

I64 Un(U8 *rip, I64 count=0x80, I64 seg_size=64)
{//Unassembles a num of bytes
	I64 i = 0;
	U8  buf[1024], *end_rip = rip(I64) + count;

	if (seg_size == 16)
		PrintWarn("16-bit unassembly is not well supported.\n");
	"$$HL,1$$";
	while (rip < end_rip)
	{
		Ui(buf, &rip, seg_size);
		"%s", buf;
		i++;
	}
	"$$HL,0$$";

	return i;
}
