|
|
1.1 root 1: /*
2: * @(#)kdb_opset.c 7.4 (Berkeley) 5/1/89
3: */
4:
5: #include "../kdb/defs.h"
6:
7: #include "frame.h"
8:
9: ADDR kdbcallpc;
10: ADDR kdblastframe;
11:
12: /*
13: * Instruction printing.
14: */
15: REGLIST kdbreglist [] = {
16: "p1lr", &kdbpcb.pcb_p1lr, "p1br", (int *)&kdbpcb.pcb_p1br,
17: "p0lr", &kdbpcb.pcb_p0lr, "p0br", (int *)&kdbpcb.pcb_p0br,
18: "ksp", &kdbpcb.pcb_ksp, "esp", &kdbpcb.pcb_esp,
19: "ssp", &kdbpcb.pcb_ssp, "psl", &kdbpcb.pcb_psl,
20: "pc", &kdbpcb.pcb_pc, "usp", &kdbpcb.pcb_usp,
21: "fp", &kdbpcb.pcb_fp, "ap", &kdbpcb.pcb_ap,
22: "r11", &kdbpcb.pcb_r11, "r10", &kdbpcb.pcb_r10,
23: "r9", &kdbpcb.pcb_r9, "r8", &kdbpcb.pcb_r8,
24: "r7", &kdbpcb.pcb_r7, "r6", &kdbpcb.pcb_r6,
25: "r5", &kdbpcb.pcb_r5, "r4", &kdbpcb.pcb_r4,
26: "r3", &kdbpcb.pcb_r3, "r2", &kdbpcb.pcb_r2,
27: "r1", &kdbpcb.pcb_r1, "r0", &kdbpcb.pcb_r0,
28: 0
29: };
30:
31: /*
32: * Argument data types
33: *
34: * If you change these definitions, you must also change the tables
35: * in assizetab.c
36: */
37: #define TYPB 000 /* byte integer */
38: #define TYPW 001 /* word integer */
39: #define TYPL 002 /* long integer */
40: #define TYPQ 003 /* quad integer */
41: #define TYPO 004 /* octa integer */
42: #define TYPF 005 /* F float */
43: #define TYPD 006 /* D float */
44: #define TYPG 007 /* G float */
45: #define TYPH 010 /* H float */
46: #define TYPUNPACKED 011 /* when unpacked into mantissa & exponent */
47: #define TYPNONE 012 /* when nothing */
48: #define TYPLG 4 /* number of bits the above take up */
49:
50: #define TYPMASK ((1<<TYPLG)-1) /* the mask (assumes 2's comp arith) */
51: /*
52: * Constructors and extractors for argument access kinds and types
53: */
54: #define A_CONS(access, type) ((access) | (type))
55: #define A_ACCEXT(consed) ((consed) & (TYPMASK << TYPLG))
56: #define A_TYPEXT(consed) ((consed) & TYPMASK)
57:
58: /*
59: * Argument access types used to test validity of operands to operators
60: */
61: #define ACCR (1<<TYPLG) /* read */
62: #define ACCW (2<<TYPLG) /* write */
63: #define ACCB (4<<TYPLG) /* branch displacement */
64: #define ACCA (8<<TYPLG) /* address only */
65: #define ACCV (8<<TYPLG) /* address only */
66: #define ACCM (ACCR | ACCW) /* modify */
67: #define ACCI (ACCB | ACCR) /* XFC code */
68:
69: #define ACCESSMASK (ACCA | ACCR | ACCW | ACCB) /* the mask */
70:
71: /*
72: * Construction of TYPX and ACCX, to make the instrs table
73: * easy to use and read.
74: */
75: /*
76: * For real memory address
77: */
78: #define A_AB A_CONS(ACCA, TYPB)
79: #define A_AW A_CONS(ACCA, TYPW)
80: #define A_AL A_CONS(ACCA, TYPL)
81: #define A_AQ A_CONS(ACCA, TYPQ)
82: #define A_AO A_CONS(ACCA, TYPO)
83: #define A_AF A_CONS(ACCA, TYPF)
84: #define A_AD A_CONS(ACCA, TYPD)
85: #define A_AG A_CONS(ACCA, TYPG)
86: #define A_AH A_CONS(ACCA, TYPH)
87: /*
88: * For real memory addresses, or register addresses [sic]
89: *
90: * CHEAT! we just call these read access, since
91: * registers are allowed. All field instruction, except insv,
92: * are are read access fields.
93: */
94: #define A_VB A_CONS(ACCR, TYPB)
95: #define A_VW A_CONS(ACCR, TYPW)
96: #define A_VL A_CONS(ACCR, TYPL)
97: #define A_VQ A_CONS(ACCR, TYPQ)
98: #define A_VO A_CONS(ACCR, TYPO)
99: #define A_VF A_CONS(ACCR, TYPF)
100: #define A_VD A_CONS(ACCR, TYPD)
101: #define A_VG A_CONS(ACCR, TYPG)
102: #define A_VH A_CONS(ACCR, TYPH)
103: /*
104: * For branch displacement
105: */
106: #define A_BB A_CONS(ACCB, TYPB)
107: #define A_BW A_CONS(ACCB, TYPW)
108: /*
109: * For modification
110: */
111: #define A_MB A_CONS(ACCM, TYPB)
112: #define A_MW A_CONS(ACCM, TYPW)
113: #define A_ML A_CONS(ACCM, TYPL)
114: #define A_MF A_CONS(ACCM, TYPF)
115: #define A_MD A_CONS(ACCM, TYPD)
116: #define A_MG A_CONS(ACCM, TYPG)
117: #define A_MH A_CONS(ACCM, TYPH)
118: /*
119: * For reading
120: */
121: #define A_RB A_CONS(ACCR, TYPB)
122: #define A_RW A_CONS(ACCR, TYPW)
123: #define A_RL A_CONS(ACCR, TYPL)
124: #define A_RQ A_CONS(ACCR, TYPQ)
125: #define A_RO A_CONS(ACCR, TYPO)
126: #define A_RF A_CONS(ACCR, TYPF)
127: #define A_RD A_CONS(ACCR, TYPD)
128: #define A_RG A_CONS(ACCR, TYPG)
129: #define A_RH A_CONS(ACCR, TYPH)
130: /*
131: * For writing
132: */
133: #define A_WB A_CONS(ACCW, TYPB)
134: #define A_WW A_CONS(ACCW, TYPW)
135: #define A_WL A_CONS(ACCW, TYPL)
136: #define A_WQ A_CONS(ACCW, TYPQ)
137: #define A_WO A_CONS(ACCW, TYPO)
138: #define A_WF A_CONS(ACCW, TYPF)
139: #define A_WD A_CONS(ACCW, TYPD)
140: #define A_WG A_CONS(ACCW, TYPG)
141: #define A_WH A_CONS(ACCW, TYPH)
142:
143: struct insttab {
144: char *iname;
145: u_char eopcode;
146: u_char popcode;
147: char nargs;
148: u_char argtype[6];
149: };
150:
151: #define OP(name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6) \
152: {name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6}
153: /*
154: * Definitions for the escape bytes
155: */
156: #define CORE 0
157: #define NEW 1
158: #define ESCD 0xfd
159: #define ESCF 0xff
160: #define mapescbyte(b) ((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0)
161:
162: static struct insttab insttab[] = {
163: #include "../vax/kdb_instrs"
164: 0};
165:
166: /*
167: * Convert TYP[BWLQOFDGH] into {1 if relocation not OK}
168: */
169: int ty_NORELOC[] = {
170: 0, /* TYPB */
171: 0, /* TYPW */
172: 0, /* TYPL */
173: 1, /* TYPQ */
174: 1, /* TYPO */
175: 1, /* TYPF */
176: 1, /* TYPD */
177: 1, /* TYPG */
178: 1, /* TYPH */
179: 1 /* TYPNONE */
180: };
181:
182: /*
183: * Convert TYP[BWLQOFDGH] into {1 ... 16}
184: */
185: int ty_nbyte[] = {
186: 1, /* TYPB */
187: 2, /* TYPW */
188: 4, /* TYPL */
189: 8, /* TYPQ */
190: 16, /* TYPO */
191: 4, /* TYPF */
192: 8, /* TYPD */
193: 8, /* TYPG */
194: 16, /* TYPH */
195: 0 /* TYPNONE */
196: };
197:
198: static char *regname[] = {
199: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
200: "r8", "r9", "r10","r11","ap", "fp", "sp", "pc"
201: };
202: static char *fltimm[] = {
203: "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875", "0.9375",
204: "1.0", "1.125", "1.25", "1.375", "1.5", "1.625", "1.75", "1.875",
205: "2.0", "2.25", "2.5", "2.75", "3.0", "3.25", "3.5", "3.75",
206: "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5",
207: "8.0", "9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0",
208: "16.0", "18.0", "20.0", "22.0", "24.0", "26.0", "28.0", "30.0",
209: "32.0", "36.0", "40.0", "44.0", "48.0", "52.0", "56.0", "60.0",
210: "64.0", "72.0", "80.0", "88.0", "96.0", "104.0", "112.0", "120.0"
211: };
212:
213: static int type, space, incp;
214: static long insoutvar[36];
215: /*
216: * Definitions for registers and for operand classes
217: */
218: static char *insregname(); /* how to print a register */
219:
220: #define R_PC 0xF
221:
222: #define OC_IMM0 0x0
223: #define OC_IMM1 0x1
224: #define OC_IMM2 0x2
225: #define OC_IMM3 0x3
226: #define OC_INDEX 0x4
227: #define OC_REG 0x5
228: #define OC_DREG 0x6
229: #define OC_ADREG 0x7
230: #define OC_AIREG 0x8
231: #define OC_DAIREG 0x9
232:
233: #define OC_BDISP 0xA
234: #define OC_DBDISP 0xB
235: #define OC_WDISP 0xC
236: #define OC_DWDISP 0xD
237: #define OC_LDISP 0xE
238: #define OC_DLDISP 0xF
239:
240: #define OC_SHIFT 4
241: #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
242: #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF)
243: #define OC_REGEXT(x) ((x) & 0xF)
244:
245: /*
246: * Definitions for large numbers
247: */
248: #include "asnumber.h"
249: typedef struct as_number *numberp;
250: static numberp snarf();
251: static numberp snarfreloc();
252: /*
253: * Definitions for special instructions
254: */
255: #define CASEB 0x8F
256: #define CASEW 0xAF
257: #define CASEL 0xCF
258:
259: /* two level 1-based index by opcode into insttab */
260: static short ioptab[3][256];
261:
262: kdbsetup()
263: {
264: register struct insttab *p;
265: int mapchar;
266:
267: for(p = insttab; p->iname; p++){
268: mapchar = mapescbyte(p->eopcode);
269: if (ioptab[mapchar][p->popcode])
270: continue;
271: ioptab[mapchar][p->popcode] = (p - insttab) + 1;
272: }
273: }
274:
275: static u_char snarfuchar();
276: /*
277: * Global variables for communicating with the minions and printins
278: */
279: static int idsp;
280: static short argno; /* which argument one is working on */
281: static char insoutfmt[2]; /* how to format the relocated symbols */
282:
283: static savevar(val)
284: long val;
285: {
286: kdbvar[argno] = val;
287: insoutvar[argno] = val;
288: }
289:
290: /* ARGSUSED */
291: kdbprintins(Idsp, ins)
292: u_char ins;
293: int Idsp;
294: {
295: u_char mode; /* mode */
296: u_char ins2;
297: char *indexreg; /* print of which register indexes */
298: char *indexed; /* we indexed */
299: char *operandout();
300: register u_char *ap;
301: register struct insttab *ip;
302: u_char optype;
303: int mapchar;
304:
305: idsp = Idsp;
306: type = DSYM;
307: space = idsp;
308: insoutfmt[0] = 0;
309:
310: incp = 1;
311: if ((mapchar = mapescbyte(ins)) != 0){
312: ins2 = snarfuchar();
313: if (ioptab[mapchar][ins2] == 0){
314: /*
315: * Oops; not a defined instruction;
316: * back over this escape byte.
317: */
318: incp -= 1;
319: mapchar = 0;
320: } else {
321: ins = ins2;
322: }
323: }
324: if (ioptab[mapchar][ins] == 0){
325: kdbprintf("<undefined operator byte>: %x", ins);
326: goto ret;
327: }
328: ip = &insttab[ioptab[mapchar][ins] - 1];
329: kdbprintf("%s\t", ip->iname);
330:
331: for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
332: savevar(0x80000000); /* an illegal symbol */
333: optype = *ap;
334: if (argno != 0)
335: kdbprintc(',');
336: indexreg = 0;
337: indexed = 0;
338: do{
339: if (A_ACCEXT(optype) & ACCB){
340: switch(A_TYPEXT(optype)){
341: case TYPB:
342: mode = OC_CONS(OC_BDISP, R_PC);
343: break;
344: case TYPW:
345: mode = OC_CONS(OC_WDISP, R_PC);
346: break;
347: }
348: } else {
349: mode = snarfuchar();
350: }
351: indexreg = operandout(mode, optype);
352: if (indexed)
353: kdbprintf("[%s]", indexed);
354: indexed = indexreg;
355: } while(indexed);
356: }
357: if (mapchar == 0){
358: switch(ins){
359: case CASEB:
360: case CASEW:
361: case CASEL:
362: casebody(insoutvar[1], insoutvar[2]);
363: break;
364: default:
365: break;
366: }
367: }
368: ret: ;
369:
370: kdbdotinc = incp;
371: }
372:
373: casebody(base, limit)
374: long base;
375: long limit;
376: {
377: int i;
378: u_int baseincp;
379: u_int advincp;
380: struct as_number *valuep;
381: #define OSIZE (sizeof(short))
382: argno = 0;
383: baseincp = incp;
384: for (i = 0; i <= limit; i++) {
385: kdbprintc(EOR);
386: kdbprintf(" %R: ", i + base);
387: valuep = snarfreloc(OSIZE, 0);
388: advincp = incp;
389: incp = baseincp;
390: dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
391: incp = advincp;
392: }
393: }
394:
395: /*
396: * magic values to mung an offset to a register into
397: * something that psymoff can understand.. all magic
398: */
399: /* 0 1 2 3 4 */
400: static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0};
401: static long magic_compl[5] = {0, 0x100, 0x10000,0, 0};
402: /*
403: * Snarf up some bytes, and put in the magic relocation flags
404: */
405: static numberp snarfreloc(nbytes)
406: int nbytes;
407: {
408: numberp back;
409: back = snarf(nbytes);
410: if (back->num_ulong[0] & magic_masks[nbytes])
411: back->num_ulong[0] -= magic_compl[nbytes];
412: return(back);
413: }
414: /*
415: * The following code is NOT portable from the PDP 11 to the VAX
416: * because of the byte ordering problem.
417: */
418: static numberp snarf(nbytes)
419: int nbytes;
420: {
421: register int i;
422:
423: static struct as_number backnumber;
424: static struct as_number znumber; /* init'ed to 0 */
425:
426: backnumber = znumber;
427: for (i = 0; i < nbytes; i++)
428: backnumber.num_uchar[i] = snarfuchar();
429: return(&backnumber);
430: }
431:
432: /*
433: * Read one single character, and advance the dot
434: */
435: static u_char
436: snarfuchar()
437: {
438: u_char back;
439: /*
440: * assert: bchkget and inkdot don't have side effects
441: */
442: back = (u_char)kdbbchkget(kdbinkdot(incp), idsp);
443: incp += 1;
444: return(back);
445: }
446:
447: /*
448: * normal operand; return non zero pointer to register
449: * name if this is an index instruction.
450: */
451: char *operandout(mode, optype)
452: u_char mode;
453: u_char optype;
454: {
455: char *r;
456: int regnumber;
457: int nbytes;
458:
459: regnumber = OC_REGEXT(mode);
460: r = insregname(regnumber);
461: switch (OC_AMEXT(mode)){
462: case OC_IMM0:
463: case OC_IMM1:
464: case OC_IMM2:
465: case OC_IMM3:
466: shortliteral(mode, optype);
467: return(0);
468: case OC_INDEX:
469: return(r); /* will be printed later */
470: case OC_REG:
471: kdbprintf("%s", r);
472: return(0);
473: case OC_DREG:
474: kdbprintf("(%s)", r);
475: return(0);
476: case OC_ADREG:
477: kdbprintf("-(%s)", r);
478: return(0);
479: case OC_DAIREG:
480: kdbprintc('*');
481: case OC_AIREG:
482: if (regnumber == R_PC){
483: pcimmediate(mode, optype);
484: } else {
485: kdbprintf("(%s)+", r);
486: }
487: return(0);
488: case OC_DBDISP:
489: kdbprintc('*');
490: case OC_BDISP:
491: nbytes = 1;
492: break;
493: case OC_DWDISP:
494: kdbprintc('*');
495: case OC_WDISP:
496: nbytes = 2;
497: break;
498: case OC_DLDISP:
499: kdbprintc('*');
500: case OC_LDISP:
501: nbytes = 4;
502: break;
503: }
504: dispaddress(snarfreloc(nbytes), mode);
505: return(0);
506: }
507:
508: dispaddress(valuep, mode)
509: numberp valuep;
510: u_char mode;
511: {
512: int regnumber = OC_REGEXT(mode);
513:
514: switch(OC_AMEXT(mode)){
515: case OC_BDISP:
516: case OC_DBDISP:
517: case OC_WDISP:
518: case OC_DWDISP:
519: case OC_LDISP:
520: case OC_DLDISP:
521: if (regnumber == R_PC){
522: /* PC offset addressing */
523: valuep->num_ulong[0] += kdbinkdot(incp);
524: }
525: }
526: if (regnumber == R_PC)
527: kdbpsymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
528: else { /* } */
529: kdbprintf(LPRMODE, valuep->num_ulong[0]);
530: kdbprintf(insoutfmt);
531: kdbprintf("(%s)", insregname(regnumber));
532: }
533: savevar((long)valuep->num_ulong[0]);
534: }
535:
536: /*
537: * get a register name
538: */
539: static char *
540: insregname(regnumber)
541: int regnumber;
542: {
543: char *r;
544: r = regname[regnumber];
545: return(r);
546: }
547:
548: /*
549: * print out a short literal
550: */
551: shortliteral(mode, optype)
552: u_char mode;
553: u_char optype;
554: {
555: savevar((long)mode);
556: switch(A_TYPEXT(optype)){
557: case TYPF:
558: case TYPD:
559: case TYPG:
560: case TYPH:
561: kdbprintf("$%s", fltimm[mode]);
562: break;
563: default:
564: kdbprintf("$%r", mode);
565: break;
566: }
567: }
568:
569: pcimmediate(mode, optype)
570: u_char mode;
571: u_char optype;
572: {
573: int nbytes;
574:
575: kdbprintc('$');
576: if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/
577: dispaddress(snarfreloc(4), mode);
578: return;
579: }
580: nbytes = ty_nbyte[A_TYPEXT(optype)];
581: if (! ty_NORELOC[A_TYPEXT(optype)]){
582: dispaddress(snarfreloc(nbytes), mode);
583: return;
584: }
585: bignumprint(nbytes, optype);
586: }
587:
588: bignumprint(nbytes, optype)
589: int nbytes;
590: u_char optype;
591: {
592: numberp valuep;
593: int leading_zero = 1;
594: register int bindex;
595: register int nindex;
596: register int ch;
597:
598: valuep = snarf(nbytes);
599: switch(A_TYPEXT(optype)){
600: case TYPF:
601: kdbprintf("0f%f", valuep->num_num.numFf_float.Ff_value);
602: break;
603: case TYPD:
604: kdbprintf("0d%f", valuep->num_num.numFd_float.Fd_value);
605: break;
606: case TYPG:
607: kdbprintf("0g::"); goto qprint;
608: case TYPH:
609: kdbprintf("0h::"); goto qprint;
610: case TYPQ:
611: case TYPO:
612: qprint:
613: for (bindex = nbytes - 1; bindex >= 0; --bindex){
614: for (nindex = 4; nindex >= 0; nindex -= 4){
615: ch = (valuep->num_uchar[bindex] >> nindex);
616: ch &= 0x0F;
617: if ( ! (leading_zero &= (ch == 0) ) ){
618: if (ch <= 0x09)
619: kdbprintc(ch + '0');
620: else
621: kdbprintc(ch - 0x0A + 'a');
622: }
623: }
624: }
625: break;
626: }
627: }
628:
629: kdbstacktrace(dolocals)
630: int dolocals;
631: {
632: register ADDR ap, fp;
633: register int i, narg, tramp;
634: struct frame fr;
635:
636: if (kdbadrflg) {
637: /*
638: * Can only find args if called via `calls' (not callg).
639: * The horrible expression below reads the second
640: * longword of the given frame address; this contains
641: * fr_s and fr_spa, plus the register save mask. The
642: * memory layout is
643: * fp+0x00: call frame structure
644: * fp+0x14: saved registers
645: * fp+0xMM: stack alignment bytes
646: * fp+0xNN: arguments
647: */
648: fp = kdbadrval;
649: ((int *)&fr)[1] = kdbget((off_t)fp + 4, DSP);
650: if (fr.fr_s) {
651: ap = fp + sizeof(fr) + fr.fr_spa;
652: for (i = fr.fr_mask; i != 0; i >>= 1)
653: if (i & 1)
654: ap += 4;
655: } else
656: ap = 0;
657: kdbcallpc = getprevpc(fp);
658: } else {
659: fp = kdbpcb.pcb_fp;
660: ap = kdbpcb.pcb_ap;
661: kdbcallpc = kdbpcb.pcb_pc;
662: }
663:
664: kdblastframe = NOFRAME;
665: while (kdbcntval-- && fp != NOFRAME) {
666: char *name;
667:
668: kdbchkerr();
669: /* check for pc in pcb (signal trampoline code) */
670: if (issignalpc(kdbcallpc)) {
671: tramp = 1;
672: name = "sigtramp";
673: } else {
674: tramp = 0;
675: (void) kdbfindsym((long)kdbcallpc, ISYM);
676: if (kdbcursym)
677: name = kdbcursym->n_un.n_name;
678: else
679: name = "?";
680: }
681: kdbprintf("%s(", name);
682: if (ap) {
683: /* byte at ap tells how many arguments */
684: narg = kdbget((off_t)ap, DSP) & 0xff;
685: for (i = narg > 10 ? 10 : narg; i;) {
686: ap += 4;
687: kdbprintf("%R", kdbget((off_t)ap, DSP));
688: if (--i != 0)
689: kdbprintc(',');
690: }
691: } else
692: kdbprintc('?');
693: kdbprintf(") at ");
694: kdbpsymoff((long)kdbcallpc, ISYM, "\n");
695:
696: if (dolocals) {
697: register ADDR word;
698:
699: while (kdblocalsym((long)fp)) {
700: word = kdbget((off_t)kdblocalval, DSP);
701: kdbprintf("%8t%s:%10t",
702: kdbcursym->n_un.n_name);
703: if (kdberrflg) {
704: kdbprintf("?\n");
705: kdberrflg = 0;
706: } else
707: kdbprintf("%R\n", word);
708: }
709: }
710: if (!tramp) {
711: kdbcallpc = getprevpc(fp);
712: kdblastframe = fp;
713: /* 8 below == offsetof(struct frame, fr_savap) */
714: ap = kdbget((off_t)fp + 8, DSP);
715: fp = getprevframe(fp);
716: } else {
717: kdbcallpc = getsignalpc(kdblastframe);
718: /* ??? WHAT ABOUT ap AND fp ??? */
719: }
720: if (!kdbadrflg && !INSTACK(fp))
721: break;
722: }
723: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.