File:  [Research Unix] / researchv9 / cmd / adb / 68v / das.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

/*
 * disassemble 68020 opcodes
 */

#include "defs.h"
#include "optab.h"

#define	SZ_MASK		00300
#define	SZ_SHIFT	6		/* bits  (7-6) */

static struct opmask {
	long mask;
	int shift;
} opmask[] = {
	0,		0,	/* DIG	0   ignore this address */
	0x0000003f,	0,	/* DEA	1   E.A. to low order 6 bits */
	0x00000007,	0,	/* DRG	2   register to low order 3 bits */
	0x00000e00,	9,	/* DRGL	3   register to bits 11-9 */
	0x000000ff,	0,	/* DBR	4   branch offset (short) */
	0x000000ff,	0,	/* DMQ	5   move-quick 8-bit value */
	0x00000e00,	9,	/* DAQ	6   add-quick 3-bit value in 11-9 */
	0,		0,	/* DIM	7   Immediate value, according to size */
	0x00000fc0,	6,	/* DEAM	8   E.A. to bits 11-6 as in move */
	0,		0,	/* DBCC	9   branch address as in "dbcc" */
	0x0000000f,	0,	/* DTRAP 10 immediate in low 4 bits */
	0x00070000,	16,	/* D2L	11  register to bits 0-2 of next word */
	0x70000000,	16+12,	/* D2H	12  register to bits 12-14 of next word */
	0x001f0000,	16,	/* DBL	13  qty in bits 0-5 of next word */
	0x07c00000,	16+6,	/* DBH	14  qty in bits 6-11 of next word */
	0x0fff0000,	16,	/* DCR	15  control reg a bit combination in 0-11 */
};

static int dsp;

printins(isp)
int isp;
{
	register struct optab *op;
	register int i;
	register WORD w, w1;
	int w1f = 0;
	extern struct optab optab[];

	dsp = isp;
	w = stow(sget(dot, isp));
	chkerr();
	for (op = optab; op->opname; op++) {
		if ((w & op->mask) != op->opcode)
			continue;
		if ((op->flags & I2W) == 0)
			break;		/* 1-word match */
		if (w1f == 0) {
			w1 = stow(sget(dot+2, isp));
			w1f++;
		}
		if ((w1 & op->mk2) == op->op2)
			break;		/* 2-word match */
	}
	if (op->opname == NULL) {
		printf("\tnumber\t%R", w);
		dotinc = 2;
		return;
	}
	w &= 0xffff;
	if ((op->flags & I2W) == 0)
		dotinc = 2;
	else {
		w |= w1 << 16;
		dotinc = 4;
	}
	printf("\t%s", op->opname);
	for (i = 0; i < op->nrand; i++) {
		if (i == 0)
			printf("\t");
		else
			printf(",");
		dorand(w, op->rand[i], op->flags & SZ);
	}
}

#define	ENSIGN(x)	((WORD)(short)(x))

static
dorand(w, rand, size)
register WORD w;
register short rand;
int size;
{
	struct opmask *om;
	WORD val;

	om = &opmask[rand & DMASK];
	if (om->mask)
		val = (w & om->mask) >> om->shift;
	switch(rand & DMASK) {
	case DEA:	/* effective address spec */
		ea(val >> 3, val & 07, size);
		return;

	case DRG:	/* abs register */
	case DRGL:
	case D2H:
	case D2L:
		if (rand & ADEC)
			printf("-(%%a%d)", val);
		else if (rand & AINC)
			printf("(%%a%d)+", val);
		else if (rand & AAREG)
			printf("%%a%d", val);
		else if (rand & ADREG)
			printf("%%d%d", val);
		else
			printf("DRGgok");
		return;

	case DBR:	/* branch displacement */
		if (val == 0) {
			val = stow(sget(dot+dotinc, dsp));
			if (val & 0x8000)
				val |= ~0xffff;
			dotinc += 2;
		}
		else if (val == 0xff) {
			val = ltow(lget(dot+dotinc, dsp));
			dotinc += 4;
		}
		else if (val & 0x80)
			val |= ~0xff;
		val += dot + 2;
		psymoff(val, dsp, "");
		return;

	case DMQ:	/* 8-bit quick */
	case DBH:	/* 6-bit strange quick */
	case DTRAP:	/* 4-bit quick */
	case DBL:	/* other 6-bit strange quick */
		printf("&");
		psymoff(val, dsp, "");
		return;

	case DAQ:	/* silly 3-bit immediate */
		if (val == 0)
			val = 8;
		printf("&");
		psymoff(val, dsp, "");
		return;

	case DIM:	/* immediate */
		if (rand & AONE) {
			printf("&1");
			return;
		}
		if (rand & AWORD)
			size = W;
		switch (size) {
		case B:
			val = ENSIGN(ctow(cget(dot+dotinc, dsp)));
			dotinc += 2;	/* sic */
			break;

		case W:
			val = ENSIGN(stow(sget(dot+dotinc, dsp)));
			dotinc += 2;
			break;

		case L:
			val = stow(sget(dot+dotinc, dsp));
			dotinc += 2;
			break;
		}
		printf("&");
		psymoff(val, dsp, "");
		return;

	case DEAM:	/* assinine backwards ea */
		ea(val & 07, val >> 3, size);
		return;

	case DBCC:	/* branch displacement a la dbcc */
		val = stow(sget(dot+dotinc, dsp));
		dotinc += 2;
		val += dot + 2;
		psymoff(val, dsp, "");
		return;

	case DCR:
		dcr(val);
		return;

	case DSREG:
		if (rand & C)
			printf("%%ccr");
		else if (rand & SR)
			printf("%%sr");
		else if (rand & U)
			printf("%%usp");
		else
			printf("%%GOKdsreg");
		return;
	}
	printf("GOK");
}

static
ea(mode, reg, size)
int mode, reg;
{
	WORD disp;

	switch(mode){
	case 0:
		printf("%%d%d", reg);
		return;

	case 1:
		printf("%%a%d", reg);
		return;

	case 2:
		printf("(%%a%d)", reg);
		return;

	case 3:
		printf("(%%a%d)+", reg);
		return;

	case 4:
		printf("-(%%a%d)", reg);
		return;

	case 5:
		disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
		dotinc += 2;
		psymoff(disp, dsp, "");
		printf("(%%a%d)", reg);
		return;

	case 6:
		doindex();	/* ugh */
		return;

	case 7:
		switch (reg) {
		case 0:
			disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
			dotinc += 2;
			psymoff(disp, dsp, "");
			return;

		case 1:
			disp = ltow(lget(dot+dotinc, dsp));
			dotinc += 4;
			psymoff(disp, dsp, "");
			return;

		case 4:
			switch(size) {
			case B:
				disp = ENSIGN(ctow(cget(dot+dotinc, dsp)));
				dotinc += 2;	/* sic */
				psymoff(disp, dsp, "");
				return;

			case W:
				disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
				dotinc += 2;
				psymoff(disp, dsp, "");
				return;

			case L:
				disp = ltow(lget(dot+dotinc, dsp));
				dotinc += 4;
				psymoff(disp, dsp, "");
				return;
			}
		}
	}
	printf("gok%d:%d", mode, reg);
}

static
doindex()
{
	register WORD w;
	register WORD base, outer;

	base = outer = 0;
	w = stow(sget(dot+dotinc, dsp));
	dotinc += 2;
	if ((w & 0x80) == 0) {		/* brief format */
		base = w & 0x7f;
		if (base & 0x40)
			base |= ~0x7f;
	}
	else {				/* full format */
		switch (w & 0x30) {
		case 0:			/* ugh */
		case 0x10:		/* null displacement */
			break;

		case 0x20:
			base = stow(sget(dot+dotinc, dsp));
			outer = stow(sget(dot+dotinc+2, dsp));
			dotinc += 4;
			break;

		case 0x30:
			base = ltow(lget(dot+dotinc, dsp));
			outer = ltow(lget(dot+dotinc+4, dsp));
			dotinc += 8;
			break;
		}
	}
	/* stuff */
	printf("index");
}

static
dcr(reg)
int reg;
{

	switch (reg) {
	case 0x000:
		printf("%sfc");
		return;

	case 0x001:
		printf("%dfc");
		return;

	case 0x002:
		printf("%cacr");
		return;

	case 0x800:
		printf("%usp");
		return;

	case 0x801:
		printf("%vbr");
		return;

	case 0x802:
		printf("%caar");
		return;

	case 0x803:
		printf("%msp");
		return;

	case 0x804:
		printf("%isp");
		return;

	default:
		printf("%cr%x", reg);
		return;
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.