Johns release
[deliverable/binutils-gdb.git] / gdb / ns32k-pinsn.c
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 "ns32k-opcode.h"
27 #include "gdbcore.h"
28
29 /* 32000 instructions are never longer than this. */
30 #define MAXLEN 62
31
32 /* Number of elements in the opcode table. */
33 #define NOPCODES (sizeof notstrs / sizeof notstrs[0])
34
35 extern char *reg_names[];
36
37 #define NEXT_IS_ADDR '|'
38
39 /*
40 * extract "count" bits starting "offset" bits
41 * into buffer
42 */
43
44 int
45 bit_extract (buffer, offset, count)
46 char *buffer;
47 int offset;
48 int count;
49 {
50 int result;
51 int mask;
52 int bit;
53
54 buffer += offset >> 3;
55 offset &= 7;
56 bit = 1;
57 result = 0;
58 while (count--)
59 {
60 if ((*buffer & (1 << offset)))
61 result |= bit;
62 if (++offset == 8)
63 {
64 offset = 0;
65 buffer++;
66 }
67 bit <<= 1;
68 }
69 return result;
70 }
71
72 float
73 fbit_extract (buffer, offset, count)
74 {
75 union {
76 int ival;
77 float fval;
78 } foo;
79
80 foo.ival = bit_extract (buffer, offset, 32);
81 return foo.fval;
82 }
83
84 double
85 dbit_extract (buffer, offset, count)
86 {
87 union {
88 struct {int low, high; } ival;
89 double dval;
90 } foo;
91
92 foo.ival.low = bit_extract (buffer, offset, 32);
93 foo.ival.high = bit_extract (buffer, offset+32, 32);
94 return foo.dval;
95 }
96
97 sign_extend (value, bits)
98 {
99 value = value & ((1 << bits) - 1);
100 return (value & (1 << (bits-1))
101 ? value | (~((1 << bits) - 1))
102 : value);
103 }
104
105 flip_bytes (ptr, count)
106 char *ptr;
107 int count;
108 {
109 char tmp;
110
111 while (count > 0)
112 {
113 tmp = *ptr;
114 ptr[0] = ptr[count-1];
115 ptr[count-1] = tmp;
116 ptr++;
117 count -= 2;
118 }
119 }
120 \f
121 /* Given a character C, does it represent a general addressing mode? */
122 #define Is_gen(c) \
123 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
124 || (c) == 'W' || (c) == 'D' || (c) == 'A')
125
126 /* Adressing modes. */
127 #define Adrmod_index_byte 0x1c
128 #define Adrmod_index_word 0x1d
129 #define Adrmod_index_doubleword 0x1e
130 #define Adrmod_index_quadword 0x1f
131
132 /* Is MODE an indexed addressing mode? */
133 #define Adrmod_is_index(mode) \
134 (mode == Adrmod_index_byte \
135 || mode == Adrmod_index_word \
136 || mode == Adrmod_index_doubleword \
137 || mode == Adrmod_index_quadword)
138
139 \f
140 /* Print the 32000 instruction at address MEMADDR in debugged memory,
141 on STREAM. Returns length of the instruction, in bytes. */
142
143 int
144 print_insn (memaddr, stream)
145 CORE_ADDR memaddr;
146 FILE *stream;
147 {
148 unsigned char buffer[MAXLEN];
149 register int i;
150 register unsigned char *p;
151 register char *d;
152 unsigned short first_word;
153 int gen, disp;
154 int ioffset; /* bits into instruction */
155 int aoffset; /* bits into arguments */
156 char arg_bufs[MAX_ARGS+1][ARG_LEN];
157 int argnum;
158 int maxarg;
159
160 read_memory (memaddr, buffer, MAXLEN);
161
162 first_word = *(unsigned short *) buffer;
163 for (i = 0; i < NOPCODES; i++)
164 if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
165 == notstrs[i].detail.code)
166 break;
167
168 /* Handle undefined instructions. */
169 if (i == NOPCODES)
170 {
171 fprintf (stream, "0%o", buffer[0]);
172 return 1;
173 }
174
175 fprintf (stream, "%s", notstrs[i].name);
176
177 ioffset = notstrs[i].detail.ibits;
178 aoffset = notstrs[i].detail.ibits;
179 d = notstrs[i].detail.args;
180
181 if (*d)
182 {
183 /* Offset in bits of the first thing beyond each index byte.
184 Element 0 is for operand A and element 1 is for operand B.
185 The rest are irrelevant, but we put them here so we don't
186 index outside the array. */
187 int index_offset[MAX_ARGS];
188
189 /* 0 for operand A, 1 for operand B, greater for other args. */
190 int whicharg = 0;
191
192 fputc ('\t', stream);
193
194 maxarg = 0;
195
196 /* First we have to find and keep track of the index bytes,
197 if we are using scaled indexed addressing mode, since the index
198 bytes occur right after the basic instruction, not as part
199 of the addressing extension. */
200 if (Is_gen(d[1]))
201 {
202 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
203
204 if (Adrmod_is_index (addr_mode))
205 {
206 aoffset += 8;
207 index_offset[0] = aoffset;
208 }
209 }
210 if (d[2] && Is_gen(d[3]))
211 {
212 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
213
214 if (Adrmod_is_index (addr_mode))
215 {
216 aoffset += 8;
217 index_offset[1] = aoffset;
218 }
219 }
220
221 while (*d)
222 {
223 argnum = *d - '1';
224 d++;
225 if (argnum > maxarg && argnum < MAX_ARGS)
226 maxarg = argnum;
227 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
228 memaddr, arg_bufs[argnum],
229 index_offset[whicharg]);
230 d++;
231 whicharg++;
232 }
233 for (argnum = 0; argnum <= maxarg; argnum++)
234 {
235 CORE_ADDR addr;
236 char *ch, *index ();
237 for (ch = arg_bufs[argnum]; *ch;)
238 {
239 if (*ch == NEXT_IS_ADDR)
240 {
241 ++ch;
242 addr = atoi (ch);
243 print_address (addr, stream);
244 while (*ch && *ch != NEXT_IS_ADDR)
245 ++ch;
246 if (*ch)
247 ++ch;
248 }
249 else
250 putc (*ch++, stream);
251 }
252 if (argnum < maxarg)
253 fprintf (stream, ", ");
254 }
255 }
256 return aoffset / 8;
257 }
258
259 /* Print an instruction operand of category given by d. IOFFSET is
260 the bit position below which small (<1 byte) parts of the operand can
261 be found (usually in the basic instruction, but for indexed
262 addressing it can be in the index byte). AOFFSETP is a pointer to the
263 bit position of the addressing extension. BUFFER contains the
264 instruction. ADDR is where BUFFER was read from. Put the disassembled
265 version of the operand in RESULT. INDEX_OFFSET is the bit position
266 of the index byte (it contains garbage if this operand is not a
267 general operand using scaled indexed addressing mode). */
268
269 print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
270 char d;
271 int ioffset, *aoffsetp;
272 char *buffer;
273 CORE_ADDR addr;
274 char *result;
275 int index_offset;
276 {
277 int addr_mode;
278 float Fvalue;
279 double Lvalue;
280 int Ivalue;
281 int disp1, disp2;
282 int index;
283
284 switch (d)
285 {
286 case 'F':
287 case 'L':
288 case 'B':
289 case 'W':
290 case 'D':
291 case 'A':
292 addr_mode = bit_extract (buffer, ioffset-5, 5);
293 ioffset -= 5;
294 switch (addr_mode)
295 {
296 case 0x0: case 0x1: case 0x2: case 0x3:
297 case 0x4: case 0x5: case 0x6: case 0x7:
298 switch (d)
299 {
300 case 'F':
301 case 'L':
302 sprintf (result, "f%d", addr_mode);
303 break;
304 default:
305 sprintf (result, "r%d", addr_mode);
306 }
307 break;
308 case 0x8: case 0x9: case 0xa: case 0xb:
309 case 0xc: case 0xd: case 0xe: case 0xf:
310 disp1 = get_displacement (buffer, aoffsetp);
311 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
312 break;
313 case 0x10:
314 case 0x11:
315 case 0x12:
316 disp1 = get_displacement (buffer, aoffsetp);
317 disp2 = get_displacement (buffer, aoffsetp);
318 sprintf (result, "%d(%d(%s))", disp2, disp1,
319 addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
320 break;
321 case 0x13:
322 sprintf (result, "reserved");
323 break;
324 case 0x14:
325 switch (d)
326 {
327 case 'B':
328 Ivalue = bit_extract (buffer, *aoffsetp, 8);
329 Ivalue = sign_extend (Ivalue, 8);
330 *aoffsetp += 8;
331 sprintf (result, "$%d", Ivalue);
332 break;
333 case 'W':
334 Ivalue = bit_extract (buffer, *aoffsetp, 16);
335 flip_bytes (&Ivalue, 2);
336 *aoffsetp += 16;
337 Ivalue = sign_extend (Ivalue, 16);
338 sprintf (result, "$%d", Ivalue);
339 break;
340 case 'D':
341 Ivalue = bit_extract (buffer, *aoffsetp, 32);
342 flip_bytes (&Ivalue, 4);
343 *aoffsetp += 32;
344 sprintf (result, "$%d", Ivalue);
345 break;
346 case 'A':
347 Ivalue = bit_extract (buffer, *aoffsetp, 32);
348 flip_bytes (&Ivalue, 4);
349 *aoffsetp += 32;
350 sprintf (result, "$|%d|", Ivalue);
351 break;
352 case 'F':
353 Fvalue = fbit_extract (buffer, *aoffsetp, 32);
354 flip_bytes (&Fvalue, 4);
355 *aoffsetp += 32;
356 sprintf (result, "$%g", Fvalue);
357 break;
358 case 'L':
359 Lvalue = dbit_extract (buffer, *aoffsetp, 64);
360 flip_bytes (&Lvalue, 8);
361 *aoffsetp += 64;
362 sprintf (result, "$%g", Lvalue);
363 break;
364 }
365 break;
366 case 0x15:
367 disp1 = get_displacement (buffer, aoffsetp);
368 sprintf (result, "@|%d|", disp1);
369 break;
370 case 0x16:
371 disp1 = get_displacement (buffer, aoffsetp);
372 disp2 = get_displacement (buffer, aoffsetp);
373 sprintf (result, "EXT(%d) + %d", disp1, disp2);
374 break;
375 case 0x17:
376 sprintf (result, "tos");
377 break;
378 case 0x18:
379 disp1 = get_displacement (buffer, aoffsetp);
380 sprintf (result, "%d(fp)", disp1);
381 break;
382 case 0x19:
383 disp1 = get_displacement (buffer, aoffsetp);
384 sprintf (result, "%d(sp)", disp1);
385 break;
386 case 0x1a:
387 disp1 = get_displacement (buffer, aoffsetp);
388 sprintf (result, "%d(sb)", disp1);
389 break;
390 case 0x1b:
391 disp1 = get_displacement (buffer, aoffsetp);
392 sprintf (result, "|%d|", addr + disp1);
393 break;
394 case 0x1c:
395 case 0x1d:
396 case 0x1e:
397 case 0x1f:
398 index = bit_extract (buffer, index_offset - 8, 3);
399 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
400 result, 0);
401 {
402 static char *ind[] = {"b", "w", "d", "q"};
403 char *off;
404
405 off = result + strlen (result);
406 sprintf (off, "[r%d:%s]", index,
407 ind[addr_mode & 3]);
408 }
409 break;
410 }
411 break;
412 case 'q':
413 Ivalue = bit_extract (buffer, ioffset-4, 4);
414 Ivalue = sign_extend (Ivalue, 4);
415 sprintf (result, "%d", Ivalue);
416 ioffset -= 4;
417 break;
418 case 'r':
419 Ivalue = bit_extract (buffer, ioffset-3, 3);
420 sprintf (result, "r%d", Ivalue&7);
421 ioffset -= 3;
422 break;
423 case 'd':
424 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
425 break;
426 case 'p':
427 sprintf (result, "%c%d%c", NEXT_IS_ADDR,
428 addr + get_displacement (buffer, aoffsetp),
429 NEXT_IS_ADDR);
430 break;
431 case 'i':
432 Ivalue = bit_extract (buffer, *aoffsetp, 8);
433 *aoffsetp += 8;
434 sprintf (result, "0x%x", Ivalue);
435 break;
436 }
437 return ioffset;
438 }
439
440 get_displacement (buffer, aoffsetp)
441 char *buffer;
442 int *aoffsetp;
443 {
444 int Ivalue;
445
446 Ivalue = bit_extract (buffer, *aoffsetp, 8);
447 switch (Ivalue & 0xc0)
448 {
449 case 0x00:
450 case 0x40:
451 Ivalue = sign_extend (Ivalue, 7);
452 *aoffsetp += 8;
453 break;
454 case 0x80:
455 Ivalue = bit_extract (buffer, *aoffsetp, 16);
456 flip_bytes (&Ivalue, 2);
457 Ivalue = sign_extend (Ivalue, 14);
458 *aoffsetp += 16;
459 break;
460 case 0xc0:
461 Ivalue = bit_extract (buffer, *aoffsetp, 32);
462 flip_bytes (&Ivalue, 4);
463 Ivalue = sign_extend (Ivalue, 30);
464 *aoffsetp += 32;
465 break;
466 }
467 return Ivalue;
468 }
469 \f
470 /* Return the number of locals in the current frame given a pc
471 pointing to the enter instruction. This is used in the macro
472 FRAME_FIND_SAVED_REGS. */
473
474 ns32k_localcount (enter_pc)
475 CORE_ADDR enter_pc;
476 {
477 unsigned char localtype;
478 int localcount;
479
480 localtype = read_memory_integer (enter_pc+2, 1);
481 if ((localtype & 0x80) == 0)
482 localcount = localtype;
483 else if ((localtype & 0xc0) == 0x80)
484 localcount = (((localtype & 0x3f) << 8)
485 | (read_memory_integer (enter_pc+3, 1) & 0xff));
486 else
487 localcount = (((localtype & 0x3f) << 24)
488 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
489 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
490 | (read_memory_integer (enter_pc+5, 1) & 0xff));
491 return localcount;
492 }
493
494 /*
495 * Get the address of the enter opcode for the function
496 * containing PC, if there is an enter for the function,
497 * and if the pc is between the enter and exit.
498 * Returns positive address if pc is between enter/exit,
499 * 1 if pc before enter or after exit, 0 otherwise.
500 */
501
502 CORE_ADDR
503 ns32k_get_enter_addr (pc)
504 CORE_ADDR pc;
505 {
506 CORE_ADDR enter_addr;
507 unsigned char op;
508
509 if (ABOUT_TO_RETURN (pc))
510 return 1; /* after exit */
511
512 enter_addr = get_pc_function_start (pc);
513
514 if (pc == enter_addr)
515 return 1; /* before enter */
516
517 op = read_memory_integer (enter_addr, 1);
518
519 if (op != 0x82)
520 return 0; /* function has no enter/exit */
521
522 return enter_addr; /* pc is between enter and exit */
523 }
This page took 0.046503 seconds and 4 git commands to generate.