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