Commit | Line | Data |
---|---|---|
f02effa0 | 1 | #ifndef lint |
e9971154 | 2 | static char sccsid[] = "@(#)opset.c 4.4 %G%"; |
f02effa0 | 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 |
17 | L_INT dot; |
18 | INT dotinc; | |
f02effa0 RH |
19 | L_INT insoutvar[36]; |
20 | #ifdef ADB | |
21 | L_INT var[36]; | |
22 | #endif ADB | |
7cb4340a | 23 | |
f02effa0 RH |
24 | #undef INSTTAB |
25 | #include "instrs.h" | |
7cb4340a | 26 | |
f02effa0 RH |
27 | STRING regname[]; |
28 | STRING fltimm[]; | |
29 | POS type, space, incp; | |
7cb4340a | 30 | /* |
f02effa0 | 31 | * Definitions for registers and for operand classes |
7cb4340a | 32 | */ |
f02effa0 RH |
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) | |
7cb4340a BJ |
59 | |
60 | /* | |
f02effa0 | 61 | * Definitions for large numbers |
7cb4340a | 62 | */ |
f02effa0 RH |
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 | ||
e9971154 | 83 | short ioptab[3][256]; /* two level 1-based index by opcode into insttab */ |
f02effa0 RH |
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 | } | |
7cb4340a | 94 | |
f02effa0 RH |
95 | mkioptab() |
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 |
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 | } | |
7cb4340a | 125 | |
f02effa0 RH |
126 | printins(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 | } | |
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; | |
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 | } | |
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 */ | |
264 | static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0}; | |
265 | static 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 | */ | |
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 */ | |
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 | 298 | u_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 | */ | |
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; | |
7cb4340a | 364 | } |
f02effa0 RH |
365 | dispaddress(snarfreloc(nbytes), mode); |
366 | return(0); | |
7cb4340a BJ |
367 | } |
368 | ||
f02effa0 RH |
369 | dispaddress(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 | */ | |
402 | char *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 | */ | |
420 | shortliteral(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 |
443 | pcimmediate(mode, optype) |
444 | u_char mode; | |
445 | u_char optype; | |
7cb4340a | 446 | { |
f02effa0 RH |
447 | int nbytes; |
448 | ||
449 | printc('$'); | |
7fad38f7 | 450 | if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/ |
f02effa0 RH |
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 | ||
462 | bignumprint(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 | ||
504 | L_INT inkdot(incr) | |
505 | int incr; | |
506 | { | |
507 | L_INT newdot; | |
508 | ||
509 | newdot = dot + incr; | |
510 | return(newdot); | |
511 | } | |
512 | ||
513 | printc(c) | |
514 | char c; | |
515 | { | |
516 | printf("%c", c); | |
517 | } | |
518 | ||
519 | psymoff(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 | ||
563 | prdiff(diff) | |
564 | { | |
565 | if (diff) { | |
566 | printf("+"); | |
567 | prhex(diff); | |
568 | } | |
7cb4340a | 569 | } |
f02effa0 RH |
570 | |
571 | #endif SDB |