4.4BSD/usr/src/old/adb/adb.tahoe/opset.c

Compare this file to the similar file:
Show the results in this format:

/*-
 * Copyright (c) 1991 The Regents of the University of California.
 * All rights reserved.
 *
 * This module is believed to contain source code proprietary to AT&T.
 * Use and redistribution is subject to the Berkeley Software License
 * Agreement and your Software Agreement with AT&T (Western Electric).
 */

#ifndef lint
static char sccsid[] = "@(#)opset.c	5.1 (Berkeley) 4/4/91";
#endif /* not lint */

/*
 * adb - instruction decoding
 */

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

struct	optab *ioptab[256];	/* index by opcode to optab */

/* set up ioptab */
mkioptab()
{
	register struct optab *p;

	for (p = optab; p->iname; p++)
		ioptab[p->val] = p;
}

/*
 * Print one instruction, and leave dotinc set to the number of bytes
 * it occupied.
 */
printins(space)
	int space;
{
	u_char ins;		/* instruction opcode */
	int argno;		/* argument index */
	register int mode;	/* mode */
	register int r;		/* register name */
	register int d;		/* assembled byte, word, long or float */
	register int dotoff;	/* offset from dot of current byte */
	register u_char *ap;
	register struct optab *ip;
	union {
		u_char	ub;
		char	b;
		short	w;
		int	l;
	} mem;
	extern char *syscalls[];
	extern int nsys;
#define	snarfbytes(nbytes) \
	(void) adbread(space, inkdot(dotoff), &mem.b, nbytes); \
	checkerr(); \
	dotoff += (nbytes)

	if (space == SP_NONE)
		ins = (u_char)dot;
	else {
		(void) adbread(space, dot, &ins, 1);
		checkerr();
	}
	if ((ip = ioptab[ins]) == NULL) {
		adbprintf("?%2x", ins);
		dotinc = 1;
		return;
	}
	adbprintf("%s%8t", ip->iname);
	dotoff = 1;
	ap = ip->argtype;
	for (argno = 0; argno < ip->nargs; argno++, ap++) {
		var[argno] = 0x80000000;
		if (argno != 0)
			printc(',');
again:
		if (*ap & ACCB)		/* branch displacement */
			mode = 0xAF + ((*ap & 7) << 5);
		else {
			snarfbytes(1);
			mode = mem.ub;
		}
		r = mode & 0xF;
		mode >>= 4;
		switch (mode) {

		case 0: case 1: case 2: case 3:
			/* short literal */
			d = mode << 4 | r;
			goto immed;

		case 4:	/* [r] */
			adbprintf("[%s]", regname[r]);
			goto again;

		case 5:	/* r */
			adbprintf("%s", regname[r]);
			continue;

		case 6:	/* (r) */
			adbprintf("(%s)", regname[r]);
			continue;

		case 7:	/* -(r) */
			adbprintf("-(%s)", regname[r]);
			continue;

		case 9:	/* *(r)+ */
			printc('*');
			/* FALLTHROUGH */

		case 8:	/* (r)+ */
			if (r == 0xf) {
				/* PC immediate */
				snarfbytes(4);
				d = mem.l;
			} else if (mode == 8 && (r == 8 || r == 9)) {
				/* absolute */
				snarfbytes((r & 1) + 1);
				d = r == 8 ? mem.b : mem.w;
			} else {
				adbprintf("(%s)+", regname[r]);
				continue;
			}
	immed:
			printc('$');
			if (ins == KCALL && (u_int)d < nsys && syscalls[d])
				prints(syscalls[d]);
			else
				adbprintf("%R", d);
			var[argno] = d;
			continue;

		case 0xA:	/* byte displacement */
		case 0xB:	/* byte displacement deferred */
			d = 1;
			break;

		case 0xC:	/* word displacement */
		case 0xD:	/* word displacement deferred */
			d = 2;
			break;

		case 0xE:	/* long displacement */
		case 0xF:	/* long displacement deferred */
			d = 4;
			break;
		}

		/* displacement or displacement deferred */
		if (mode & 1)
			printc('*');
		snarfbytes(d);
		switch (d) {
		case 1:
			d = mem.b;
			break;
		case 2:
			d = mem.w;
			break;
		case 4:
			d = mem.l;
			break;
		}
		if (r == 0xF) {	/* PC offset addressing */
			d += dot + dotoff;
			psymoff("%R", (addr_t)d, SP_DATA, maxoff, "");
		} else
			adbprintf("%V(%s)", d, regname[r]);
		var[argno] = d;
	}
	if (ins == CASEL) {
		register addr_t adjdot;

		if (inkdot(dotoff) & 01)	/* align */
			dotoff++;
		adjdot = inkdot(dotoff);
		for (argno = 0; argno <= var[2]; ++argno) {
			adbprintf("\n    %R:  ", argno + var[1]);
			snarfbytes(2);
			psymoff("%R", adjdot + mem.w, SP_DATA, maxoff, "");
		}
	}
	dotinc = dotoff;
}