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