xref: /original-bsd/old/adb/adb.tahoe/opset.c (revision bdc0a208)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)opset.c	5.1 (Berkeley) 04/04/91";
10 #endif /* not lint */
11 
12 /*
13  * adb - instruction decoding
14  */
15 
16 #include "defs.h"
17 #include "optab.h"
18 
19 struct	optab *ioptab[256];	/* index by opcode to optab */
20 
21 /* set up ioptab */
22 mkioptab()
23 {
24 	register struct optab *p;
25 
26 	for (p = optab; p->iname; p++)
27 		ioptab[p->val] = p;
28 }
29 
30 /*
31  * Print one instruction, and leave dotinc set to the number of bytes
32  * it occupied.
33  */
34 printins(space)
35 	int space;
36 {
37 	u_char ins;		/* instruction opcode */
38 	int argno;		/* argument index */
39 	register int mode;	/* mode */
40 	register int r;		/* register name */
41 	register int d;		/* assembled byte, word, long or float */
42 	register int dotoff;	/* offset from dot of current byte */
43 	register u_char *ap;
44 	register struct optab *ip;
45 	union {
46 		u_char	ub;
47 		char	b;
48 		short	w;
49 		int	l;
50 	} mem;
51 	extern char *syscalls[];
52 	extern int nsys;
53 #define	snarfbytes(nbytes) \
54 	(void) adbread(space, inkdot(dotoff), &mem.b, nbytes); \
55 	checkerr(); \
56 	dotoff += (nbytes)
57 
58 	if (space == SP_NONE)
59 		ins = (u_char)dot;
60 	else {
61 		(void) adbread(space, dot, &ins, 1);
62 		checkerr();
63 	}
64 	if ((ip = ioptab[ins]) == NULL) {
65 		adbprintf("?%2x", ins);
66 		dotinc = 1;
67 		return;
68 	}
69 	adbprintf("%s%8t", ip->iname);
70 	dotoff = 1;
71 	ap = ip->argtype;
72 	for (argno = 0; argno < ip->nargs; argno++, ap++) {
73 		var[argno] = 0x80000000;
74 		if (argno != 0)
75 			printc(',');
76 again:
77 		if (*ap & ACCB)		/* branch displacement */
78 			mode = 0xAF + ((*ap & 7) << 5);
79 		else {
80 			snarfbytes(1);
81 			mode = mem.ub;
82 		}
83 		r = mode & 0xF;
84 		mode >>= 4;
85 		switch (mode) {
86 
87 		case 0: case 1: case 2: case 3:
88 			/* short literal */
89 			d = mode << 4 | r;
90 			goto immed;
91 
92 		case 4:	/* [r] */
93 			adbprintf("[%s]", regname[r]);
94 			goto again;
95 
96 		case 5:	/* r */
97 			adbprintf("%s", regname[r]);
98 			continue;
99 
100 		case 6:	/* (r) */
101 			adbprintf("(%s)", regname[r]);
102 			continue;
103 
104 		case 7:	/* -(r) */
105 			adbprintf("-(%s)", regname[r]);
106 			continue;
107 
108 		case 9:	/* *(r)+ */
109 			printc('*');
110 			/* FALLTHROUGH */
111 
112 		case 8:	/* (r)+ */
113 			if (r == 0xf) {
114 				/* PC immediate */
115 				snarfbytes(4);
116 				d = mem.l;
117 			} else if (mode == 8 && (r == 8 || r == 9)) {
118 				/* absolute */
119 				snarfbytes((r & 1) + 1);
120 				d = r == 8 ? mem.b : mem.w;
121 			} else {
122 				adbprintf("(%s)+", regname[r]);
123 				continue;
124 			}
125 	immed:
126 			printc('$');
127 			if (ins == KCALL && (u_int)d < nsys && syscalls[d])
128 				prints(syscalls[d]);
129 			else
130 				adbprintf("%R", d);
131 			var[argno] = d;
132 			continue;
133 
134 		case 0xA:	/* byte displacement */
135 		case 0xB:	/* byte displacement deferred */
136 			d = 1;
137 			break;
138 
139 		case 0xC:	/* word displacement */
140 		case 0xD:	/* word displacement deferred */
141 			d = 2;
142 			break;
143 
144 		case 0xE:	/* long displacement */
145 		case 0xF:	/* long displacement deferred */
146 			d = 4;
147 			break;
148 		}
149 
150 		/* displacement or displacement deferred */
151 		if (mode & 1)
152 			printc('*');
153 		snarfbytes(d);
154 		switch (d) {
155 		case 1:
156 			d = mem.b;
157 			break;
158 		case 2:
159 			d = mem.w;
160 			break;
161 		case 4:
162 			d = mem.l;
163 			break;
164 		}
165 		if (r == 0xF) {	/* PC offset addressing */
166 			d += dot + dotoff;
167 			psymoff("%R", (addr_t)d, SP_DATA, maxoff, "");
168 		} else
169 			adbprintf("%V(%s)", d, regname[r]);
170 		var[argno] = d;
171 	}
172 	if (ins == CASEL) {
173 		register addr_t adjdot;
174 
175 		if (inkdot(dotoff) & 01)	/* align */
176 			dotoff++;
177 		adjdot = inkdot(dotoff);
178 		for (argno = 0; argno <= var[2]; ++argno) {
179 			adbprintf("\n    %R:  ", argno + var[1]);
180 			snarfbytes(2);
181 			psymoff("%R", adjdot + mem.w, SP_DATA, maxoff, "");
182 		}
183 	}
184 	dotinc = dotoff;
185 }
186