!	UX -- Unassemble Tcode files.
!	Copyright (C) 1997,1998 Nils M Holm

const	BUFSIZE	=	1025;
const	TEXTLEN	=	129;

var	Buffer[BUFSIZE], Cp, Ep;
var	Opcodes;
var	Addr;


const	ICLAB=129, IDLAB=130, IDECL=131, IDATA=132, ICREF=133,
	IDREF=134, ISTR=135, IPSTR=136, IINIT=137, IHDR=010,
	IEND=011,

	INEG=012, ILNOT=013, IBNOT=014, IPOP=015, ICLEAN=144,
	INOP=017,

	IINDB=018, IIND=019, IDREFB=020, IDEREF=021, IINCG=150,
	IINCL=151,

	IMUL=024, IDIV=025, IMOD=026, IADD=027, ISUB=028, IBAND=029,
	IBOR=030, IBXOR=031,

	IBSHL=032, IBSHR=033, IEQU=034, INEQU=035, ILESS=036,
	IGRTR=037, ILTEQ=038, IGTEQ=039,

	ILDG=168, ILDGV=169, ILDL=170, ILDLV=171, ILDLAB=172,

	INUM=173, ISAVG=174, ISAVL=175, ISTORE=048, ISTORB=049,

	ISTACK=178, ICALL=179, ICALR=52, IEXEC=181, IBRF=182,
	IBRT=183, INBRF=184, INBRT=185, IJUMP=186, IUNEXT=187,
	IDNEXT=188, IHALT=061,

	IPUB=190, IEXT=191,

	IUMUL=64, IUDIV=65, IULESS=66, IUGRTR=67, IULTEQ=68,
	IUGTEQ=69,

	IDUP = 70, ISWAP = 71,

	ILINE = 200, IGSYM = 201, ILSYM = 202,

	IENDOFSET=75;


init() do
	Ep := 1;
	Cp := 1;
	Addr := 0;
	Opcodes := [
		"OOPS!",
		"CLAB", "DLAB", "DECL", "DATA", "CREF",
		"DREF", "STR", "PSTR", "INIT", "HDR",
		"END",
		"NEG", "LNOT", "BNOT", "POP", "CLEAN",
		"NOP",
		"INDB", "IND", "DREFB", "DEREF", "INCG",
		"INCL",
		"MUL", "DIV", "MOD", "ADD", "SUB",
		"BAND", "BOR", "BXOR",
		"BSHL", "BSHR", "EQU", "NEQU", "LESS",
		"GRTR", "LTEQ", "GTEQ",
		"LDG", "LDGV", "LDL", "LDLV", "LDLAB",
		"NUM", "SAVG", "SAVL", "STORE", "STORB",
		"STACK", "CALL", "CALR", "EXEC", "BRF",
		"BRT", "NBRF", "NBRT", "JUMP", "UNEXT",
		"DNEXT", "HALT",
		"PUB", "EXT",
		"UMUL", "UDIV", "ULESS", "UGRTR", "ULTEQ",
		"UGTEQ",
		"DUP", "SWAP",
		"LINE", "GSYM", "LSYM"
	];
end


rdch() do
	if (Cp >= Ep) do
		Ep := reads(Buffer, BUFSIZE-1);
		Cp := 0;
		if (\Ep) return %1;
	end
	Cp := Cp+1;
	Addr := Addr+1;
	return Buffer[Cp-1];
end


disasm() do
	var	op, o2, arg, i, j, ch;
	var	sbuf[TEXTLEN];
	var	ab;

	ab := ntoa(Addr, 5);
	op := rdch();
	if (op = %1) return 0;
	writes(ab); writes("\t");
	o2 := op & ~128;
	if (o2 < 1 \/ o2 >= IENDOFSET) do
		writes("UX: invalid opcode: ");
		writes(ntoa(op, 0));
		newline();
		halt;
	end
	if (op & 128) do
		arg := rdch();
		arg := rdch() << 8 | arg;
	end
	writes(Opcodes[o2]);
	if (op & 128) do
		if (arg > 32767) arg := arg-(16384<<2);	! 32-bit hack!
		writes("\t"); writes(ntoa(arg, 6));
	end
	ie (op = IINCL \/ op = IINCG \/ op = IINIT /\ arg > 1) do
		arg := rdch();
		arg := rdch() << 8 | arg;
		if (arg > 32767) arg := arg-(16384<<2);	! 32-bit hack!
		writes("\t"); writes(ntoa(arg, 6));
	end
	else if (op = ISTR \/ op = IPSTR \/ op = IPUB \/ op = IEXT \/
		op = IGSYM \/ op = ILSYM) do
		writes("\t\q");
		for (i=0, arg) sbuf[i] := rdch();
		sbuf[i] := 0;
		writes(sbuf);
		writes("\q");
		if (op = IGSYM \/ op = ILSYM) do
			arg := rdch();
			arg := rdch() << 8 | arg;
			if (arg > 32767) arg := arg-(16384<<2);	! 32-bit hack!
			writes("\t"); writes(ntoa(arg, 6));
		end
	end
	newline();
end


do
	init();
	while (Ep) disasm();
end

