gdb-3.5
[deliverable/binutils-gdb.git] / gdb / ns32k-pinsn.c
CommitLineData
3bf57d21 1/* Print 32000 instructions for GDB, the GNU debugger.
2 Copyright (C) 1986,1988 Free Software Foundation, Inc.
3
4GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5WARRANTY. No author or distributor accepts responsibility to anyone
6for the consequences of using it or for whether it serves any
7particular purpose or works at all, unless he says so in writing.
8Refer to the GDB General Public License for full details.
9
10Everyone is granted permission to copy, modify and redistribute GDB,
11but only under the conditions described in the GDB General Public
12License. A copy of this license is supposed to have been given to you
13along with GDB so you can know your rights and responsibilities. It
14should be in a file named COPYING. Among other things, the copyright
15notice and this notice must be preserved on all copies.
16
17In other words, go ahead and share GDB, but don't try to stop
18anyone 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
34extern char *reg_names[];
35
36#define NEXT_IS_ADDR '|'
37
38/*
39 * extract "count" bits starting "offset" bits
40 * into buffer
41 */
42
43int
44bit_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
71float
72fbit_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
83double
84dbit_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
96sign_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
104flip_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}
4187119d 119\f
120/* Given a character C, does it represent a general addressing mode? */
121#define Is_gen(c) \
122 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
123 || (c) == 'W' || (c) == 'D' || (c) == 'A')
124
125/* Adressing modes. */
126#define Adrmod_index_byte 0x1c
127#define Adrmod_index_word 0x1d
128#define Adrmod_index_doubleword 0x1e
129#define Adrmod_index_quadword 0x1f
130
131/* Is MODE an indexed addressing mode? */
132#define Adrmod_is_index(mode) \
133 (mode == Adrmod_index_byte \
134 || mode == Adrmod_index_word \
135 || mode == Adrmod_index_doubleword \
136 || mode == Adrmod_index_quadword)
3bf57d21 137
138\f
139/* Print the 32000 instruction at address MEMADDR in debugged memory,
140 on STREAM. Returns length of the instruction, in bytes. */
141
142int
143print_insn (memaddr, stream)
4187119d 144 CORE_ADDR memaddr;
145 FILE *stream;
3bf57d21 146{
147 unsigned char buffer[MAXLEN];
148 register int i;
149 register unsigned char *p;
150 register char *d;
151 unsigned short first_word;
152 int gen, disp;
153 int ioffset; /* bits into instruction */
154 int aoffset; /* bits into arguments */
155 char arg_bufs[MAX_ARGS+1][ARG_LEN];
156 int argnum;
157 int maxarg;
158
159 read_memory (memaddr, buffer, MAXLEN);
160
161 first_word = *(unsigned short *) buffer;
162 for (i = 0; i < NOPCODES; i++)
163 if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
164 == notstrs[i].detail.code)
165 break;
166
167 /* Handle undefined instructions. */
168 if (i == NOPCODES)
169 {
170 fprintf (stream, "0%o", buffer[0]);
171 return 1;
172 }
173
174 fprintf (stream, "%s", notstrs[i].name);
175
176 ioffset = notstrs[i].detail.ibits;
177 aoffset = notstrs[i].detail.ibits;
178 d = notstrs[i].detail.args;
179
180 if (*d)
181 {
4187119d 182 /* Offset in bits of the first thing beyond each index byte.
183 Element 0 is for operand A and element 1 is for operand B.
184 The rest are irrelevant, but we put them here so we don't
185 index outside the array. */
186 int index_offset[MAX_ARGS];
187
188 /* 0 for operand A, 1 for operand B, greater for other args. */
189 int whicharg = 0;
190
3bf57d21 191 fputc ('\t', stream);
192
193 maxarg = 0;
4187119d 194
195 /* First we have to find and keep track of the index bytes,
196 if we are using scaled indexed addressing mode, since the index
197 bytes occur right after the basic instruction, not as part
198 of the addressing extension. */
199 if (Is_gen(d[1]))
200 {
201 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
202
203 if (Adrmod_is_index (addr_mode))
204 {
205 aoffset += 8;
206 index_offset[0] = aoffset;
207 }
208 }
209 if (d[2] && Is_gen(d[3]))
210 {
211 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
212
213 if (Adrmod_is_index (addr_mode))
214 {
215 aoffset += 8;
216 index_offset[1] = aoffset;
217 }
218 }
219
3bf57d21 220 while (*d)
221 {
222 argnum = *d - '1';
223 d++;
224 if (argnum > maxarg && argnum < MAX_ARGS)
225 maxarg = argnum;
226 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
4187119d 227 memaddr, arg_bufs[argnum],
228 index_offset[whicharg]);
3bf57d21 229 d++;
4187119d 230 whicharg++;
3bf57d21 231 }
232 for (argnum = 0; argnum <= maxarg; argnum++)
233 {
234 CORE_ADDR addr;
235 char *ch, *index ();
236 for (ch = arg_bufs[argnum]; *ch;)
237 {
238 if (*ch == NEXT_IS_ADDR)
239 {
240 ++ch;
241 addr = atoi (ch);
242 print_address (addr, stream);
243 while (*ch && *ch != NEXT_IS_ADDR)
244 ++ch;
245 if (*ch)
246 ++ch;
247 }
248 else
249 putc (*ch++, stream);
250 }
251 if (argnum < maxarg)
252 fprintf (stream, ", ");
253 }
254 }
255 return aoffset / 8;
256}
257
4187119d 258/* Print an instruction operand of category given by d. IOFFSET is
259 the bit position below which small (<1 byte) parts of the operand can
260 be found (usually in the basic instruction, but for indexed
261 addressing it can be in the index byte). AOFFSETP is a pointer to the
262 bit position of the addressing extension. BUFFER contains the
263 instruction. ADDR is where BUFFER was read from. Put the disassembled
264 version of the operand in RESULT. INDEX_OFFSET is the bit position
265 of the index byte (it contains garbage if this operand is not a
266 general operand using scaled indexed addressing mode). */
267
268print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
3bf57d21 269 char d;
270 int ioffset, *aoffsetp;
271 char *buffer;
272 CORE_ADDR addr;
273 char *result;
4187119d 274 int index_offset;
3bf57d21 275{
276 int addr_mode;
277 float Fvalue;
278 double Lvalue;
279 int Ivalue;
280 int disp1, disp2;
281 int index;
282
283 switch (d)
284 {
285 case 'F':
286 case 'L':
287 case 'B':
288 case 'W':
289 case 'D':
290 case 'A':
291 addr_mode = bit_extract (buffer, ioffset-5, 5);
292 ioffset -= 5;
293 switch (addr_mode)
294 {
295 case 0x0: case 0x1: case 0x2: case 0x3:
296 case 0x4: case 0x5: case 0x6: case 0x7:
297 switch (d)
298 {
299 case 'F':
300 case 'L':
301 sprintf (result, "f%d", addr_mode);
302 break;
303 default:
304 sprintf (result, "r%d", addr_mode);
305 }
306 break;
307 case 0x8: case 0x9: case 0xa: case 0xb:
308 case 0xc: case 0xd: case 0xe: case 0xf:
309 disp1 = get_displacement (buffer, aoffsetp);
310 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
311 break;
312 case 0x10:
313 case 0x11:
314 case 0x12:
315 disp1 = get_displacement (buffer, aoffsetp);
316 disp2 = get_displacement (buffer, aoffsetp);
317 sprintf (result, "%d(%d(%s))", disp2, disp1,
318 addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
319 break;
320 case 0x13:
321 sprintf (result, "reserved");
322 break;
323 case 0x14:
324 switch (d)
325 {
326 case 'B':
327 Ivalue = bit_extract (buffer, *aoffsetp, 8);
328 Ivalue = sign_extend (Ivalue, 8);
329 *aoffsetp += 8;
330 sprintf (result, "$%d", Ivalue);
331 break;
332 case 'W':
333 Ivalue = bit_extract (buffer, *aoffsetp, 16);
334 flip_bytes (&Ivalue, 2);
335 *aoffsetp += 16;
336 Ivalue = sign_extend (Ivalue, 16);
337 sprintf (result, "$%d", Ivalue);
338 break;
339 case 'D':
340 Ivalue = bit_extract (buffer, *aoffsetp, 32);
341 flip_bytes (&Ivalue, 4);
342 *aoffsetp += 32;
343 sprintf (result, "$%d", Ivalue);
344 break;
345 case 'A':
346 Ivalue = bit_extract (buffer, *aoffsetp, 32);
347 flip_bytes (&Ivalue, 4);
348 *aoffsetp += 32;
349 sprintf (result, "$|%d|", Ivalue);
350 break;
351 case 'F':
352 Fvalue = fbit_extract (buffer, *aoffsetp, 32);
353 flip_bytes (&Fvalue, 4);
354 *aoffsetp += 32;
355 sprintf (result, "$%g", Fvalue);
356 break;
357 case 'L':
358 Lvalue = dbit_extract (buffer, *aoffsetp, 64);
359 flip_bytes (&Lvalue, 8);
360 *aoffsetp += 64;
361 sprintf (result, "$%g", Lvalue);
362 break;
363 }
364 break;
365 case 0x15:
366 disp1 = get_displacement (buffer, aoffsetp);
367 sprintf (result, "@|%d|", disp1);
368 break;
369 case 0x16:
370 disp1 = get_displacement (buffer, aoffsetp);
371 disp2 = get_displacement (buffer, aoffsetp);
372 sprintf (result, "EXT(%d) + %d", disp1, disp2);
373 break;
374 case 0x17:
375 sprintf (result, "tos");
376 break;
377 case 0x18:
378 disp1 = get_displacement (buffer, aoffsetp);
379 sprintf (result, "%d(fp)", disp1);
380 break;
381 case 0x19:
382 disp1 = get_displacement (buffer, aoffsetp);
383 sprintf (result, "%d(sp)", disp1);
384 break;
385 case 0x1a:
386 disp1 = get_displacement (buffer, aoffsetp);
387 sprintf (result, "%d(sb)", disp1);
388 break;
389 case 0x1b:
390 disp1 = get_displacement (buffer, aoffsetp);
391 sprintf (result, "|%d|", addr + disp1);
392 break;
393 case 0x1c:
394 case 0x1d:
395 case 0x1e:
396 case 0x1f:
4187119d 397 index = bit_extract (buffer, index_offset - 8, 3);
398 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
399 result, 0);
3bf57d21 400 {
401 static char *ind[] = {"b", "w", "d", "q"};
402 char *off;
403
404 off = result + strlen (result);
4187119d 405 sprintf (off, "[r%d:%s]", index,
3bf57d21 406 ind[addr_mode & 3]);
407 }
408 break;
409 }
410 break;
411 case 'q':
412 Ivalue = bit_extract (buffer, ioffset-4, 4);
413 Ivalue = sign_extend (Ivalue, 4);
414 sprintf (result, "%d", Ivalue);
415 ioffset -= 4;
416 break;
417 case 'r':
418 Ivalue = bit_extract (buffer, ioffset-3, 3);
419 sprintf (result, "r%d", Ivalue&7);
420 ioffset -= 3;
421 break;
422 case 'd':
423 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
424 break;
425 case 'p':
426 sprintf (result, "%c%d%c", NEXT_IS_ADDR,
427 addr + get_displacement (buffer, aoffsetp),
428 NEXT_IS_ADDR);
429 break;
430 case 'i':
431 Ivalue = bit_extract (buffer, *aoffsetp, 8);
432 *aoffsetp += 8;
433 sprintf (result, "0x%x", Ivalue);
434 break;
435 }
436 return ioffset;
437}
438
439get_displacement (buffer, aoffsetp)
440 char *buffer;
441 int *aoffsetp;
442{
443 int Ivalue;
444
445 Ivalue = bit_extract (buffer, *aoffsetp, 8);
446 switch (Ivalue & 0xc0)
447 {
448 case 0x00:
449 case 0x40:
450 Ivalue = sign_extend (Ivalue, 7);
451 *aoffsetp += 8;
452 break;
453 case 0x80:
454 Ivalue = bit_extract (buffer, *aoffsetp, 16);
455 flip_bytes (&Ivalue, 2);
456 Ivalue = sign_extend (Ivalue, 14);
457 *aoffsetp += 16;
458 break;
459 case 0xc0:
460 Ivalue = bit_extract (buffer, *aoffsetp, 32);
461 flip_bytes (&Ivalue, 4);
462 Ivalue = sign_extend (Ivalue, 30);
463 *aoffsetp += 32;
464 break;
465 }
466 return Ivalue;
467}
468\f
469/* Return the number of locals in the current frame given a pc
470 pointing to the enter instruction. This is used in the macro
471 FRAME_FIND_SAVED_REGS. */
472
473ns32k_localcount (enter_pc)
474 CORE_ADDR enter_pc;
475{
476 unsigned char localtype;
477 int localcount;
478
479 localtype = read_memory_integer (enter_pc+2, 1);
480 if ((localtype & 0x80) == 0)
481 localcount = localtype;
482 else if ((localtype & 0xc0) == 0x80)
483 localcount = (((localtype & 0x3f) << 8)
484 | (read_memory_integer (enter_pc+3, 1) & 0xff));
485 else
486 localcount = (((localtype & 0x3f) << 24)
487 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
488 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
489 | (read_memory_integer (enter_pc+5, 1) & 0xff));
490 return localcount;
491}
492
493/*
494 * Get the address of the enter opcode for the function
495 * containing PC, if there is an enter for the function,
496 * and if the pc is between the enter and exit.
497 * Returns positive address if pc is between enter/exit,
498 * 1 if pc before enter or after exit, 0 otherwise.
499 */
500
501CORE_ADDR
502ns32k_get_enter_addr (pc)
503 CORE_ADDR pc;
504{
505 CORE_ADDR enter_addr;
506 unsigned char op;
507
508 if (ABOUT_TO_RETURN (pc))
509 return 1; /* after exit */
510
511 enter_addr = get_pc_function_start (pc);
512
513 if (pc == enter_addr)
514 return 1; /* before enter */
515
516 op = read_memory_integer (enter_addr, 1);
517
518 if (op != 0x82)
519 return 0; /* function has no enter/exit */
520
521 return enter_addr; /* pc is between enter and exit */
522}
This page took 0.042839 seconds and 4 git commands to generate.