check in before removing
[unix-history] / usr / src / old / adb / adb.vax / opset.c
CommitLineData
f02effa0 1#ifndef lint
5f2ce988 2static char sccsid[] = "@(#)opset.c 4.7 %G%";
8ae34dba 3#endif /* lint */
7cb4340a 4/*
7cb4340a 5 * UNIX debugger
f02effa0
RH
6 * Instruction printing routines.
7 * MACHINE DEPENDENT
7cb4340a
BJ
8 */
9
f02effa0 10#ifdef ADB
7cb4340a 11#include "defs.h"
8ae34dba 12#endif /* ADB */
f02effa0
RH
13#ifdef SDB
14#include "head.h"
8ae34dba 15#endif /* SDB */
7cb4340a 16
7cb4340a
BJ
17L_INT dot;
18INT dotinc;
f02effa0
RH
19L_INT insoutvar[36];
20#ifdef ADB
21L_INT var[36];
8ae34dba 22#endif /* ADB */
7cb4340a 23
f02effa0
RH
24#undef INSTTAB
25#include "instrs.h"
7cb4340a 26
f02effa0
RH
27STRING regname[];
28STRING fltimm[];
29POS type, space, incp;
7cb4340a 30/*
f02effa0 31 * Definitions for registers and for operand classes
7cb4340a 32 */
f02effa0
RH
33char *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)
7cb4340a
BJ
59
60/*
f02effa0 61 * Definitions for large numbers
7cb4340a 62 */
f02effa0
RH
63#include "asnumber.h"
64typedef struct as_number *numberp;
65numberp snarf();
66numberp 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 */
77extern int ty_NORELOC[];
78extern int ty_float[];
79extern int ty_nbyte[];
80extern int ty_nlg[];
81extern char *ty_string[];
82
e9971154 83short ioptab[3][256]; /* two level 1-based index by opcode into insttab */
f02effa0
RH
84
85int 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}
7cb4340a 94
f02effa0
RH
95mkioptab()
96{
97 REG struct insttab *p;
98 int mapchar;
7cb4340a 99
f02effa0
RH
100 for(p = insttab; p->iname; p++){
101 mapchar = mapescbyte(p->eopcode);
102 if (ioptab[mapchar][p->popcode])
103 continue;
e9971154 104 ioptab[mapchar][p->popcode] = (p - insttab) + 1;
7cb4340a
BJ
105 }
106}
107
f02effa0
RH
108u_char snarfuchar();
109/*
110 * Global variables for communicating with the minions and printins
111 */
112static int idsp;
113static short argno; /* which argument one is working on */
114static char insoutfmt[2]; /* how to format the relocated symbols */
115#ifdef SDB
116static struct proct *procp;
8ae34dba 117#endif /* SDB */
f02effa0
RH
118
119static savevar(val)
120 long val;
121{
122 var[argno] = val;
123 insoutvar[argno] = val;
124}
7cb4340a 125
f02effa0
RH
126printins(fmt, Idsp, ins)
127 char fmt;
7cb4340a 128#ifndef vax
f02effa0 129 u_char ins;
7cb4340a 130#else
f02effa0 131 u_char ins;
7cb4340a 132#endif
f02effa0 133 int Idsp;
7cb4340a 134{
f02effa0
RH
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;
7cb4340a 144
f02effa0 145 idsp = Idsp;
7cb4340a
BJ
146 type = DSYM;
147 space = idsp;
f02effa0
RH
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 }
8ae34dba 155#endif /* SDB */
f02effa0
RH
156
157#ifdef ADB
158 insoutfmt[0] = 0;
8ae34dba 159#endif /* ADB */
f02effa0
RH
160#ifdef SDB
161 insoutfmt[0] = fmt;
8ae34dba 162#endif /* SDB */
f02effa0 163
7cb4340a 164 incp = 1;
f02effa0
RH
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;
7cb4340a 176 }
f02effa0
RH
177 }
178 if (ioptab[mapchar][ins] == 0){
179 printf("<undefined operator byte>: %x", ins);
180 goto ret;
181 }
e9971154 182 ip = &insttab[ioptab[mapchar][ins] - 1];
f02effa0
RH
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);
7cb4340a 197 break;
f02effa0
RH
198 case TYPW:
199 mode = OC_CONS(OC_WDISP, R_PC);
7cb4340a 200 break;
f02effa0
RH
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);
7cb4340a 210 }
f02effa0
RH
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;
7cb4340a 220 }
7cb4340a 221 }
f02effa0
RH
222 ret: ;
223
224#ifdef SDB
225 oincr = incp;
8ae34dba 226#endif /* SDB */
f02effa0
RH
227#ifdef ADB
228 dotinc = incp;
8ae34dba 229#endif /* ADB */
f02effa0
RH
230}
231
232casebody(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);
8ae34dba 247#endif /* SDB */
f02effa0
RH
248#ifdef ADB
249 printf(" %R: ", i + base);
8ae34dba 250#endif /* ADB */
f02effa0
RH
251 valuep = snarfreloc(OSIZE, 0);
252 advincp = incp;
253 incp = baseincp;
254 dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
255 incp = advincp;
256 }
7cb4340a
BJ
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 */
264static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0};
265static long magic_compl[5] = {0, 0x100, 0x10000,0, 0};
f02effa0
RH
266/*
267 * Snarf up some bytes, and put in the magic relocation flags
268 */
269numberp 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 */
282numberp 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 */
7cb4340a 289
f02effa0
RH
290 backnumber = znumber;
291 for (i = 0; i < nbytes; i++)
292 backnumber.num_uchar[i] = snarfuchar();
293 return(&backnumber);
294}
7cb4340a 295/*
f02effa0 296 * Read one single character, and advance the dot
7cb4340a 297 */
f02effa0 298u_char snarfuchar()
7cb4340a 299{
f02effa0
RH
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 */
312char *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;
7cb4340a 364 }
f02effa0
RH
365 dispaddress(snarfreloc(nbytes), mode);
366 return(0);
7cb4340a
BJ
367}
368
f02effa0
RH
369dispaddress(valuep, mode)
370 numberp valuep;
371 u_char mode;
7cb4340a 372{
f02effa0
RH
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
eedf7e79
EW
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);
8ae34dba 393#endif /* ADB */
f02effa0
RH
394#ifdef SDB
395 if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0])
396 && (regnumber != R_PC)){
8ae34dba 397#endif /* SDB */
f02effa0
RH
398 printf("(%s)", insregname(regnumber));
399 }
400 savevar((long)valuep->num_ulong[0]);
401}
402/*
403 * get a register name
404 */
405char *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 }
8ae34dba 417#endif /* SDB */
f02effa0
RH
418 return(r);
419}
420/*
421 * print out a short literal
422 */
423shortliteral(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);
8ae34dba 438#endif /* ADB */
f02effa0
RH
439#ifdef SDB
440 printf("$%d", mode);
8ae34dba 441#endif /* SDB */
f02effa0
RH
442 break;
443 }
7cb4340a
BJ
444}
445
f02effa0
RH
446pcimmediate(mode, optype)
447 u_char mode;
448 u_char optype;
7cb4340a 449{
f02effa0
RH
450 int nbytes;
451
452 printc('$');
7fad38f7 453 if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/
f02effa0
RH
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
465bignumprint(nbytes, optype)
466 int nbytes;
467 u_char optype;
468{
469 numberp valuep;
7cb4340a 470 int leading_zero = 1;
f02effa0
RH
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:
5f2ce988
KB
478 if ((valuep->num_num.numFf_float.Ff_ushort[0] & 0xff80) == 0x8000) {
479 printf("0f::"); goto qprint;
480 }
f02effa0
RH
481 printf("0f%f", valuep->num_num.numFf_float.Ff_value);
482 break;
483 case TYPD:
5f2ce988
KB
484 if ((valuep->num_num.numFd_float.Fd_ushort[0] & 0xff80) == 0x8000) {
485 printf("0d::"); goto qprint;
486 }
f02effa0
RH
487 printf("0d%f", valuep->num_num.numFd_float.Fd_value);
488 break;
489 case TYPG:
490 printf("0g::"); goto qprint;
491 case TYPH:
492 printf("0h::"); goto qprint;
493 case TYPQ:
494 case TYPO:
495 qprint:
496 for (bindex = nbytes - 1; bindex >= 0; --bindex){
497 for (nindex = 4; nindex >= 0; nindex -= 4){
498 ch = (valuep->num_uchar[bindex] >> nindex);
499 ch &= 0x0F;
500 if ( ! (leading_zero &= (ch == 0) ) ){
501 if (ch <= 0x09)
502 printc(ch + '0');
503 else
504 printc(ch - 0x0A + 'a');
505 }
506 }
507 }
508 break;
509 }
510}
511#ifdef SDB
512
513L_INT inkdot(incr)
514 int incr;
515{
516 L_INT newdot;
517
518 newdot = dot + incr;
519 return(newdot);
520}
521
522printc(c)
523 char c;
524{
525 printf("%c", c);
526}
527
528psymoff(v, regnumber, fmt)
529 L_INT v;
530 char *fmt;
531{
532 struct proct *procp;
533 REG int diff;
534 if (fmt[0] == 'i') {
535 switch(regnumber){
536 case 12: /* parameter */
537 if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot)))
538 != -1) {
539 printf("%s", sl_name);
540 prdiff(diff);
541 return(0);
542 }
543 break;
544 case 13: /* local */
545 if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot))
546 ) != -1) {
547 printf("%s", sl_name);
548 prdiff(diff);
549 return(0);
550 }
551 break;
552 default:
553 break;
554 }
555 if (v < firstdata) {
556 if ((procp = adrtoprocp((ADDR) v)) != badproc) {
557 prlnoff(procp, v);
558 return(0);
559 }
560 } else {
561 if ((diff = adrtoext((ADDR) v)) != -1) {
562 printf("%s", sl_name);
563 prdiff(diff);
564 return(0);
7cb4340a
BJ
565 }
566 }
567 }
f02effa0
RH
568 prhex(v);
569 return(1);
570}
571
572prdiff(diff)
573{
574 if (diff) {
575 printf("+");
576 prhex(diff);
577 }
7cb4340a 578}
f02effa0 579
8ae34dba 580#endif /* SDB */