]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ns32k-pinsn.c
gdb-2.4+.aux.coff
[thirdparty/binutils-gdb.git] / gdb / ns32k-pinsn.c
CommitLineData
7b4ac7e1 1/* Print 32000 instructions for GDB, the GNU debugger.
2 Copyright (C) 1986 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 "ns32k-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
71double
72dbit_extract (buffer, offset, count)
73{
74 union {
75 struct {int low, high; } ival;
76 double dval;
77 } foo;
78
79 foo.ival.low = bit_extract (buffer, offset, 32);
80 foo.ival.high = bit_extract (buffer, offset+32, 32);
81 return foo.dval;
82}
83
84sign_extend (value, bits)
85{
86 value = value & ((1 << bits) - 1);
87 return (value & (1 << (bits-1))
88 ? value | (~((1 << bits) - 1))
89 : value);
90}
91
92flip_bytes (ptr, count)
93 char *ptr;
94 int count;
95{
96 char tmp;
97
98 while (count > 0)
99 {
100 tmp = *ptr;
101 ptr[0] = ptr[count-1];
102 ptr[count-1] = tmp;
103 ptr++;
104 count -= 2;
105 }
106}
107
108\f
109/* Print the 32000 instruction at address MEMADDR in debugged memory,
110 on STREAM. Returns length of the instruction, in bytes. */
111
112int
113print_insn (memaddr, stream)
114CORE_ADDR memaddr;
115FILE *stream;
116{
117 unsigned char buffer[MAXLEN];
118 register int i;
119 register unsigned char *p;
120 register char *d;
121 unsigned short first_word;
122 int gen, disp;
123 int ioffset; /* bits into instruction */
124 int aoffset; /* bits into arguments */
125 char arg_bufs[MAX_ARGS+1][ARG_LEN];
126 int argnum;
127 int maxarg;
128
129 read_memory (memaddr, buffer, MAXLEN);
130
131 first_word = *(unsigned short *) buffer;
132 for (i = 0; i < NOPCODES; i++)
133 if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
134 == notstrs[i].detail.code)
135 break;
136
137 /* Handle undefined instructions. */
138 if (i == NOPCODES)
139 {
140 fprintf (stream, "0%o", buffer[0]);
141 return 1;
142 }
143
144 fprintf (stream, "%s", notstrs[i].name);
145
146 ioffset = notstrs[i].detail.ibits;
147 aoffset = notstrs[i].detail.ibits;
148 d = notstrs[i].detail.args;
149
150 if (*d)
151 {
152 fputc ('\t', stream);
153
154 maxarg = 0;
155 while (*d)
156 {
157 argnum = *d - '1';
158 d++;
159 if (argnum > maxarg && argnum < MAX_ARGS)
160 maxarg = argnum;
161 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
162 memaddr, arg_bufs[argnum]);
163 d++;
164 }
165 for (argnum = 0; argnum <= maxarg; argnum++)
166 {
167 CORE_ADDR addr;
168 char *ch, *index ();
169 for (ch = arg_bufs[argnum]; *ch;)
170 {
171 if (*ch == NEXT_IS_ADDR)
172 {
173 ++ch;
174 addr = atoi (ch);
175 print_address (addr, stream);
176 while (*ch && *ch != NEXT_IS_ADDR)
177 ++ch;
178 if (*ch)
179 ++ch;
180 }
181 else
182 putc (*ch++, stream);
183 }
184 if (argnum < maxarg)
185 fprintf (stream, ", ");
186 }
187 }
188 return aoffset / 8;
189}
190
191print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
192 char d;
193 int ioffset, *aoffsetp;
194 char *buffer;
195 CORE_ADDR addr;
196 char *result;
197{
198 int addr_mode;
199 float Fvalue;
200 double Lvalue;
201 int Ivalue;
202 int disp1, disp2;
203 int index;
204
205 switch (d)
206 {
207 case 'F':
208 case 'L':
209 case 'B':
210 case 'W':
211 case 'D':
212 case 'A':
213 addr_mode = bit_extract (buffer, ioffset-5, 5);
214 ioffset -= 5;
215 switch (addr_mode)
216 {
217 case 0x0: case 0x1: case 0x2: case 0x3:
218 case 0x4: case 0x5: case 0x6: case 0x7:
219 sprintf (result, "r%d", addr_mode);
220 break;
221 case 0x8: case 0x9: case 0xa: case 0xb:
222 case 0xc: case 0xd: case 0xe: case 0xf:
223 disp1 = get_displacement (buffer, aoffsetp);
224 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
225 break;
226 case 0x10:
227 case 0x11:
228 case 0x12:
229 disp1 = get_displacement (buffer, aoffsetp);
230 disp2 = get_displacement (buffer, aoffsetp);
231 sprintf (result, "%d(%d(%s))", disp2, disp1,
232 addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
233 break;
234 case 0x13:
235 sprintf (result, "reserved");
236 break;
237 case 0x14:
238 switch (d)
239 {
240 case 'B':
241 Ivalue = bit_extract (buffer, *aoffsetp, 8);
242 Ivalue = sign_extend (Ivalue, 8);
243 *aoffsetp += 8;
244 sprintf (result, "$%d", Ivalue);
245 break;
246 case 'W':
247 Ivalue = bit_extract (buffer, *aoffsetp, 16);
248 flip_bytes (&Ivalue, 2);
249 *aoffsetp += 16;
250 Ivalue = sign_extend (Ivalue, 16);
251 sprintf (result, "$%d", Ivalue);
252 break;
253 case 'D':
254 Ivalue = bit_extract (buffer, *aoffsetp, 32);
255 flip_bytes (&Ivalue, 4);
256 *aoffsetp += 32;
257 sprintf (result, "$%d", Ivalue);
258 break;
259 case 'A':
260 Ivalue = bit_extract (buffer, *aoffsetp, 32);
261 flip_bytes (&Ivalue, 4);
262 *aoffsetp += 32;
263 sprintf (result, "$|%d|", Ivalue);
264 break;
265 case 'F':
266 Fvalue = (float) bit_extract (buffer, *aoffsetp, 32);
267 flip_bytes (&Fvalue, 4);
268 *aoffsetp += 32;
269 sprintf (result, "$%g", Fvalue);
270 break;
271 case 'L':
272 Lvalue = dbit_extract (buffer, *aoffsetp, 64);
273 flip_bytes (&Lvalue, 8);
274 *aoffsetp += 64;
275 sprintf (result, "$%g", Lvalue);
276 break;
277 }
278 break;
279 case 0x15:
280 disp1 = get_displacement (buffer, aoffsetp);
281 sprintf (result, "@|%d|", disp1);
282 break;
283 case 0x16:
284 disp1 = get_displacement (buffer, aoffsetp);
285 disp2 = get_displacement (buffer, aoffsetp);
286 sprintf (result, "EXT(%d) + %d", disp1, disp2);
287 break;
288 case 0x17:
289 sprintf (result, "tos");
290 break;
291 case 0x18:
292 disp1 = get_displacement (buffer, aoffsetp);
293 sprintf (result, "%d(fp)", disp1);
294 break;
295 case 0x19:
296 disp1 = get_displacement (buffer, aoffsetp);
297 sprintf (result, "%d(sp)", disp1);
298 break;
299 case 0x1a:
300 disp1 = get_displacement (buffer, aoffsetp);
301 sprintf (result, "%d(sb)", disp1);
302 break;
303 case 0x1b:
304 disp1 = get_displacement (buffer, aoffsetp);
305 sprintf (result, "|%d|", addr + disp1);
306 break;
307 case 0x1c:
308 case 0x1d:
309 case 0x1e:
310 case 0x1f:
311 index = bit_extract (buffer, *aoffsetp, 8);
312 *aoffsetp += 8;
313 print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
314 result);
315 {
316 static char *ind[] = {"b", "w", "d", "q"};
317 char *off;
318
319 off = result + strlen (result);
320 sprintf (off, "[r%d:%s]", index & 7,
321 ind[addr_mode & 3]);
322 }
323 break;
324 }
325 break;
326 case 'q':
327 Ivalue = bit_extract (buffer, ioffset-4, 4);
328 Ivalue = sign_extend (Ivalue, 4);
329 sprintf (result, "%d", Ivalue);
330 ioffset -= 4;
331 break;
332 case 'r':
333 Ivalue = bit_extract (buffer, ioffset-3, 3);
334 sprintf (result, "r%d", Ivalue&7);
335 ioffset -= 3;
336 break;
337 case 'd':
338 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
339 break;
340 case 'p':
341 sprintf (result, "%c%d%c", NEXT_IS_ADDR,
342 addr + get_displacement (buffer, aoffsetp),
343 NEXT_IS_ADDR);
344 break;
345 case 'i':
346 Ivalue = bit_extract (buffer, *aoffsetp, 8);
347 *aoffsetp += 8;
348 sprintf (result, "0x%x", Ivalue);
349 break;
350 }
351 return ioffset;
352}
353
354get_displacement (buffer, aoffsetp)
355 char *buffer;
356 int *aoffsetp;
357{
358 int Ivalue;
359
360 Ivalue = bit_extract (buffer, *aoffsetp, 8);
361 switch (Ivalue & 0xc0)
362 {
363 case 0x00:
364 case 0x40:
365 Ivalue = sign_extend (Ivalue, 7);
366 *aoffsetp += 8;
367 break;
368 case 0x80:
369 Ivalue = bit_extract (buffer, *aoffsetp, 16);
370 flip_bytes (&Ivalue, 2);
371 Ivalue = sign_extend (Ivalue, 14);
372 *aoffsetp += 16;
373 break;
374 case 0xc0:
375 Ivalue = bit_extract (buffer, *aoffsetp, 32);
376 flip_bytes (&Ivalue, 4);
377 Ivalue = sign_extend (Ivalue, 30);
378 *aoffsetp += 32;
379 break;
380 }
381 return Ivalue;
382}
383\f
384/* Return the number of locals in the current frame given a pc
385 pointing to the enter instruction. This is used in the macro
386 FRAME_FIND_SAVED_REGS. */
387
388ns32k_localcount (enter_pc)
389 CORE_ADDR enter_pc;
390{
391 unsigned char localtype;
392 int localcount;
393
394 localtype = read_memory_integer (enter_pc+2, 1);
395 if ((localtype & 0x80) == 0)
396 localcount = localtype;
397 else if ((localtype & 0xc0) == 0x80)
398 localcount = (((localtype & 0x3f) << 8)
399 | (read_memory_integer (enter_pc+3, 1) & 0xff));
400 else
401 localcount = (((localtype & 0x3f) << 24)
402 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
403 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
404 | (read_memory_integer (enter_pc+5, 1) & 0xff));
405 return localcount;
406}
407
408/*
409 * Get the address of the enter opcode for the function
410 * containing PC, if there is an enter for the function,
411 * and if the pc is between the enter and exit.
412 * Returns positive address if pc is between enter/exit,
413 * 1 if pc before enter or after exit, 0 otherwise.
414 */
415
416CORE_ADDR
417n32k_get_enter_addr (pc)
418 CORE_ADDR pc;
419{
420 CORE_ADDR enter_addr;
421 unsigned char op;
422
423 if (ABOUT_TO_RETURN (pc))
424 return 1; /* after exit */
425
426 enter_addr = get_pc_function_start (pc);
427
428 if (pc == enter_addr)
429 return 1; /* before enter */
430
431 op = read_memory_integer (enter_addr, 1);
432
433 if (op != 0x82)
434 return 0; /* function has no enter/exit */
435
436 return enter_addr; /* pc is between enter and exit */
437}