Tue Mar 3 15:11:52 1992 Michael Tiemann (tiemann@cygnus.com)
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
CommitLineData
7d9884b9 1/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
d747e0af 2 Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
bd5635a1
RP
3 Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
4 and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
5
6This file is part of GDB.
7
361bf6ee 8This program is free software; you can redistribute it and/or modify
bd5635a1 9it under the terms of the GNU General Public License as published by
361bf6ee
JG
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
bd5635a1 12
361bf6ee 13This program is distributed in the hope that it will be useful,
bd5635a1
RP
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
361bf6ee
JG
19along with this program; if not, write to the Free Software
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
bd5635a1 21
bd5635a1 22#include "defs.h"
bd5635a1
RP
23#include "frame.h"
24#include "inferior.h"
25#include "symtab.h"
26#include "value.h"
27#include "gdbcmd.h"
ef08856f 28#include "language.h"
bd5635a1
RP
29
30#ifdef USG
31#include <sys/types.h>
32#endif
33
34#include <sys/param.h>
35#include <sys/dir.h>
36#include <signal.h>
37#include <sys/ioctl.h>
38
39#include "gdbcore.h"
40
41#ifndef MIPSMAGIC
42#ifdef MIPSEL
43#define MIPSMAGIC MIPSELMAGIC
44#else
45#define MIPSMAGIC MIPSEBMAGIC
46#endif
47#endif
48
49#define VM_MIN_ADDRESS (unsigned)0x400000
50
51#include <sys/user.h> /* After a.out.h */
52#include <sys/file.h>
53#include <sys/stat.h>
54
55\f
56#define PROC_LOW_ADDR(proc) ((proc)->adr) /* least address */
57#define PROC_HIGH_ADDR(proc) ((proc)->pad2) /* upper address bound */
58#define PROC_FRAME_OFFSET(proc) ((proc)->framesize)
59#define PROC_FRAME_REG(proc) ((proc)->framereg)
60#define PROC_REG_MASK(proc) ((proc)->regmask)
61#define PROC_FREG_MASK(proc) ((proc)->fregmask)
62#define PROC_REG_OFFSET(proc) ((proc)->regoffset)
63#define PROC_FREG_OFFSET(proc) ((proc)->fregoffset)
64#define PROC_PC_REG(proc) ((proc)->pcreg)
65#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->isym)
66#define _PROC_MAGIC_ 0x0F0F0F0F
67#define PROC_DESC_IS_DUMMY(proc) ((proc)->isym == _PROC_MAGIC_)
68#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->isym = _PROC_MAGIC_)
69
70struct linked_proc_info
71{
72 struct mips_extra_func_info info;
73 struct linked_proc_info *next;
74} * linked_proc_desc_table = NULL;
75
76\f
77#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno)
78
79int
80read_next_frame_reg(fi, regno)
81 FRAME fi;
82 int regno;
83{
84#define SIGFRAME_BASE sizeof(struct sigcontext)
85#define SIGFRAME_PC_OFF (-SIGFRAME_BASE+ 2*sizeof(int))
86#define SIGFRAME_SP_OFF (-SIGFRAME_BASE+32*sizeof(int))
87#define SIGFRAME_RA_OFF (-SIGFRAME_BASE+34*sizeof(int))
88 for (; fi; fi = fi->next)
89 if (in_sigtramp(fi->pc, 0)) {
90 /* No idea if this code works. --PB. */
91 int offset;
92 if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF;
93 else if (regno == RA_REGNUM) offset = SIGFRAME_RA_OFF;
94 else if (regno == SP_REGNUM) offset = SIGFRAME_SP_OFF;
95 else return 0;
96 return read_memory_integer(fi->frame + offset, 4);
97 }
98 else if (regno == SP_REGNUM) return fi->frame;
99 else if (fi->saved_regs->regs[regno])
100 return read_memory_integer(fi->saved_regs->regs[regno], 4);
101 return read_register(regno);
102}
103
104int
105mips_frame_saved_pc(frame)
106 FRAME frame;
107{
108 mips_extra_func_info_t proc_desc = (mips_extra_func_info_t)frame->proc_desc;
109 int pcreg = proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM;
110 if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
111 return read_memory_integer(frame->frame - 4, 4);
112#if 0
113 /* If in the procedure prologue, RA_REGNUM might not have been saved yet.
114 * Assume non-leaf functions start with:
115 * addiu $sp,$sp,-frame_size
116 * sw $ra,ra_offset($sp)
117 * This if the pc is pointing at either of these instructions,
118 * then $ra hasn't been trashed.
119 * If the pc has advanced beyond these two instructions,
120 * then $ra has been saved.
121 * critical, and much more complex. Handling $ra is enough to get
122 * a stack trace, but some register values with be wrong.
123 */
124 if (frame->proc_desc && frame->pc < PROC_LOW_ADDR(proc_desc) + 8)
125 return read_register(pcreg);
126#endif
127 return read_next_frame_reg(frame, pcreg);
128}
129
130static struct mips_extra_func_info temp_proc_desc;
131static struct frame_saved_regs temp_saved_regs;
132
133CORE_ADDR heuristic_proc_start(pc)
134 CORE_ADDR pc;
135{
136
137 CORE_ADDR start_pc = pc;
138 CORE_ADDR fence = start_pc - 10000;
139 if (fence < VM_MIN_ADDRESS) fence = VM_MIN_ADDRESS;
140 /* search back for previous return */
141 for (start_pc -= 4; ; start_pc -= 4)
142 if (start_pc < fence) return 0;
143 else if (ABOUT_TO_RETURN(start_pc))
144 break;
145
146 start_pc += 8; /* skip return, and its delay slot */
147#if 0
148 /* skip nops (usually 1) 0 - is this */
149 while (start_pc < pc && read_memory_integer (start_pc, 4) == 0)
150 start_pc += 4;
151#endif
152 return start_pc;
153}
154
155mips_extra_func_info_t
156heuristic_proc_desc(start_pc, limit_pc, next_frame)
157 CORE_ADDR start_pc, limit_pc;
158 FRAME next_frame;
159{
160 CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
161 CORE_ADDR cur_pc;
162 int frame_size;
163 int has_frame_reg = 0;
164 int reg30; /* Value of $r30. Used by gcc for frame-pointer */
165 unsigned long reg_mask = 0;
166
167 if (start_pc == 0) return NULL;
168 bzero(&temp_proc_desc, sizeof(temp_proc_desc));
169 bzero(&temp_saved_regs, sizeof(struct frame_saved_regs));
170 if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
171 restart:
172 frame_size = 0;
173 for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
174 unsigned long word;
175 int status;
176
177 status = read_memory_nobpt (cur_pc, &word, 4);
178 if (status) memory_error (status, cur_pc);
179 if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
180 frame_size += (-word) & 0xFFFF;
181 else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
182 frame_size += (-word) & 0xFFFF;
183 else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
184 int reg = (word & 0x001F0000) >> 16;
185 reg_mask |= 1 << reg;
186 temp_saved_regs.regs[reg] = sp + (short)word;
187 }
188 else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size */
189 if ((unsigned short)word != frame_size)
190 reg30 = sp + (unsigned short)word;
191 else if (!has_frame_reg) {
192 int alloca_adjust;
193 has_frame_reg = 1;
194 reg30 = read_next_frame_reg(next_frame, 30);
195 alloca_adjust = reg30 - (sp + (unsigned short)word);
196 if (alloca_adjust > 0) {
197 /* FP > SP + frame_size. This may be because
198 /* of an alloca or somethings similar.
199 * Fix sp to "pre-alloca" value, and try again.
200 */
201 sp += alloca_adjust;
202 goto restart;
203 }
204 }
205 }
206 else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30) */
207 int reg = (word & 0x001F0000) >> 16;
208 reg_mask |= 1 << reg;
209 temp_saved_regs.regs[reg] = reg30 + (short)word;
210 }
211 }
212 if (has_frame_reg) {
213 PROC_FRAME_REG(&temp_proc_desc) = 30;
214 PROC_FRAME_OFFSET(&temp_proc_desc) = 0;
215 }
216 else {
217 PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
218 PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
219 }
220 PROC_REG_MASK(&temp_proc_desc) = reg_mask;
221 PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;
222 return &temp_proc_desc;
223}
224
225mips_extra_func_info_t
226find_proc_desc(pc, next_frame)
227 CORE_ADDR pc;
228 FRAME next_frame;
229{
230 mips_extra_func_info_t proc_desc;
231 extern struct block *block_for_pc();
232 struct block *b = block_for_pc(pc);
233
234 struct symbol *sym =
235 b ? lookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, 0, NULL) : NULL;
236 if (sym != NULL)
237 {
238 /* IF this is the topmost frame AND
239 * (this proc does not have debugging information OR
240 * the PC is in the procedure prologue)
241 * THEN create a "hueristic" proc_desc (by analyzing
242 * the actual code) to replace the "official" proc_desc.
243 */
244 proc_desc = (struct mips_extra_func_info *)sym->value.value;
245 if (next_frame == NULL) {
246 struct symtab_and_line val;
247 struct symbol *proc_symbol =
248 PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
249 if (proc_symbol) {
250 val = find_pc_line (BLOCK_START
251 (SYMBOL_BLOCK_VALUE(proc_symbol)),
252 0);
253 val.pc = val.end ? val.end : pc;
254 }
255 if (!proc_symbol || pc < val.pc) {
256 mips_extra_func_info_t found_heuristic =
257 heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),
258 pc, next_frame);
259 if (found_heuristic) proc_desc = found_heuristic;
260 }
261 }
262 }
263 else
264 {
265 register struct linked_proc_info *link;
266 for (link = linked_proc_desc_table; link; link = link->next)
267 if (PROC_LOW_ADDR(&link->info) <= pc
268 && PROC_HIGH_ADDR(&link->info) > pc)
269 return &link->info;
270 proc_desc =
271 heuristic_proc_desc(heuristic_proc_start(pc), pc, next_frame);
272 }
273 return proc_desc;
274}
275
276mips_extra_func_info_t cached_proc_desc;
277
278FRAME_ADDR mips_frame_chain(frame)
279 FRAME frame;
280{
281 extern CORE_ADDR startup_file_start; /* From blockframe.c */
282 mips_extra_func_info_t proc_desc;
283 CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
284 if (startup_file_start)
285 { /* has at least the __start symbol */
286 if (saved_pc == 0 || !outside_startup_file (saved_pc)) return 0;
287 }
288 else
289 { /* This hack depends on the internals of __start. */
290 /* We also assume the breakpoints are *not* inserted */
361bf6ee
JG
291 if (saved_pc == 0
292 || read_memory_integer (saved_pc + 8, 4) & 0xFC00003F == 0xD)
bd5635a1
RP
293 return 0; /* break */
294 }
295 proc_desc = find_proc_desc(saved_pc, frame);
296 if (!proc_desc) return 0;
297 cached_proc_desc = proc_desc;
298 return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
299 + PROC_FRAME_OFFSET(proc_desc);
300}
301
302void
303init_extra_frame_info(fci)
304 struct frame_info *fci;
305{
306 extern struct obstack frame_cache_obstack;
307 /* Use proc_desc calculated in frame_chain */
308 mips_extra_func_info_t proc_desc = fci->next ? cached_proc_desc :
309 find_proc_desc(fci->pc, fci->next);
310 fci->saved_regs = (struct frame_saved_regs*)
311 obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
312 bzero(fci->saved_regs, sizeof(struct frame_saved_regs));
313 fci->proc_desc =
314 proc_desc == &temp_proc_desc ? (char*)NULL : (char*)proc_desc;
315 if (proc_desc)
316 {
317 int ireg;
318 CORE_ADDR reg_position;
319 unsigned long mask;
320 /* r0 bit means kernel trap */
321 int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
322
323 /* Fixup frame-pointer - only needed for top frame */
324 /* This may not be quite right, if procedure has a real frame register */
325 if (fci->pc == PROC_LOW_ADDR(proc_desc))
326 fci->frame = read_register (SP_REGNUM);
327 else
328 fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
329 + PROC_FRAME_OFFSET(proc_desc);
330
331 if (proc_desc == &temp_proc_desc)
332 *fci->saved_regs = temp_saved_regs;
333 else
334 {
335 /* find which general-purpose registers were saved */
336 reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
337 mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
338 for (ireg= 31; mask; --ireg, mask <<= 1)
339 if (mask & 0x80000000)
340 {
341 fci->saved_regs->regs[ireg] = reg_position;
342 reg_position -= 4;
343 }
344 /* find which floating-point registers were saved */
345 reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
346 /* The freg_offset points to where the first *double* register is saved.
347 * So skip to the high-order word. */
348 reg_position += 4;
349 mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
350 for (ireg = 31; mask; --ireg, mask <<= 1)
351 if (mask & 0x80000000)
352 {
d747e0af 353 fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
bd5635a1
RP
354 reg_position -= 4;
355 }
356 }
357
358 /* hack: if argument regs are saved, guess these contain args */
359 if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
360 else if ((PROC_REG_MASK(proc_desc) & 0x80) == 0) fci->num_args = 4;
361 else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args = 3;
362 else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args = 2;
363 else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args = 1;
364
365 fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
366 }
367 if (fci->next == 0)
368 supply_register(FP_REGNUM, &fci->frame);
369}
370
371
372CORE_ADDR mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
373 int nargs;
374 value *args;
375 CORE_ADDR sp;
376 int struct_return;
377 CORE_ADDR struct_addr;
378{
379 CORE_ADDR buf;
380 register i;
381 int accumulate_size = struct_return ? 4 : 0;
382 struct mips_arg { char *contents; int len; int offset; };
383 struct mips_arg *mips_args =
384 (struct mips_arg*)alloca(nargs * sizeof(struct mips_arg));
385 register struct mips_arg *m_arg;
386 for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {
387 extern value value_arg_coerce();
388 value arg = value_arg_coerce (args[i]);
389 m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));
390 /* This entire mips-specific routine is because doubles must be aligned
391 * on 8-byte boundaries. It still isn't quite right, because MIPS decided
392 * to align 'struct {int a, b}' on 4-byte boundaries (even though this
393 * breaks their varargs implementation...). A correct solution
394 * requires an simulation of gcc's 'alignof' (and use of 'alignof'
395 * in stdarg.h/varargs.h).
396 */
397 if (m_arg->len > 4) accumulate_size = (accumulate_size + 7) & -8;
398 m_arg->offset = accumulate_size;
399 accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
400 m_arg->contents = VALUE_CONTENTS(arg);
401 }
402 accumulate_size = (accumulate_size + 7) & (-8);
403 if (accumulate_size < 16) accumulate_size = 16;
404 sp -= accumulate_size;
405 for (i = nargs; m_arg--, --i >= 0; )
406 write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
407 if (struct_return) {
408 buf = struct_addr;
409 write_memory(sp, &buf, sizeof(CORE_ADDR));
410}
411 return sp;
412}
413
414/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
415#define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1)
416
417void
418mips_push_dummy_frame()
419{
420 int ireg;
421 struct linked_proc_info *link = (struct linked_proc_info*)
422 xmalloc(sizeof(struct linked_proc_info));
423 mips_extra_func_info_t proc_desc = &link->info;
424 CORE_ADDR sp = read_register (SP_REGNUM);
425 CORE_ADDR save_address;
426 REGISTER_TYPE buffer;
427 link->next = linked_proc_desc_table;
428 linked_proc_desc_table = link;
429#define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
430#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<31)
431#define GEN_REG_SAVE_COUNT 22
432#define FLOAT_REG_SAVE_MASK MASK(0,19)
433#define FLOAT_REG_SAVE_COUNT 20
434#define SPECIAL_REG_SAVE_COUNT 4
435 /*
436 * The registers we must save are all those not preserved across
437 * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
438 * In addition, we must save the PC, and PUSH_FP_REGNUM.
439 * (Ideally, we should also save MDLO/-HI and FP Control/Status reg.)
440 *
441 * Dummy frame layout:
442 * (high memory)
443 * Saved PC
444 * Saved MMHI, MMLO, FPC_CSR
445 * Saved R31
446 * Saved R28
447 * ...
448 * Saved R1
449 * Saved D18 (i.e. F19, F18)
450 * ...
451 * Saved D0 (i.e. F1, F0)
452 * CALL_DUMMY (subroutine stub; see m-mips.h)
453 * Parameter build area (not yet implemented)
454 * (low memory)
455 */
456 PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
457 PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
458 PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */
459 -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;
460 PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */
461 -sizeof(double) - 4 * (SPECIAL_REG_SAVE_COUNT + GEN_REG_SAVE_COUNT);
462 /* save general registers */
463 save_address = sp + PROC_REG_OFFSET(proc_desc);
464 for (ireg = 32; --ireg >= 0; )
465 if (PROC_REG_MASK(proc_desc) & (1 << ireg))
466 {
467 buffer = read_register (ireg);
468 write_memory (save_address, &buffer, sizeof(REGISTER_TYPE));
469 save_address -= 4;
470 }
471 /* save floating-points registers */
472 save_address = sp + PROC_FREG_OFFSET(proc_desc);
473 for (ireg = 32; --ireg >= 0; )
474 if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
475 {
7d9884b9 476 buffer = read_register (ireg + FP0_REGNUM);
bd5635a1
RP
477 write_memory (save_address, &buffer, 4);
478 save_address -= 4;
479 }
480 write_register (PUSH_FP_REGNUM, sp);
481 PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
482 PROC_FRAME_OFFSET(proc_desc) = 0;
483 buffer = read_register (PC_REGNUM);
484 write_memory (sp - 4, &buffer, sizeof(REGISTER_TYPE));
485 buffer = read_register (HI_REGNUM);
486 write_memory (sp - 8, &buffer, sizeof(REGISTER_TYPE));
487 buffer = read_register (LO_REGNUM);
488 write_memory (sp - 12, &buffer, sizeof(REGISTER_TYPE));
489 buffer = read_register (FCRCS_REGNUM);
490 write_memory (sp - 16, &buffer, sizeof(REGISTER_TYPE));
491 sp -= 4 * (GEN_REG_SAVE_COUNT+FLOAT_REG_SAVE_COUNT+SPECIAL_REG_SAVE_COUNT);
492 write_register (SP_REGNUM, sp);
493 PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE + CALL_DUMMY_START_OFFSET;
494 PROC_HIGH_ADDR(proc_desc) = sp;
495 SET_PROC_DESC_IS_DUMMY(proc_desc);
496 PROC_PC_REG(proc_desc) = RA_REGNUM;
497}
498
499void
500mips_pop_frame()
501{ register int regnum;
502 FRAME frame = get_current_frame ();
503 CORE_ADDR new_sp = frame->frame;
504 mips_extra_func_info_t proc_desc = (mips_extra_func_info_t)frame->proc_desc;
505 if (PROC_DESC_IS_DUMMY(proc_desc))
506 {
507 struct linked_proc_info **ptr = &linked_proc_desc_table;;
508 for (; &ptr[0]->info != proc_desc; ptr = &ptr[0]->next )
509 if (ptr[0] == NULL) abort();
510 *ptr = ptr[0]->next;
511 free (ptr[0]);
512 write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4));
513 write_register (LO_REGNUM, read_memory_integer(new_sp - 12, 4));
514 write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
515 }
516 write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
517 if (frame->proc_desc) {
518 for (regnum = 32; --regnum >= 0; )
519 if (PROC_REG_MASK(proc_desc) & (1 << regnum))
520 write_register (regnum,
521 read_memory_integer (frame->saved_regs->regs[regnum], 4));
7d9884b9 522 for (regnum = 32; --regnum >= 0; )
bd5635a1 523 if (PROC_FREG_MASK(proc_desc) & (1 << regnum))
7d9884b9
JG
524 write_register (regnum + FP0_REGNUM,
525 read_memory_integer (frame->saved_regs->regs[regnum + FP0_REGNUM], 4));
bd5635a1
RP
526 }
527 write_register (SP_REGNUM, new_sp);
528 flush_cached_frames ();
529 set_current_frame (create_new_frame (new_sp, read_pc ()));
530}
531
d8b3b00e
JG
532static
533mips_print_register(regnum, all)
bd5635a1
RP
534 int regnum, all;
535{
536 unsigned char raw_buffer[8];
537 REGISTER_TYPE val;
538
539 read_relative_register_raw_bytes (regnum, raw_buffer);
540
d747e0af
MT
541 /* If an even floating pointer register, also print as double. */
542 if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+32
543 && !((regnum-FP0_REGNUM) & 1)) {
bd5635a1 544 read_relative_register_raw_bytes (regnum+1, raw_buffer+4);
d747e0af 545 printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
bd5635a1
RP
546 val_print (builtin_type_double, raw_buffer, 0,
547 stdout, 0, 1, 0, Val_pretty_default);
d747e0af 548 printf_filtered ("); ");
bd5635a1
RP
549 }
550 fputs_filtered (reg_names[regnum], stdout);
551#ifndef NUMERIC_REG_NAMES
552 if (regnum < 32)
553 printf_filtered ("(r%d): ", regnum);
554 else
555#endif
556 printf_filtered (": ");
557
558 /* If virtual format is floating, print it that way. */
559 if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
560 && ! INVALID_FLOAT (raw_buffer, REGISTER_VIRTUAL_SIZE(regnum))) {
561 val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
562 stdout, 0, 1, 0, Val_pretty_default);
563 }
564 /* Else print as integer in hex. */
565 else
566 {
567 long val;
568
569 bcopy (raw_buffer, &val, sizeof (long));
570 if (val == 0)
571 printf_filtered ("0");
572 else if (all)
d8b3b00e 573 printf_filtered (local_hex_format(), val);
bd5635a1 574 else
d8b3b00e 575 printf_filtered ("%s=%d", local_hex_string(val), val);
bd5635a1
RP
576 }
577}
578
d8b3b00e 579/* Replacement for generic do_registers_info. */
361bf6ee 580mips_do_registers_info (regnum, fpregs)
bd5635a1 581 int regnum;
361bf6ee 582 int fpregs;
bd5635a1
RP
583{
584 if (regnum != -1) {
585 mips_print_register (regnum, 0);
586 printf_filtered ("\n");
587 }
588 else {
589 for (regnum = 0; regnum < NUM_REGS; ) {
d8b3b00e
JG
590 if ((!fpregs) && regnum >= FP0_REGNUM && regnum <= FCRIR_REGNUM) {
591 regnum++;
592 continue;
593 }
bd5635a1
RP
594 mips_print_register (regnum, 1);
595 regnum++;
596 if ((regnum & 3) == 0 || regnum == NUM_REGS)
597 printf_filtered (";\n");
598 else
599 printf_filtered ("; ");
600 }
601 }
602}
603/* Return number of args passed to a frame. described by FIP.
604 Can return -1, meaning no way to tell. */
605
606mips_frame_num_args(fip)
607 FRAME fip;
608{
609#if 0
610 struct chain_info_t *p;
611
612 p = mips_find_cached_frame(FRAME_FP(fip));
613 if (p->valid)
614 return p->the_info.numargs;
615#endif
616 return -1;
617}
618
619\f
620/* Bad floats: Returns 0 if P points to a valid IEEE floating point number,
621 1 if P points to a denormalized number or a NaN. LEN says whether this is
622 a single-precision or double-precision float */
623#define SINGLE_EXP_BITS 8
624#define DOUBLE_EXP_BITS 11
625int
626isa_NAN(p, len)
627 int *p, len;
628{
629 int exponent;
630 if (len == 4)
631 {
632 exponent = *p;
633 exponent = exponent << 1 >> (32 - SINGLE_EXP_BITS - 1);
634 return ((exponent == -1) || (! exponent && *p));
635 }
636 else if (len == 8)
637 {
638 exponent = *(p+1);
639 exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
640 return ((exponent == -1) || (! exponent && *p * *(p+1)));
641 }
642 else return 1;
643}
644
645/* To skip prologues, I use this predicate. Returns either PC
646 itself if the code at PC does not look like a function prologue,
647 PC+4 if it does (our caller does not need anything more fancy). */
648
649CORE_ADDR mips_skip_prologue(pc)
650 CORE_ADDR pc;
651{
652 struct symbol *f;
653 struct block *b;
654 unsigned long inst;
d747e0af 655 int offset;
bd5635a1
RP
656
657 /* For -g modules and most functions anyways the
d747e0af
MT
658 first instruction adjusts the stack.
659 But we allow some number of stores before the stack adjustment.
660 (These are emitted by varags functions compiled by gcc-2.0. */
661 for (offset = 0; offset < 100; offset += 4) {
662 inst = read_memory_integer(pc + offset, 4);
663 if ((inst & 0xffff0000) == 0x27bd0000) /* addiu $sp,$sp,offset */
664 return pc + offset + 4;
665 if ((inst & 0xFFE00000) != 0xAFA00000) /* sw reg,n($sp) */
666 break;
667 }
bd5635a1
RP
668
669 /* Well, it looks like a frameless. Let's make sure.
670 Note that we are not called on the current PC,
671 but on the function`s start PC, and I have definitely
672 seen optimized code that adjusts the SP quite later */
673 b = block_for_pc(pc);
674 if (!b) return pc;
675
676 f = lookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, 0, NULL);
677 if (!f) return pc;
678 /* Ideally, I would like to use the adjusted info
679 from mips_frame_info(), but for all practical
680 purposes it will not matter (and it would require
681 a different definition of SKIP_PROLOGUE())
682
683 Actually, it would not hurt to skip the storing
684 of arguments on the stack as well. */
685 if (((struct mips_extra_func_info *)f->value.value)->framesize)
686 return pc + 4;
687
688 return pc;
689}
d747e0af
MT
690
691/* Figure out where the longjmp will land.
692 We expect the first arg to be a pointer to the jmp_buf structure from which
693 we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
694 This routine returns true on success. */
695
696int
697get_longjmp_target(pc)
698 CORE_ADDR *pc;
699{
700 CORE_ADDR jb_addr;
701
702 jb_addr = read_register(A0_REGNUM);
703
704 if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, pc,
705 sizeof(CORE_ADDR)))
706 return 0;
707
708 SWAP_TARGET_AND_HOST(pc, sizeof(CORE_ADDR));
709
710 return 1;
711}
This page took 0.077706 seconds and 4 git commands to generate.