|
|
1.1 root 1: /* Print 32000 instructions for GDB, the GNU debugger.
2: Copyright (C) 1986,1988 Free Software Foundation, Inc.
3:
4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5: WARRANTY. No author or distributor accepts responsibility to anyone
6: for the consequences of using it or for whether it serves any
7: particular purpose or works at all, unless he says so in writing.
8: Refer to the GDB General Public License for full details.
9:
10: Everyone is granted permission to copy, modify and redistribute GDB,
11: but only under the conditions described in the GDB General Public
12: License. A copy of this license is supposed to have been given to you
13: along with GDB so you can know your rights and responsibilities. It
14: should be in a file named COPYING. Among other things, the copyright
15: notice and this notice must be preserved on all copies.
16:
17: In other words, go ahead and share GDB, but don't try to stop
18: anyone else from sharing it farther. Help stamp out software hoarding!
19: */
20:
21: #include <stdio.h>
22:
23: #include "defs.h"
24: #include "param.h"
25: #include "symtab.h"
26: #include "opcode.h"
27:
28: /* 32000 instructions are never longer than this. */
29: #define MAXLEN 62
30:
31: /* Number of elements in the opcode table. */
32: #define NOPCODES (sizeof notstrs / sizeof notstrs[0])
33:
34: extern char *reg_names[];
35:
36: #define NEXT_IS_ADDR '|'
37:
38: /*
39: * extract "count" bits starting "offset" bits
40: * into buffer
41: */
42:
43: int
44: bit_extract (buffer, offset, count)
45: char *buffer;
46: int offset;
47: int count;
48: {
49: int result;
50: int mask;
51: int bit;
52:
53: buffer += offset >> 3;
54: offset &= 7;
55: bit = 1;
56: result = 0;
57: while (count--)
58: {
59: if ((*buffer & (1 << offset)))
60: result |= bit;
61: if (++offset == 8)
62: {
63: offset = 0;
64: buffer++;
65: }
66: bit <<= 1;
67: }
68: return result;
69: }
70:
71: float
72: fbit_extract (buffer, offset, count)
73: {
74: union {
75: int ival;
76: float fval;
77: } foo;
78:
79: foo.ival = bit_extract (buffer, offset, 32);
80: return foo.fval;
81: }
82:
83: double
84: dbit_extract (buffer, offset, count)
85: {
86: union {
87: struct {int low, high; } ival;
88: double dval;
89: } foo;
90:
91: foo.ival.low = bit_extract (buffer, offset, 32);
92: foo.ival.high = bit_extract (buffer, offset+32, 32);
93: return foo.dval;
94: }
95:
96: sign_extend (value, bits)
97: {
98: value = value & ((1 << bits) - 1);
99: return (value & (1 << (bits-1))
100: ? value | (~((1 << bits) - 1))
101: : value);
102: }
103:
104: flip_bytes (ptr, count)
105: char *ptr;
106: int count;
107: {
108: char tmp;
109:
110: while (count > 0)
111: {
112: tmp = *ptr;
113: ptr[0] = ptr[count-1];
114: ptr[count-1] = tmp;
115: ptr++;
116: count -= 2;
117: }
118: }
119:
120:
121: /* Print the 32000 instruction at address MEMADDR in debugged memory,
122: on STREAM. Returns length of the instruction, in bytes. */
123:
124: int
125: print_insn (memaddr, stream)
126: CORE_ADDR memaddr;
127: FILE *stream;
128: {
129: unsigned char buffer[MAXLEN];
130: register int i;
131: register unsigned char *p;
132: register char *d;
133: unsigned short first_word;
134: int gen, disp;
135: int ioffset; /* bits into instruction */
136: int aoffset; /* bits into arguments */
137: char arg_bufs[MAX_ARGS+1][ARG_LEN];
138: int argnum;
139: int maxarg;
140:
141: read_memory (memaddr, buffer, MAXLEN);
142:
143: first_word = *(unsigned short *) buffer;
144: for (i = 0; i < NOPCODES; i++)
145: if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
146: == notstrs[i].detail.code)
147: break;
148:
149: /* Handle undefined instructions. */
150: if (i == NOPCODES)
151: {
152: fprintf (stream, "0%o", buffer[0]);
153: return 1;
154: }
155:
156: fprintf (stream, "%s", notstrs[i].name);
157:
158: ioffset = notstrs[i].detail.ibits;
159: aoffset = notstrs[i].detail.ibits;
160: d = notstrs[i].detail.args;
161:
162: if (*d)
163: {
164: fputc ('\t', stream);
165:
166: maxarg = 0;
167: while (*d)
168: {
169: argnum = *d - '1';
170: d++;
171: if (argnum > maxarg && argnum < MAX_ARGS)
172: maxarg = argnum;
173: ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
174: memaddr, arg_bufs[argnum]);
175: d++;
176: }
177: for (argnum = 0; argnum <= maxarg; argnum++)
178: {
179: CORE_ADDR addr;
180: char *ch, *index ();
181: for (ch = arg_bufs[argnum]; *ch;)
182: {
183: if (*ch == NEXT_IS_ADDR)
184: {
185: ++ch;
186: addr = atoi (ch);
187: print_address (addr, stream);
188: while (*ch && *ch != NEXT_IS_ADDR)
189: ++ch;
190: if (*ch)
191: ++ch;
192: }
193: else
194: putc (*ch++, stream);
195: }
196: if (argnum < maxarg)
197: fprintf (stream, ", ");
198: }
199: }
200: return aoffset / 8;
201: }
202:
203: print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
204: char d;
205: int ioffset, *aoffsetp;
206: char *buffer;
207: CORE_ADDR addr;
208: char *result;
209: {
210: int addr_mode;
211: float Fvalue;
212: double Lvalue;
213: int Ivalue;
214: int disp1, disp2;
215: int index;
216:
217: switch (d)
218: {
219: case 'F':
220: case 'L':
221: case 'B':
222: case 'W':
223: case 'D':
224: case 'A':
225: addr_mode = bit_extract (buffer, ioffset-5, 5);
226: ioffset -= 5;
227: switch (addr_mode)
228: {
229: case 0x0: case 0x1: case 0x2: case 0x3:
230: case 0x4: case 0x5: case 0x6: case 0x7:
231: switch (d)
232: {
233: case 'F':
234: case 'L':
235: sprintf (result, "f%d", addr_mode);
236: break;
237: default:
238: sprintf (result, "r%d", addr_mode);
239: }
240: break;
241: case 0x8: case 0x9: case 0xa: case 0xb:
242: case 0xc: case 0xd: case 0xe: case 0xf:
243: disp1 = get_displacement (buffer, aoffsetp);
244: sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
245: break;
246: case 0x10:
247: case 0x11:
248: case 0x12:
249: disp1 = get_displacement (buffer, aoffsetp);
250: disp2 = get_displacement (buffer, aoffsetp);
251: sprintf (result, "%d(%d(%s))", disp2, disp1,
252: addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
253: break;
254: case 0x13:
255: sprintf (result, "reserved");
256: break;
257: case 0x14:
258: switch (d)
259: {
260: case 'B':
261: Ivalue = bit_extract (buffer, *aoffsetp, 8);
262: Ivalue = sign_extend (Ivalue, 8);
263: *aoffsetp += 8;
264: sprintf (result, "$%d", Ivalue);
265: break;
266: case 'W':
267: Ivalue = bit_extract (buffer, *aoffsetp, 16);
268: flip_bytes (&Ivalue, 2);
269: *aoffsetp += 16;
270: Ivalue = sign_extend (Ivalue, 16);
271: sprintf (result, "$%d", Ivalue);
272: break;
273: case 'D':
274: Ivalue = bit_extract (buffer, *aoffsetp, 32);
275: flip_bytes (&Ivalue, 4);
276: *aoffsetp += 32;
277: sprintf (result, "$%d", Ivalue);
278: break;
279: case 'A':
280: Ivalue = bit_extract (buffer, *aoffsetp, 32);
281: flip_bytes (&Ivalue, 4);
282: *aoffsetp += 32;
283: sprintf (result, "$|%d|", Ivalue);
284: break;
285: case 'F':
286: Fvalue = fbit_extract (buffer, *aoffsetp, 32);
287: flip_bytes (&Fvalue, 4);
288: *aoffsetp += 32;
289: sprintf (result, "$%g", Fvalue);
290: break;
291: case 'L':
292: Lvalue = dbit_extract (buffer, *aoffsetp, 64);
293: flip_bytes (&Lvalue, 8);
294: *aoffsetp += 64;
295: sprintf (result, "$%g", Lvalue);
296: break;
297: }
298: break;
299: case 0x15:
300: disp1 = get_displacement (buffer, aoffsetp);
301: sprintf (result, "@|%d|", disp1);
302: break;
303: case 0x16:
304: disp1 = get_displacement (buffer, aoffsetp);
305: disp2 = get_displacement (buffer, aoffsetp);
306: sprintf (result, "EXT(%d) + %d", disp1, disp2);
307: break;
308: case 0x17:
309: sprintf (result, "tos");
310: break;
311: case 0x18:
312: disp1 = get_displacement (buffer, aoffsetp);
313: sprintf (result, "%d(fp)", disp1);
314: break;
315: case 0x19:
316: disp1 = get_displacement (buffer, aoffsetp);
317: sprintf (result, "%d(sp)", disp1);
318: break;
319: case 0x1a:
320: disp1 = get_displacement (buffer, aoffsetp);
321: sprintf (result, "%d(sb)", disp1);
322: break;
323: case 0x1b:
324: disp1 = get_displacement (buffer, aoffsetp);
325: sprintf (result, "|%d|", addr + disp1);
326: break;
327: case 0x1c:
328: case 0x1d:
329: case 0x1e:
330: case 0x1f:
331: index = bit_extract (buffer, *aoffsetp, 8);
332: *aoffsetp += 8;
333: print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
334: result);
335: {
336: static char *ind[] = {"b", "w", "d", "q"};
337: char *off;
338:
339: off = result + strlen (result);
340: sprintf (off, "[r%d:%s]", index & 7,
341: ind[addr_mode & 3]);
342: }
343: break;
344: }
345: break;
346: case 'q':
347: Ivalue = bit_extract (buffer, ioffset-4, 4);
348: Ivalue = sign_extend (Ivalue, 4);
349: sprintf (result, "%d", Ivalue);
350: ioffset -= 4;
351: break;
352: case 'r':
353: Ivalue = bit_extract (buffer, ioffset-3, 3);
354: sprintf (result, "r%d", Ivalue&7);
355: ioffset -= 3;
356: break;
357: case 'd':
358: sprintf (result, "%d", get_displacement (buffer, aoffsetp));
359: break;
360: case 'p':
361: sprintf (result, "%c%d%c", NEXT_IS_ADDR,
362: addr + get_displacement (buffer, aoffsetp),
363: NEXT_IS_ADDR);
364: break;
365: case 'i':
366: Ivalue = bit_extract (buffer, *aoffsetp, 8);
367: *aoffsetp += 8;
368: sprintf (result, "0x%x", Ivalue);
369: break;
370: }
371: return ioffset;
372: }
373:
374: get_displacement (buffer, aoffsetp)
375: char *buffer;
376: int *aoffsetp;
377: {
378: int Ivalue;
379:
380: Ivalue = bit_extract (buffer, *aoffsetp, 8);
381: switch (Ivalue & 0xc0)
382: {
383: case 0x00:
384: case 0x40:
385: Ivalue = sign_extend (Ivalue, 7);
386: *aoffsetp += 8;
387: break;
388: case 0x80:
389: Ivalue = bit_extract (buffer, *aoffsetp, 16);
390: flip_bytes (&Ivalue, 2);
391: Ivalue = sign_extend (Ivalue, 14);
392: *aoffsetp += 16;
393: break;
394: case 0xc0:
395: Ivalue = bit_extract (buffer, *aoffsetp, 32);
396: flip_bytes (&Ivalue, 4);
397: Ivalue = sign_extend (Ivalue, 30);
398: *aoffsetp += 32;
399: break;
400: }
401: return Ivalue;
402: }
403:
404: /* Return the number of locals in the current frame given a pc
405: pointing to the enter instruction. This is used in the macro
406: FRAME_FIND_SAVED_REGS. */
407:
408: ns32k_localcount (enter_pc)
409: CORE_ADDR enter_pc;
410: {
411: unsigned char localtype;
412: int localcount;
413:
414: localtype = read_memory_integer (enter_pc+2, 1);
415: if ((localtype & 0x80) == 0)
416: localcount = localtype;
417: else if ((localtype & 0xc0) == 0x80)
418: localcount = (((localtype & 0x3f) << 8)
419: | (read_memory_integer (enter_pc+3, 1) & 0xff));
420: else
421: localcount = (((localtype & 0x3f) << 24)
422: | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
423: | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
424: | (read_memory_integer (enter_pc+5, 1) & 0xff));
425: return localcount;
426: }
427:
428: /*
429: * Get the address of the enter opcode for the function
430: * containing PC, if there is an enter for the function,
431: * and if the pc is between the enter and exit.
432: * Returns positive address if pc is between enter/exit,
433: * 1 if pc before enter or after exit, 0 otherwise.
434: */
435:
436: CORE_ADDR
437: ns32k_get_enter_addr (pc)
438: CORE_ADDR pc;
439: {
440: CORE_ADDR enter_addr;
441: unsigned char op;
442:
443: if (ABOUT_TO_RETURN (pc))
444: return 1; /* after exit */
445:
446: enter_addr = get_pc_function_start (pc);
447:
448: if (pc == enter_addr)
449: return 1; /* before enter */
450:
451: op = read_memory_integer (enter_addr, 1);
452:
453: if (op != 0x82)
454: return 0; /* function has no enter/exit */
455:
456: return enter_addr; /* pc is between enter and exit */
457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.