xref: /original-bsd/old/adb/adb.vax/opset.c (revision a9c19d04)
1 #ifndef lint
2 static	char sccsid[] = "@(#)opset.c 4.5 05/27/85";
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 	if (regnumber == R_PC)
389 		psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
390 	else {				/* } */
391 		printf(LPRMODE, valuep->num_ulong[0]);
392 		printf(insoutfmt);
393 #endif ADB
394 #ifdef SDB
395 	if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0])
396 	   && (regnumber != R_PC)){
397 #endif SDB
398 		printf("(%s)", insregname(regnumber));
399 	}
400 	savevar((long)valuep->num_ulong[0]);
401 }
402 /*
403  *	get a register name
404  */
405 char *insregname(regnumber)
406 	int	regnumber;
407 {
408 	char	*r;
409 	r = regname[regnumber];
410 #ifdef SDB
411 	if (   (insoutfmt[0] == 'i')
412 	    && (regnumber >= 6)
413 	    && (regnumber <= 11)
414 	    && (adrtoregvar(regnumber, procp) != -1)) {
415 		r = sl_name;
416 	}
417 #endif SDB
418 	return(r);
419 }
420 /*
421  *	print out a short literal
422  */
423 shortliteral(mode, optype)
424 	u_char	mode;
425 	u_char	optype;
426 {
427 	savevar((long)mode);
428 	switch(A_TYPEXT(optype)){
429 	case TYPF:
430 	case TYPD:
431 	case TYPG:
432 	case TYPH:
433 		printf("$%s", fltimm[mode]);
434 		break;
435 	default:
436 #ifdef ADB
437 		printf("$%r", mode);
438 #endif ADB
439 #ifdef SDB
440 		printf("$%d", mode);
441 #endif SDB
442 		break;
443 	}
444 }
445 
446 pcimmediate(mode, optype)
447 	u_char	mode;
448 	u_char	optype;
449 {
450 	int	nbytes;
451 
452 	printc('$');
453 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
454 		dispaddress(snarfreloc(4), mode);
455 		return;
456 	}
457 	nbytes = ty_nbyte[A_TYPEXT(optype)];
458 	if (! ty_NORELOC[A_TYPEXT(optype)]){
459 		dispaddress(snarfreloc(nbytes), mode);
460 		return;
461 	}
462 	bignumprint(nbytes, optype);
463 }
464 
465 bignumprint(nbytes, optype)
466 	int	nbytes;
467 	u_char	optype;
468 {
469 	numberp	valuep;
470 	int	leading_zero = 1;
471 	REG	int	bindex;
472 	REG	int	nindex;
473 	REG	int	ch;
474 
475 	valuep = snarf(nbytes);
476 	switch(A_TYPEXT(optype)){
477 	case TYPF:
478 		printf("0f%f", valuep->num_num.numFf_float.Ff_value);
479 		break;
480 	case TYPD:
481 		printf("0d%f", valuep->num_num.numFd_float.Fd_value);
482 		break;
483 	case TYPG:
484 		printf("0g::"); goto qprint;
485 	case TYPH:
486 		printf("0h::"); goto qprint;
487 	case TYPQ:
488 	case TYPO:
489 	qprint:
490 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
491 			for (nindex = 4; nindex >= 0; nindex -= 4){
492 				ch = (valuep->num_uchar[bindex] >> nindex);
493 				ch &= 0x0F;
494 				if ( ! (leading_zero &= (ch == 0) ) ){
495 					if (ch <= 0x09)
496 						printc(ch + '0');
497 					else
498 						printc(ch - 0x0A + 'a');
499 				}
500 			}
501 		}
502 		break;
503 	}
504 }
505 #ifdef SDB
506 
507 L_INT inkdot(incr)
508 	int	incr;
509 {
510 	L_INT		newdot;
511 
512 	newdot = dot + incr;
513 	return(newdot);
514 }
515 
516 printc(c)
517 	char c;
518 {
519 	printf("%c", c);
520 }
521 
522 psymoff(v, regnumber, fmt)
523 	L_INT	v;
524 	char	*fmt;
525 {
526 	struct	proct	*procp;
527 	REG	int diff;
528 	if (fmt[0] == 'i') {
529 		switch(regnumber){
530 		case 12:	/* parameter */
531 			if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot)))
532 					!= -1) {
533 				printf("%s", sl_name);
534 				prdiff(diff);
535 				return(0);
536 			}
537 			break;
538 		case 13:	/* local */
539 			if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot))
540 					) != -1) {
541 				printf("%s", sl_name);
542 				prdiff(diff);
543 				return(0);
544 			}
545 			break;
546 		default:
547 			break;
548 		}
549 		if (v < firstdata) {
550 			if ((procp = adrtoprocp((ADDR) v)) != badproc) {
551 				prlnoff(procp, v);
552 				return(0);
553 			}
554 		} else {
555 			if ((diff = adrtoext((ADDR) v)) != -1) {
556 				printf("%s", sl_name);
557 				prdiff(diff);
558 				return(0);
559 			}
560 		}
561 	}
562 	prhex(v);
563 	return(1);
564 }
565 
566 prdiff(diff)
567 {
568 	if (diff) {
569 		printf("+");
570 		prhex(diff);
571 	}
572 }
573 
574 #endif SDB
575