]>
Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* Pyramid target-dependent code for GDB. |
2 | Copyright (C) 1988, 1989, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | ||
22 | /*** Prettier register printing. ***/ | |
23 | ||
24 | /* Print registers in the same format as pyramid's dbx, adb, sdb. */ | |
25 | pyr_print_registers(reg_buf, regnum) | |
26 | long *reg_buf[]; | |
27 | { | |
28 | register int regno; | |
29 | int usp, ksp; | |
30 | struct user u; | |
31 | ||
32 | for (regno = 0; regno < 16; regno++) { | |
33 | printf_unfiltered/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n", | |
34 | REGISTER_NAME (regno), reg_buf[regno], | |
35 | REGISTER_NAME (regno+16), reg_buf[regno+16], | |
36 | REGISTER_NAME (regno+32), reg_buf[regno+32], | |
37 | REGISTER_NAME (regno+48), reg_buf[regno+48]); | |
38 | } | |
39 | usp = ptrace (3, inferior_pid, | |
40 | (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_usp) - | |
41 | ((char *)&u), 0); | |
42 | ksp = ptrace (3, inferior_pid, | |
43 | (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_ksp) - | |
44 | ((char *)&u), 0); | |
45 | printf_unfiltered/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n", | |
46 | REGISTER_NAME (CSP_REGNUM),reg_buf[CSP_REGNUM], | |
47 | REGISTER_NAME (KSP_REGNUM), reg_buf[KSP_REGNUM], ksp, | |
48 | "usp", usp); | |
49 | } | |
50 | ||
51 | /* Print the register regnum, or all registers if regnum is -1. | |
52 | fpregs is currently ignored. */ | |
53 | ||
54 | pyr_do_registers_info (regnum, fpregs) | |
55 | int regnum; | |
56 | int fpregs; | |
57 | { | |
58 | /* On a pyr, we know a virtual register can always fit in an long. | |
59 | Here (and elsewhere) we take advantage of that. Yuk. */ | |
60 | long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS]; | |
61 | register int i; | |
62 | ||
63 | for (i = 0 ; i < 64 ; i++) { | |
64 | read_relative_register_raw_bytes(i, raw_regs+i); | |
65 | } | |
66 | if (regnum == -1) | |
67 | pyr_print_registers (raw_regs, regnum); | |
68 | else | |
69 | for (i = 0; i < NUM_REGS; i++) | |
70 | if (i == regnum) { | |
71 | long val = raw_regs[i]; | |
72 | ||
73 | fputs_filtered (REGISTER_NAME (i), gdb_stdout); | |
74 | printf_filtered(":"); | |
75 | print_spaces_filtered (6 - strlen (REGISTER_NAME (i)), gdb_stdout); | |
76 | if (val == 0) | |
77 | printf_filtered ("0"); | |
78 | else | |
79 | printf_filtered ("%s %d", local_hex_string_custom(val,"08"), val); | |
80 | printf_filtered("\n"); | |
81 | } | |
82 | } | |
83 | \f | |
84 | /*** Debugging editions of various macros from m-pyr.h ****/ | |
85 | ||
86 | CORE_ADDR frame_locals_address (frame) | |
87 | struct frame_info *frame; | |
88 | { | |
89 | register int addr = find_saved_register (frame,CFP_REGNUM); | |
90 | register int result = read_memory_integer (addr, 4); | |
91 | #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING | |
92 | fprintf_unfiltered (gdb_stderr, | |
93 | "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n", | |
94 | frame->frame, | |
95 | REGISTER_NAME (CFP_REGNUM), | |
96 | result, addr, | |
97 | frame->frame_cfp, (CFP_REGNUM), | |
98 | ||
99 | ||
100 | read_register(13), read_register(29), read_register(61), | |
101 | find_saved_register(frame, 61)); | |
102 | #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */ | |
103 | ||
104 | /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer; | |
105 | or at least CFP_REGNUM relative to FRAME (ie, result). | |
106 | There seems to be a bug in the way the innermost frame is set up. */ | |
107 | ||
108 | return ((frame->next) ? result: frame->frame_cfp); | |
109 | } | |
110 | ||
111 | CORE_ADDR frame_args_addr (frame) | |
112 | struct frame_info *frame; | |
113 | { | |
114 | register int addr = find_saved_register (frame,CFP_REGNUM); | |
115 | register int result = read_memory_integer (addr, 4); | |
116 | ||
117 | #ifdef PYRAMID_CONTROL_FRAME_DEBUGGING | |
118 | fprintf_unfiltered (gdb_stderr, | |
119 | "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n", | |
120 | frame->frame, | |
121 | REGISTER_NAME (CFP_REGNUM), | |
122 | result, addr, | |
123 | frame->frame_cfp, read_register(CFP_REGNUM), | |
124 | ||
125 | read_register(13), read_register(29), read_register(61), | |
126 | find_saved_register(frame, 61)); | |
127 | #endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */ | |
128 | ||
129 | /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer; | |
130 | or at least CFP_REGNUM relative to FRAME (ie, result). | |
131 | There seems to be a bug in the way the innermost frame is set up. */ | |
132 | return ((frame->next) ? result: frame->frame_cfp); | |
133 | } | |
134 | ||
135 | #include "symtab.h" | |
136 | #include "opcode/pyr.h" | |
137 | #include "gdbcore.h" | |
138 | ||
139 | \f | |
140 | /* A couple of functions used for debugging frame-handling on | |
141 | Pyramids. (The Pyramid-dependent handling of register values for | |
142 | windowed registers is known to be buggy.) | |
143 | ||
144 | When debugging, these functions can supplant the normal definitions of some | |
145 | of the macros in tm-pyramid.h The quantity of information produced | |
146 | when these functions are used makes the gdb unusable as a | |
147 | debugger for user programs. */ | |
148 | ||
149 | extern unsigned pyr_saved_pc(), pyr_frame_chain(); | |
150 | ||
151 | CORE_ADDR pyr_frame_chain(frame) | |
152 | CORE_ADDR frame; | |
153 | { | |
154 | int foo=frame - CONTROL_STACK_FRAME_SIZE; | |
155 | /* printf_unfiltered ("...following chain from %x: got %x\n", frame, foo);*/ | |
156 | return foo; | |
157 | } | |
158 | ||
159 | CORE_ADDR pyr_saved_pc(frame) | |
160 | CORE_ADDR frame; | |
161 | { | |
162 | int foo=0; | |
163 | foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4); | |
164 | printf_unfiltered ("..reading pc from frame 0x%0x+%d regs: got %0x\n", | |
165 | frame, 60/4, foo); | |
166 | return foo; | |
167 | } | |
168 | ||
169 | /* Pyramid instructions are never longer than this many bytes. */ | |
170 | #define MAXLEN 24 | |
171 | ||
172 | /* Number of elements in the opcode table. */ | |
173 | /*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0])); | |
174 | #define NOPCODES (nopcodes) | |
175 | ||
176 | /* Let's be byte-independent so we can use this as a cross-assembler. */ | |
177 | ||
178 | #define NEXTLONG(p) \ | |
179 | (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]) | |
180 | \f | |
181 | /* Print one instruction at address MEMADDR in debugged memory, | |
182 | on STREAM. Returns length of the instruction, in bytes. */ | |
183 | ||
184 | int | |
185 | pyr_print_insn (memaddr, stream) | |
186 | CORE_ADDR memaddr; | |
187 | GDB_FILE *stream; | |
188 | { | |
189 | unsigned char buffer[MAXLEN]; | |
190 | register int i, nargs, insn_size =4; | |
191 | register unsigned char *p; | |
192 | register char *d; | |
193 | register int insn_opcode, operand_mode; | |
194 | register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ; | |
195 | long insn; /* first word of the insn, not broken down. */ | |
196 | pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */ | |
197 | long extra_1, extra_2; | |
198 | ||
199 | read_memory (memaddr, buffer, MAXLEN); | |
200 | insn_decode = *((pyr_insn_format *) buffer); | |
201 | insn = * ((int *) buffer); | |
202 | insn_opcode = insn_decode.operator; | |
203 | operand_mode = insn_decode.mode; | |
204 | index_multiplier = insn_decode.index_scale; | |
205 | index_reg_regno = insn_decode.index_reg; | |
206 | op_1_regno = insn_decode.operand_1; | |
207 | op_2_regno = insn_decode.operand_2; | |
208 | ||
209 | ||
210 | if (*((int *)buffer) == 0x0) { | |
211 | /* "halt" looks just like an invalid "jump" to the insn decoder, | |
212 | so is dealt with as a special case */ | |
213 | fprintf_unfiltered (stream, "halt"); | |
214 | return (4); | |
215 | } | |
216 | ||
217 | for (i = 0; i < NOPCODES; i++) | |
218 | if (pyr_opcodes[i].datum.code == insn_opcode) | |
219 | break; | |
220 | ||
221 | if (i == NOPCODES) | |
222 | /* FIXME: Handle unrecognised instructions better. */ | |
223 | fprintf_unfiltered (stream, "???\t#%08x\t(op=%x mode =%x)", | |
224 | insn, insn_decode.operator, insn_decode.mode); | |
225 | else | |
226 | { | |
227 | /* Print the mnemonic for the instruction. Pyramid insn operands | |
228 | are so regular that we can deal with almost all of them | |
229 | separately. | |
230 | Unconditional branches are an exception: they are encoded as | |
231 | conditional branches (branch if false condition, I think) | |
232 | with no condition specified. The average user will not be | |
233 | aware of this. To maintain their illusion that an | |
234 | unconditional branch insn exists, we will have to FIXME to | |
235 | treat the insn mnemnonic of all branch instructions here as a | |
236 | special case: check the operands of branch insn and print an | |
237 | appropriate mnemonic. */ | |
238 | ||
239 | fprintf_unfiltered (stream, "%s\t", pyr_opcodes[i].name); | |
240 | ||
241 | /* Print the operands of the insn (as specified in | |
242 | insn.operand_mode). | |
243 | Branch operands of branches are a special case: they are a word | |
244 | offset, not a byte offset. */ | |
245 | ||
246 | if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) { | |
247 | register int bit_codes=(insn >> 16)&0xf; | |
248 | register int i; | |
249 | register int displacement = (insn & 0x0000ffff) << 2; | |
250 | ||
251 | static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */ | |
252 | ||
253 | /* Is bfc and no bits specified an unconditional branch?*/ | |
254 | for (i=0;i<4;i++) { | |
255 | if ((bit_codes) & 0x1) | |
256 | fputc_unfiltered (cc_bit_names[i], stream); | |
257 | bit_codes >>= 1; | |
258 | } | |
259 | ||
260 | fprintf_unfiltered (stream, ",%0x", | |
261 | displacement + memaddr); | |
262 | return (insn_size); | |
263 | } | |
264 | ||
265 | switch (operand_mode) { | |
266 | case 0: | |
267 | fprintf_unfiltered (stream, "%s,%s", | |
268 | REGISTER_NAME (op_1_regno), | |
269 | REGISTER_NAME (op_2_regno)); | |
270 | break; | |
271 | ||
272 | case 1: | |
273 | fprintf_unfiltered (stream, " 0x%0x,%s", | |
274 | op_1_regno, | |
275 | REGISTER_NAME (op_2_regno)); | |
276 | break; | |
277 | ||
278 | case 2: | |
279 | read_memory (memaddr+4, buffer, MAXLEN); | |
280 | insn_size += 4; | |
281 | extra_1 = * ((int *) buffer); | |
282 | fprintf_unfiltered (stream, " $0x%0x,%s", | |
283 | extra_1, | |
284 | REGISTER_NAME (op_2_regno)); | |
285 | break; | |
286 | case 3: | |
287 | fprintf_unfiltered (stream, " (%s),%s", | |
288 | REGISTER_NAME (op_1_regno), | |
289 | REGISTER_NAME (op_2_regno)); | |
290 | break; | |
291 | ||
292 | case 4: | |
293 | read_memory (memaddr+4, buffer, MAXLEN); | |
294 | insn_size += 4; | |
295 | extra_1 = * ((int *) buffer); | |
296 | fprintf_unfiltered (stream, " 0x%0x(%s),%s", | |
297 | extra_1, | |
298 | REGISTER_NAME (op_1_regno), | |
299 | REGISTER_NAME (op_2_regno)); | |
300 | break; | |
301 | ||
302 | /* S1 destination mode */ | |
303 | case 5: | |
304 | fprintf_unfiltered (stream, | |
305 | ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"), | |
306 | REGISTER_NAME (op_1_regno), | |
307 | REGISTER_NAME (op_2_regno), | |
308 | REGISTER_NAME (index_reg_regno), | |
309 | index_multiplier); | |
310 | break; | |
311 | ||
312 | case 6: | |
313 | fprintf_unfiltered (stream, | |
314 | ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]" | |
315 | : " $%#0x,(%s)"), | |
316 | op_1_regno, | |
317 | REGISTER_NAME (op_2_regno), | |
318 | REGISTER_NAME (index_reg_regno), | |
319 | index_multiplier); | |
320 | break; | |
321 | ||
322 | case 7: | |
323 | read_memory (memaddr+4, buffer, MAXLEN); | |
324 | insn_size += 4; | |
325 | extra_1 = * ((int *) buffer); | |
326 | fprintf_unfiltered (stream, | |
327 | ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]" | |
328 | : " $%#0x,(%s)"), | |
329 | extra_1, | |
330 | REGISTER_NAME (op_2_regno), | |
331 | REGISTER_NAME (index_reg_regno), | |
332 | index_multiplier); | |
333 | break; | |
334 | ||
335 | case 8: | |
336 | fprintf_unfiltered (stream, | |
337 | ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"), | |
338 | REGISTER_NAME (op_1_regno), | |
339 | REGISTER_NAME (op_2_regno), | |
340 | REGISTER_NAME (index_reg_regno), | |
341 | index_multiplier); | |
342 | break; | |
343 | ||
344 | case 9: | |
345 | read_memory (memaddr+4, buffer, MAXLEN); | |
346 | insn_size += 4; | |
347 | extra_1 = * ((int *) buffer); | |
348 | fprintf_unfiltered (stream, | |
349 | ((index_reg_regno) | |
350 | ? "%#0x(%s),(%s)[%s*%1d]" | |
351 | : "%#0x(%s),(%s)"), | |
352 | extra_1, | |
353 | REGISTER_NAME (op_1_regno), | |
354 | REGISTER_NAME (op_2_regno), | |
355 | REGISTER_NAME (index_reg_regno), | |
356 | index_multiplier); | |
357 | break; | |
358 | ||
359 | /* S2 destination mode */ | |
360 | case 10: | |
361 | read_memory (memaddr+4, buffer, MAXLEN); | |
362 | insn_size += 4; | |
363 | extra_1 = * ((int *) buffer); | |
364 | fprintf_unfiltered (stream, | |
365 | ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"), | |
366 | REGISTER_NAME (op_1_regno), | |
367 | extra_1, | |
368 | REGISTER_NAME (op_2_regno), | |
369 | REGISTER_NAME (index_reg_regno), | |
370 | index_multiplier); | |
371 | break; | |
372 | case 11: | |
373 | read_memory (memaddr+4, buffer, MAXLEN); | |
374 | insn_size += 4; | |
375 | extra_1 = * ((int *) buffer); | |
376 | fprintf_unfiltered (stream, | |
377 | ((index_reg_regno) ? | |
378 | " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"), | |
379 | op_1_regno, | |
380 | extra_1, | |
381 | REGISTER_NAME (op_2_regno), | |
382 | REGISTER_NAME (index_reg_regno), | |
383 | index_multiplier); | |
384 | break; | |
385 | case 12: | |
386 | read_memory (memaddr+4, buffer, MAXLEN); | |
387 | insn_size += 4; | |
388 | extra_1 = * ((int *) buffer); | |
389 | read_memory (memaddr+8, buffer, MAXLEN); | |
390 | insn_size += 4; | |
391 | extra_2 = * ((int *) buffer); | |
392 | fprintf_unfiltered (stream, | |
393 | ((index_reg_regno) ? | |
394 | " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"), | |
395 | extra_1, | |
396 | extra_2, | |
397 | REGISTER_NAME (op_2_regno), | |
398 | REGISTER_NAME (index_reg_regno), | |
399 | index_multiplier); | |
400 | break; | |
401 | ||
402 | case 13: | |
403 | read_memory (memaddr+4, buffer, MAXLEN); | |
404 | insn_size += 4; | |
405 | extra_1 = * ((int *) buffer); | |
406 | fprintf_unfiltered (stream, | |
407 | ((index_reg_regno) | |
408 | ? " (%s),%#0x(%s)[%s*%1d]" | |
409 | : " (%s),%#0x(%s)"), | |
410 | REGISTER_NAME (op_1_regno), | |
411 | extra_1, | |
412 | REGISTER_NAME (op_2_regno), | |
413 | REGISTER_NAME (index_reg_regno), | |
414 | index_multiplier); | |
415 | break; | |
416 | case 14: | |
417 | read_memory (memaddr+4, buffer, MAXLEN); | |
418 | insn_size += 4; | |
419 | extra_1 = * ((int *) buffer); | |
420 | read_memory (memaddr+8, buffer, MAXLEN); | |
421 | insn_size += 4; | |
422 | extra_2 = * ((int *) buffer); | |
423 | fprintf_unfiltered (stream, | |
424 | ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]" | |
425 | : "%#0x(%s),%#0x(%s) "), | |
426 | extra_1, | |
427 | REGISTER_NAME (op_1_regno), | |
428 | extra_2, | |
429 | REGISTER_NAME (op_2_regno), | |
430 | REGISTER_NAME (index_reg_regno), | |
431 | index_multiplier); | |
432 | break; | |
433 | ||
434 | default: | |
435 | fprintf_unfiltered (stream, | |
436 | ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"), | |
437 | REGISTER_NAME (op_1_regno), | |
438 | REGISTER_NAME (op_2_regno), | |
439 | REGISTER_NAME (index_reg_regno), | |
440 | index_multiplier); | |
441 | fprintf_unfiltered (stream, | |
442 | "\t\t# unknown mode in %08x", | |
443 | insn); | |
444 | break; | |
445 | } /* switch */ | |
446 | } | |
447 | ||
448 | { | |
449 | return insn_size; | |
450 | } | |
451 | abort (); | |
452 | } |