h40898
s 00526/00000/00000
d D 1.1 82/08/02 15:15:36 cecily 1 0
e
u
U
t
T
I 1
#include "defs.h"

L_INT		dot;
INT		dotinc;
L_INT		var[];

/*
 * instruction formats
 */
#define	SF	1
#define RR      2
#define	RX1	3
#define	RX2	4
#define	RX3	5
#define	RI1	6
#define	RI2	7

#define	BT	0x10	/* branch instruction (true)	*/
#define	BF	0x20	/* branch instruction (false)	*/
#define	BBACK	0x40	/* branch backwards short	*/
#define BAL	0x80	/* branch & link */
#define RXRX    0x100   /* RX/RX format                 */

/*
 * structure for information about disassembled instruction
 */
INSTR	instr;

/*
 * Perkin-Elmer opcode mnemonics & types
 */
struct {
	char *opmnem;
	int  optype;
} optab[] = {
	 0,	0,
	"balr",	RR,
	"btcr",	BT+RR,
	"bfcr",	BF+RR,
	"nr",	RR,
	"clr",	RR,
	"or",	RR,
	"xr",	RR,
	"lr",	RR,
	"cr",	RR,
	"ar",	RR,
	"sr",	RR,
	"mhr",	RR,
	"dhr",	RR,
	 0,	0,
	 0,	0,
	"srls",	SF,
	"slls",	SF,
	"chvr",	RR,
	"lper", RR,
	 0,	0,
	"lger", RR,
	"lgdr", RR,
	"lcer", RR,
	"lpsr",	RR,
	 0,	0,
	 0,	0,
	 0,	0,
	"mr",	RR,
	"dr",	RR,
	 0,	0,
	 0,	0,
	"btbs",	BT+BBACK+SF,
	"btfs",	BT+SF,
	"bfbs",	BF+BBACK+SF,
	"bffs",	BF+SF,
	"lis",	SF,
	"lcs",	SF,
	"ais",	SF,
	"sis",	SF,
	"ler",	RR,
	"cer",	RR,
	"aer",	RR,
	"ser",	RR,
	"mer",	RR,
	"der",	RR,
	"fxr",	RR,
	"flr",	RR,
	 0,     0,
	 0,     0,
	"pbr",  RR,
	"lpdr", RR,
	"exhr",	RR,
	 0,	0,
	 0,	0,
	"lcdr", RR,
	"ldr",  RR,
	"cdr",  RR,
	"adr",  RR,
	"sdr",  RR,
	"mdr",  RR,
	"ddr",  RR,
	"fxdr", RR,
	"fldr", RR,
	"sth",	RX1,
	"bal",	BAL+RX1,
	"btc",	BT+RX1,
	"bfc",	BF+RX1,
	"nh",	RX1,
	"clh",	RX1,
	"oh",	RX1,
	"xh",	RX1,
	"lh",	RX1,
	"ch",	RX1,
	"ah",	RX1,
	"sh",	RX1,
	"mh",	RX1,
	"dh",	RX1,
	 0,	0,
	 0,	0,
	"st",	RX1,
	"am",	RX1,
	 0,     0,
	 0,     0,
	"n",	RX1,
	"cl",	RX1,
	"o",	RX1,
	"x",	RX1,
	"l",	RX1,
	"c",	RX1,
	"a",	RX1,
	"s",	RX1,
	"m",	RX1,
	"d",	RX1,
	"cr12",	RX1,
	"cr16",	RX1,
	"ste",	RX1,
	"ahm",	RX1,
	"pb",   RX1,
	"lra",  RX1,
	"atl",	RX1,
	"abl",	RX1,
	"rtl",	RX1,
	"rbl",	RX1,
	"le",	RX1,
	"ce",	RX1,
	"ae",	RX1,
	"se",	RX1,
	"me",	RX1,
	"de",	RX1,
	"stbp", RX1,
	"lpb",  RX1,
	"std",  RX1,
	"stme",	RX1,
	"lme",	RX1,
	"lhl",	RX1,
	"tbt",	RX1,
	"sbt",	RX1,
	"rbt",	RX1,
	"cbt",	RX1,
	"ld",   RX1,
	"cd",   RX1,
	"ad",   RX1,
	"sd",   RX1,
	"md",   RX1,
	"dd",   RX1,
	"stmd", RX1,
	"lmd",  RX1,
	 0,	0,
	 0,	0,
	"stde", RX1,
	 0,	0,
	"led",  RX1,
	 0,	0,
	 0,	0,
	"lde",  RX1,
	"brk",  SF,
	 0,	0,
	 0,	0,
	 0,	0,
	"",     RXRX+RX1,
	 0,	0,
	 0,	0,
	 0,	0,
	"srhls",SF,
	"slhls",SF,
	"stbr",	RR,
	"lbr",	RR,
	"exbr",	RR,
	"epsr",	RR,
	"wbr",	RR,
	"rbr",	RR,
	"whr",	RR,
	"rhr",	RR,
	"wdr",	RR,
	"rdr",	RR,
	 0,	0,
	"ssr",	RR,
	"ocr",	RR,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	"ledr", RR,
	"legr", RR,
	"ldgr", RR,
	"lder", RR,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0,
	"bxh",	RX1,
	"bxle",	RX1,
	"lpsw",	RX1,
	"thi",	RI1,
	"nhi",	RI1,
	"clhi",	RI1,
	"ohi",	RI1,
	"xhi",	RI1,
	"lhi",	RI1,
	"chi",	RI1,
	"ahi",	RI1,
	"shi",	RI1,
	"srhl",	RI1,
	"slhl",	RI1,
	"srha",	RI1,
	"slha",	RI1,
	"stm",	RX1,
	"lm",	RX1,
	"stb",	RX1,
	"lb",	RX1,
	"clb",	RX1,
	"al",	RX1,
	"wb",	RX1,
	"rb",	RX1,
	"wh",	RX1,
	"rh",	RX1,
	"wd",	RX1,
	"rd",	RX1,
	 0,	0,
	"ss",	RX1,
	"oc",	RX1,
	"psf",  RX1,
	"ts",	RX1,
	"svc",	RX1,
	"sint",	RX1,
	"scp",	RX1,
	 0,	0,
	"bdcs", RX1,
	"la",	RX1,
	"tlat",	RX1,
	"rwdcs",RR,
	"ecs",  RI1,
	"rrl",	RI1,
	"rll",	RI1,
	"srl",	RI1,
	"sll",	RI1,
	"sra",	RI1,
	"sla",	RI1,
	 0,	0,
	 0,	0,
	 0,	0,
	"ti",	RI2,
	"ni",	RI2,
	"cli",	RI2,
	"oi",	RI2,
	"xi",	RI2,
	"li",	RI2,
	"ci",	RI2,
	"ai",	RI2,
	"si",	RI2,
	 0,	0,
	 0,	0,
	 0,	0,
	 0,	0
};

/*
 * Branch condition names
 */
struct {
	char *true;
	char *false;
} brtab[] = {
	"nop",	"b",
	"bm",	"bnm",
	"bp",	"bnp",
	"bne",	"be",
	"bo",	"bno",
	0,	0,
	0,	0,
	0,	0,
	"bl",	"bnl",
	0,	0,
	0,	0,
	0,	0,
	0,	0,
	0,	0,
	0,	0,
	0,	0
};

/*
 * Names of registers
 */
char *regname[16] = {
	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp",
	"r8", "r9", "ra", "rb", "rc", "rd", "re", "rf"
};

/*
 * Disassemble instruction at loc in space idsp, whose first word is in ins
 * Return length of instruction
 */
disasm(loc, idsp, ins)
register int loc, ins;
{
	instr.op = ins>>24;
	instr.reg[0] = (ins>>20)&017;
	instr.reg[1] = (ins>>16)&017;
	instr.type = optab[instr.op].optype;
	switch (instr.type & 017) {

	case SF:
	case RR:
		return(2);

	case RI1:
		instr.disp = ins&0xffff;
		/* Propagate sign */
		if (ins&0x8000)
			instr.disp |= (-1)<<16;
		return(4);

	case RI2:
		instr.disp = get(loc+2, idsp);
		return(6);

	case RX1:
		ins = get(loc+2, idsp);
		switch(ins>>30) {

		/* RX2 -- negative offset */
		case 3:
			instr.type += RX2-RX1;
			instr.disp = ((-1)<<16) | (unsigned)ins>>16;
			instr.disp += loc + 4;
			return(4);
	
		/* RX2 -- positive offset */
		case 2: 
			instr.type += RX2-RX1;
			instr.disp = (ins>>16) & 0x7fff;
			instr.disp += loc + 4;
			return(4);
	
		/* RX1 */
		case 0:
			instr.disp = (unsigned)ins>>16;
			return(4);
	
		/* RX3 */
		case 1:
			instr.type += RX3-RX1;
			instr.reg[2] = (ins>>24) & 017;
			ins &= 0xffffff;
			if (ins & 0x800000)	/* negative offset */
				ins |= (0xff<<24);
			instr.disp = ins;
			return(6);
		}

	default:
		return(0);
	}
}

/*
 * Print instruction at dot in space idsp, whose first word has been fetched
 * into ins, in assembly format
 */

printins(f, idsp, ins)
register ins;
{
	register n;
	register type;
	register opmod;

	if ((dotinc = disasm(dot, idsp, ins)) == 0) {	/* illegal opcode */
		prints("???");
		dotinc = 2;
		return;
	}

	type = instr.type;
	n = instr.reg[0];

	if (type & RXRX) {                             /* RX-RX */
		opmod = (unsigned short)getsh(dot+dotinc, idsp) >> 8;
		printf("%s%8t", rxrxop(opmod));
		if (opmod & 0x80)
			printf("=%w,", n);
		else
			printf("%s,", regname[n]);
	} else if ((type & (BT|BF)) == 0)               /* non-branch */
		printf("%s%8t%s,", optab[instr.op].opmnem,
			regname[n]);
	else if (type&BT && (n = brtab[n].true) == 0 ||
	    type&BF && (n = brtab[n].false) == 0) {	/* branch */
		printf("%s%8t%w,", optab[instr.op].opmnem, instr.reg[0]);
	} else {					/* extended branch */
		prints(n);
		switch (type & 017) {

		case RR:
			printf("r%8t");
			break;

		case RX1:
		case RX2:
		case RX3:
			printf("%8t");
			break;

		case SF:
			printf("s%8t");
			n = instr.reg[1]<<1;
			instr.reg[1] = 0;
			if (type & BBACK)
				instr.disp = dot - n;
			else
				instr.disp = dot + n;
			type = (type & ~SF) | RX1;
			break;
		}
	}

	printdisp(type);

	if (type & RXRX) {
		ins = (ins & 0xff000000) | (get(dot+dotinc, idsp) & 0xffffff);
		dotinc += disasm(dot+dotinc, idsp, ins);
		type = instr.type;
		n = instr.reg[0];
		if (opmod & 0x40)
			printf(",=%w,", n);
		else
			printf(",%s,", regname[n]);
		printdisp(type);
	}
}

/*
 * Print operand part of instruction
 */
printdisp(type)
{
	register n;

	var[2] = var[1];
	switch (type & 017) {

	case RR:
		prints(regname[var[1] = instr.reg[1]]);
		break;

	case SF:
		psymoff(var[1] = instr.reg[1], NSYM, "");
		break;

	case RI1:
	case RI2:
	case RX1:
	case RX2:
		psymoff(var[1] = instr.disp, type&(BT|BF|BAL)? ISYM : DSYM, "");
		if (n = instr.reg[1])
			printf("(%s)", regname[n]);
		break;

	case RX3:
		psymoff(var[1] = instr.disp, type&(BT|BF|BAL)? ISYM : DSYM, "");
		if (n = instr.reg[1]) {
			printf("(%s", regname[n]);
			if (n = instr.reg[2])
				printf(",%s", regname[n]);
			prints(")");
		}
		break;

	}
}
/*
 * Generate name of RX/RX Function
 */
rxrxop(opmod)
{
	switch (opmod & 0x3f) {
		case 0x00:      return("mvtu");
		case 0x01:      return("move");
		case 0x02:      return("cpan");
		case 0x03:      return("pmv");
		case 0x04:      return("umv");
		case 0x21:      return("movep");
		case 0x22:      return("cpanp");
		case 0x23:      return("pmva");
		case 0x24:      return("umva");
		default:        return("rxrx");
	}
}
E 1
