Complete reworking of opset.c to make its operation understandable
[unix-history] / usr / src / old / adb / adb.vax / opset.c
CommitLineData
f02effa0
RH
1#ifndef lint
2static char sccsid[] = "@(#)opset.c 4.2 %G%";
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"
f02effa0
RH
12#endif ADB
13#ifdef SDB
14#include "head.h"
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];
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
83short ioptab[3][256]; /* two level index by opcode into insttab */
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;
104 ioptab[mapchar][p->popcode] = p - insttab;
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;
117#endif SDB
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 }
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
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 }
182 ip = &insttab[ioptab[mapchar][ins]];
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;
226#endif SDB
227#ifdef ADB
228 dotinc = incp;
229#endif ADB
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);
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 }
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
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 */
402char *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 */
420shortliteral(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 }
7cb4340a
BJ
441}
442
f02effa0
RH
443pcimmediate(mode, optype)
444 u_char mode;
445 u_char optype;
7cb4340a 446{
f02effa0
RH
447 int nbytes;
448
449 printc('$');
450 if (mode == OC_DAIREG){ /* 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
462bignumprint(nbytes, optype)
463 int nbytes;
464 u_char optype;
465{
466 numberp valuep;
7cb4340a 467 int leading_zero = 1;
f02effa0
RH
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
504L_INT inkdot(incr)
505 int incr;
506{
507 L_INT newdot;
508
509 newdot = dot + incr;
510 return(newdot);
511}
512
513printc(c)
514 char c;
515{
516 printf("%c", c);
517}
518
519psymoff(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);
7cb4340a
BJ
556 }
557 }
558 }
f02effa0
RH
559 prhex(v);
560 return(1);
561}
562
563prdiff(diff)
564{
565 if (diff) {
566 printf("+");
567 prhex(diff);
568 }
7cb4340a 569}
f02effa0
RH
570
571#endif SDB