xref: /original-bsd/old/adb/adb.vax/opset.c (revision 3708840b)
1 #ifndef lint
2 static	char sccsid[] = "@(#)opset.c 4.4 05/12/83";
3 #endif lint
4 /*
5  *	UNIX debugger
6  *	Instruction printing routines.
7  *	MACHINE DEPENDENT
8  */
9 
10 #ifdef ADB
11 #include "defs.h"
12 #endif ADB
13 #ifdef SDB
14 #include "head.h"
15 #endif SDB
16 
17 L_INT		dot;
18 INT		dotinc;
19 L_INT		insoutvar[36];
20 #ifdef ADB
21 L_INT		var[36];
22 #endif ADB
23 
24 #undef	INSTTAB
25 #include "instrs.h"
26 
27 STRING	regname[];
28 STRING	fltimm[];
29 POS	type, space, incp;
30 /*
31  *	Definitions for registers and for operand classes
32  */
33 char	*insregname();	/* how to print a register */
34 
35 #define	R_PC		0xF
36 
37 #define	OC_IMM0		0x0
38 #define	OC_IMM1		0x1
39 #define	OC_IMM2		0x2
40 #define	OC_IMM3		0x3
41 #define	OC_INDEX	0x4
42 #define	OC_REG		0x5
43 #define	OC_DREG		0x6
44 #define	OC_ADREG	0x7
45 #define	OC_AIREG	0x8
46 #define	OC_DAIREG	0x9
47 
48 #define	OC_BDISP	0xA
49 #define	OC_DBDISP	0xB
50 #define	OC_WDISP	0xC
51 #define	OC_DWDISP	0xD
52 #define	OC_LDISP	0xE
53 #define	OC_DLDISP	0xF
54 
55 #define	OC_SHIFT	4
56 #define	OC_CONS(oc,reg)	(((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
57 #define	OC_AMEXT(x)	(((x) >> OC_SHIFT) & 0xF)
58 #define	OC_REGEXT(x)	((x) & 0xF)
59 
60 /*
61  *	Definitions for large numbers
62  */
63 #include "asnumber.h"
64 typedef	struct	as_number	*numberp;
65 numberp snarf();
66 numberp snarfreloc();
67 /*
68  *	Definitions for special instructions
69  */
70 #define	CASEB	0x8F
71 #define	CASEW	0xAF
72 #define	CASEL	0xCF
73 /*
74  *	Definitions for converting TYP's into numbers, booleans, etc.
75  *	These are shared with the assembler.
76  */
77 extern	int	ty_NORELOC[];
78 extern	int	ty_float[];
79 extern	int	ty_nbyte[];
80 extern	int	ty_nlg[];
81 extern	char	*ty_string[];
82 
83 short ioptab[3][256];	/* two level 1-based index by opcode into insttab */
84 
85 int mapescbyte(byte)
86 	u_char	byte;
87 {
88 	switch(byte){
89 	default:	return(0);
90 	case ESCD:	return(1);
91 	case ESCF:	return(2);
92 	}
93 }
94 
95 mkioptab()
96 {
97 	REG	struct insttab *p;
98 		int	mapchar;
99 
100 	for(p = insttab; p->iname; p++){
101 		mapchar = mapescbyte(p->eopcode);
102 		if (ioptab[mapchar][p->popcode])
103 			continue;
104 		ioptab[mapchar][p->popcode] = (p - insttab) + 1;
105 	}
106 }
107 
108 u_char snarfuchar();
109 /*
110  *	Global variables for communicating with the minions and printins
111  */
112 static	int	idsp;
113 static	short	argno;		/* which argument one is working on */
114 static	char	insoutfmt[2];	/* how to format the relocated symbols */
115 #ifdef SDB
116 static	struct	proct	*procp;
117 #endif SDB
118 
119 static savevar(val)
120 	long	val;
121 {
122 	var[argno] = val;
123 	insoutvar[argno] = val;
124 }
125 
126 printins(fmt, Idsp, ins)
127 	char	fmt;
128 #ifndef vax
129 	u_char	ins;
130 #else
131 	u_char	ins;
132 #endif
133 	int	Idsp;
134 {
135 		u_char	mode;		/* mode */
136 		u_char	ins2;
137 		char	*indexreg;	/* print of which register indexes */
138 		char	*indexed;	/* we indexed */
139 		char	*operandout();
140 	REG	u_char 	*ap;
141 	REG	struct insttab *ip;
142 		u_char	optype;
143 		int	mapchar;
144 
145 	idsp = Idsp;
146 	type = DSYM;
147 	space = idsp;
148 #ifdef SDB
149 	procp = adrtoprocp(dot);
150 	if (procp->paddr == dot){
151 		printf("0x%04.4x", ins);
152 		incp = 2;
153 		goto ret;
154 	}
155 #endif SDB
156 
157 #ifdef ADB
158 	insoutfmt[0] = 0;
159 #endif ADB
160 #ifdef SDB
161 	insoutfmt[0] = fmt;
162 #endif SDB
163 
164 	incp = 1;
165 	if ((mapchar = mapescbyte(ins)) != 0){
166 		ins2 = snarfuchar();
167 		if (ioptab[mapchar][ins2] == 0){
168 			/*
169 			 *	Oops; not a defined instruction;
170 			 *	back over this escape byte.
171 			 */
172 			incp -= 1;
173 			mapchar = 0;
174 		} else {
175 			ins = ins2;
176 		}
177 	}
178 	if (ioptab[mapchar][ins] == 0){
179 		printf("<undefined operator byte>: %x", ins);
180 		goto ret;
181 	}
182 	ip = &insttab[ioptab[mapchar][ins] - 1];
183 	printf("%s\t", ip->iname);
184 
185 	for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
186 		savevar(0x80000000);	/* an illegal symbol */
187 		optype = *ap;
188 		if (argno != 0)
189 			printc(',');
190 		indexreg = 0;
191 		indexed = 0;
192 		do{
193 			if (A_ACCEXT(optype) & ACCB){
194 				switch(A_TYPEXT(optype)){
195 				case TYPB:
196 					mode = OC_CONS(OC_BDISP, R_PC);
197 					break;
198 				case TYPW:
199 					mode = OC_CONS(OC_WDISP, R_PC);
200 					break;
201 				}
202 			} else {
203 				mode = snarfuchar();
204 			}
205 			indexreg = operandout(mode, optype);
206 			if (indexed)
207 				printf("[%s]", indexed);
208 			indexed = indexreg;
209 		} while(indexed);
210 	}
211 	if (mapchar == 0){
212 		switch(ins){
213 		case CASEB:
214 		case CASEW:
215 		case CASEL:
216 			casebody(insoutvar[1], insoutvar[2]);
217 			break;
218 		default:
219 			break;
220 		}
221 	}
222    ret: ;
223 
224 #ifdef SDB
225 	oincr = incp;
226 #endif SDB
227 #ifdef ADB
228 	dotinc = incp;
229 #endif ADB
230 }
231 
232 casebody(base, limit)
233 	long	base;
234 	long	limit;
235 {
236 	int	i;
237 	POS	baseincp;
238 	POS	advincp;
239 	struct	as_number	*valuep;
240 #define	OSIZE (sizeof(short))
241 	argno = 0;
242 	baseincp = incp;
243 	for (i = 0; i <= limit; i++) {
244 		printc(EOR);
245 #ifdef SDB
246 		printf("    %d:  ", i + base);
247 #endif SDB
248 #ifdef ADB
249 		printf("    %R:  ", i + base);
250 #endif ADB
251 		valuep = snarfreloc(OSIZE, 0);
252 		advincp = incp;
253 		incp = baseincp;
254 		dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
255 		incp = advincp;
256 	}
257 }
258 
259 /*
260  *	magic values to mung an offset to a register into
261  *	something that psymoff can understand.. all magic
262  */
263 			      /* 0	1	2	3	4 */
264 static long magic_masks[5] =	{0,	0x80,	0x8000,	0,	0};
265 static long magic_compl[5] =	{0,	0x100,	0x10000,0,	0};
266 /*
267  *	Snarf up some bytes, and put in the magic relocation flags
268  */
269 numberp snarfreloc(nbytes)
270 	int	nbytes;
271 {
272 	numberp	back;
273 	back = snarf(nbytes);
274 	if (back->num_ulong[0] & magic_masks[nbytes])
275 		back->num_ulong[0] -= magic_compl[nbytes];
276 	return(back);
277 }
278 /*
279  *	The following code is NOT portable from the PDP 11 to the VAX
280  *	because of the byte ordering problem.
281  */
282 numberp snarf(nbytes)
283 	int	nbytes;
284 {
285 	REG	int	i;
286 
287 	static	struct	as_number	backnumber;
288 	static	struct	as_number	znumber;	/* init'ed to 0 */
289 
290 	backnumber = znumber;
291 	for (i = 0; i < nbytes; i++)
292 		backnumber.num_uchar[i] = snarfuchar();
293 	return(&backnumber);
294 }
295 /*
296  *	Read one single character, and advance the dot
297  */
298 u_char snarfuchar()
299 {
300 	u_char	back;
301 	/*
302 	 *	assert: bchkget and inkdot don't have side effects
303 	 */
304 	back = (u_char)bchkget(inkdot(incp), idsp);
305 	incp += 1;
306 	return(back);
307 }
308 /*
309  *	normal operand; return non zero pointer to register
310  *	name if this is an index instruction.
311  */
312 char *operandout(mode, optype)
313 	u_char	mode;
314 	u_char	optype;
315 {
316 	char	*r;
317 	int	regnumber;
318 	int	nbytes;
319 
320 	regnumber = OC_REGEXT(mode);
321 	r = insregname(regnumber);
322 	switch (OC_AMEXT(mode)){
323 	case OC_IMM0:
324 	case OC_IMM1:
325 	case OC_IMM2:
326 	case OC_IMM3:
327 		shortliteral(mode, optype);
328 		return(0);
329 	case OC_INDEX:
330 		return(r);		/* will be printed later */
331 	case OC_REG:
332 		printf("%s", r);
333 		return(0);
334 	case OC_DREG:
335 		printf("(%s)", r);
336 		return(0);
337 	case OC_ADREG:
338 		printf("-(%s)", r);
339 		return(0);
340 	case OC_DAIREG:
341 		printc('*');
342 	case OC_AIREG:
343 		if (regnumber == R_PC){
344 			pcimmediate(mode, optype);
345 		} else {
346 			printf("(%s)+", r);
347 		}
348 		return(0);
349 	case OC_DBDISP:
350 		printc('*');
351 	case OC_BDISP:
352 		nbytes = 1;
353 		break;
354 	case OC_DWDISP:
355 		printc('*');
356 	case OC_WDISP:
357 		nbytes = 2;
358 		break;
359 	case OC_DLDISP:
360 		printc('*');
361 	case OC_LDISP:
362 		nbytes = 4;
363 		break;
364 	}
365 	dispaddress(snarfreloc(nbytes), mode);
366 	return(0);
367 }
368 
369 dispaddress(valuep, mode)
370 	numberp	valuep;
371 	u_char	mode;
372 {
373 	int	regnumber = OC_REGEXT(mode);
374 
375 	switch(OC_AMEXT(mode)){
376 	case OC_BDISP:
377 	case OC_DBDISP:
378 	case OC_WDISP:
379 	case OC_DWDISP:
380 	case OC_LDISP:
381 	case OC_DLDISP:
382 		if (regnumber == R_PC){
383 			/* PC offset addressing */
384 			valuep->num_ulong[0] += inkdot(incp);
385 		}
386 	}
387 #ifdef ADB
388 	psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
389 	if (regnumber != R_PC){		/* } */
390 #endif ADB
391 #ifdef SDB
392 	if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0])
393 	   && (regnumber != R_PC)){
394 #endif SDB
395 		printf("(%s)", insregname(regnumber));
396 	}
397 	savevar((long)valuep->num_ulong[0]);
398 }
399 /*
400  *	get a register name
401  */
402 char *insregname(regnumber)
403 	int	regnumber;
404 {
405 	char	*r;
406 	r = regname[regnumber];
407 #ifdef SDB
408 	if (   (insoutfmt[0] == 'i')
409 	    && (regnumber >= 6)
410 	    && (regnumber <= 11)
411 	    && (adrtoregvar(regnumber, procp) != -1)) {
412 		r = sl_name;
413 	}
414 #endif SDB
415 	return(r);
416 }
417 /*
418  *	print out a short literal
419  */
420 shortliteral(mode, optype)
421 	u_char	mode;
422 	u_char	optype;
423 {
424 	savevar((long)mode);
425 	switch(A_TYPEXT(optype)){
426 	case TYPF:
427 	case TYPD:
428 	case TYPG:
429 	case TYPH:
430 		printf("$%s", fltimm[mode]);
431 		break;
432 	default:
433 #ifdef ADB
434 		printf("$%r", mode);
435 #endif ADB
436 #ifdef SDB
437 		printf("$%d", mode);
438 #endif SDB
439 		break;
440 	}
441 }
442 
443 pcimmediate(mode, optype)
444 	u_char	mode;
445 	u_char	optype;
446 {
447 	int	nbytes;
448 
449 	printc('$');
450 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
451 		dispaddress(snarfreloc(4), mode);
452 		return;
453 	}
454 	nbytes = ty_nbyte[A_TYPEXT(optype)];
455 	if (! ty_NORELOC[A_TYPEXT(optype)]){
456 		dispaddress(snarfreloc(nbytes), mode);
457 		return;
458 	}
459 	bignumprint(nbytes, optype);
460 }
461 
462 bignumprint(nbytes, optype)
463 	int	nbytes;
464 	u_char	optype;
465 {
466 	numberp	valuep;
467 	int	leading_zero = 1;
468 	REG	int	bindex;
469 	REG	int	nindex;
470 	REG	int	ch;
471 
472 	valuep = snarf(nbytes);
473 	switch(A_TYPEXT(optype)){
474 	case TYPF:
475 		printf("0f%f", valuep->num_num.numFf_float.Ff_value);
476 		break;
477 	case TYPD:
478 		printf("0d%f", valuep->num_num.numFd_float.Fd_value);
479 		break;
480 	case TYPG:
481 		printf("0g::"); goto qprint;
482 	case TYPH:
483 		printf("0h::"); goto qprint;
484 	case TYPQ:
485 	case TYPO:
486 	qprint:
487 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
488 			for (nindex = 4; nindex >= 0; nindex -= 4){
489 				ch = (valuep->num_uchar[bindex] >> nindex);
490 				ch &= 0x0F;
491 				if ( ! (leading_zero &= (ch == 0) ) ){
492 					if (ch <= 0x09)
493 						printc(ch + '0');
494 					else
495 						printc(ch - 0x0A + 'a');
496 				}
497 			}
498 		}
499 		break;
500 	}
501 }
502 #ifdef SDB
503 
504 L_INT inkdot(incr)
505 	int	incr;
506 {
507 	L_INT		newdot;
508 
509 	newdot = dot + incr;
510 	return(newdot);
511 }
512 
513 printc(c)
514 	char c;
515 {
516 	printf("%c", c);
517 }
518 
519 psymoff(v, regnumber, fmt)
520 	L_INT	v;
521 	char	*fmt;
522 {
523 	struct	proct	*procp;
524 	REG	int diff;
525 	if (fmt[0] == 'i') {
526 		switch(regnumber){
527 		case 12:	/* parameter */
528 			if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot)))
529 					!= -1) {
530 				printf("%s", sl_name);
531 				prdiff(diff);
532 				return(0);
533 			}
534 			break;
535 		case 13:	/* local */
536 			if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot))
537 					) != -1) {
538 				printf("%s", sl_name);
539 				prdiff(diff);
540 				return(0);
541 			}
542 			break;
543 		default:
544 			break;
545 		}
546 		if (v < firstdata) {
547 			if ((procp = adrtoprocp((ADDR) v)) != badproc) {
548 				prlnoff(procp, v);
549 				return(0);
550 			}
551 		} else {
552 			if ((diff = adrtoext((ADDR) v)) != -1) {
553 				printf("%s", sl_name);
554 				prdiff(diff);
555 				return(0);
556 			}
557 		}
558 	}
559 	prhex(v);
560 	return(1);
561 }
562 
563 prdiff(diff)
564 {
565 	if (diff) {
566 		printf("+");
567 		prhex(diff);
568 	}
569 }
570 
571 #endif SDB
572