1130803Smarcel/* Traditional frame unwind support, for GDB the GNU Debugger.
2130803Smarcel
3130803Smarcel   Copyright 2003 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "frame.h"
24130803Smarcel#include "trad-frame.h"
25130803Smarcel#include "regcache.h"
26130803Smarcel
27130803Smarcel/* A traditional frame is unwound by analysing the function prologue
28130803Smarcel   and using the information gathered to track registers.  For
29130803Smarcel   non-optimized frames, the technique is reliable (just need to check
30130803Smarcel   for all potential instruction sequences).  */
31130803Smarcel
32130803Smarcelstruct trad_frame_saved_reg *
33130803Smarceltrad_frame_alloc_saved_regs (struct frame_info *next_frame)
34130803Smarcel{
35130803Smarcel  int regnum;
36130803Smarcel  struct gdbarch *gdbarch = get_frame_arch (next_frame);
37130803Smarcel  int numregs = NUM_REGS + NUM_PSEUDO_REGS;
38130803Smarcel  struct trad_frame_saved_reg *this_saved_regs
39130803Smarcel    = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
40130803Smarcel  for (regnum = 0; regnum < numregs; regnum++)
41130803Smarcel    {
42130803Smarcel      this_saved_regs[regnum].realreg = regnum;
43130803Smarcel      this_saved_regs[regnum].addr = -1;
44130803Smarcel    }
45130803Smarcel  return this_saved_regs;
46130803Smarcel}
47130803Smarcel
48130803Smarcelenum { REG_VALUE = -1, REG_UNKNOWN = -2 };
49130803Smarcel
50130803Smarcelint
51130803Smarceltrad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
52130803Smarcel{
53130803Smarcel  return (this_saved_regs[regnum].realreg == REG_VALUE);
54130803Smarcel}
55130803Smarcel
56130803Smarcelint
57130803Smarceltrad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
58130803Smarcel{
59130803Smarcel  return (this_saved_regs[regnum].realreg >= 0
60130803Smarcel	  && this_saved_regs[regnum].addr != -1);
61130803Smarcel}
62130803Smarcel
63130803Smarcelint
64130803Smarceltrad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
65130803Smarcel		      int regnum)
66130803Smarcel{
67130803Smarcel  return (this_saved_regs[regnum].realreg >= 0
68130803Smarcel	  && this_saved_regs[regnum].addr == -1);
69130803Smarcel}
70130803Smarcel
71130803Smarcelvoid
72130803Smarceltrad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
73130803Smarcel		      int regnum, LONGEST val)
74130803Smarcel{
75130803Smarcel  /* Make the REALREG invalid, indicating that the ADDR contains the
76130803Smarcel     register's value.  */
77130803Smarcel  this_saved_regs[regnum].realreg = REG_VALUE;
78130803Smarcel  this_saved_regs[regnum].addr = val;
79130803Smarcel}
80130803Smarcel
81130803Smarcelvoid
82130803Smarceltrad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
83130803Smarcel			int regnum)
84130803Smarcel{
85130803Smarcel  /* Make the REALREG invalid, indicating that the value is not known.  */
86130803Smarcel  this_saved_regs[regnum].realreg = REG_UNKNOWN;
87130803Smarcel  this_saved_regs[regnum].addr = -1;
88130803Smarcel}
89130803Smarcel
90130803Smarcelvoid
91130803Smarceltrad_frame_prev_register (struct frame_info *next_frame,
92130803Smarcel			  struct trad_frame_saved_reg this_saved_regs[],
93130803Smarcel			  int regnum, int *optimizedp,
94130803Smarcel			  enum lval_type *lvalp, CORE_ADDR *addrp,
95130803Smarcel			  int *realregp, void *bufferp)
96130803Smarcel{
97130803Smarcel  struct gdbarch *gdbarch = get_frame_arch (next_frame);
98130803Smarcel  if (trad_frame_addr_p (this_saved_regs, regnum))
99130803Smarcel    {
100130803Smarcel      /* The register was saved in memory.  */
101130803Smarcel      *optimizedp = 0;
102130803Smarcel      *lvalp = lval_memory;
103130803Smarcel      *addrp = this_saved_regs[regnum].addr;
104130803Smarcel      *realregp = -1;
105130803Smarcel      if (bufferp != NULL)
106130803Smarcel	{
107130803Smarcel	  /* Read the value in from memory.  */
108130803Smarcel	  get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
109130803Smarcel			    register_size (gdbarch, regnum));
110130803Smarcel	}
111130803Smarcel    }
112130803Smarcel  else if (trad_frame_realreg_p (this_saved_regs, regnum))
113130803Smarcel    {
114130803Smarcel      /* Ask the next frame to return the value of the register.  */
115130803Smarcel      frame_register_unwind (next_frame, this_saved_regs[regnum].realreg,
116130803Smarcel			     optimizedp, lvalp, addrp, realregp, bufferp);
117130803Smarcel    }
118130803Smarcel  else if (trad_frame_value_p (this_saved_regs, regnum))
119130803Smarcel    {
120130803Smarcel      /* The register's value is available.  */
121130803Smarcel      *optimizedp = 0;
122130803Smarcel      *lvalp = not_lval;
123130803Smarcel      *addrp = 0;
124130803Smarcel      *realregp = -1;
125130803Smarcel      if (bufferp != NULL)
126130803Smarcel	store_unsigned_integer (bufferp, register_size (gdbarch, regnum),
127130803Smarcel				this_saved_regs[regnum].addr);
128130803Smarcel    }
129130803Smarcel  else
130130803Smarcel    {
131130803Smarcel      error ("Register %s not available",
132130803Smarcel	     gdbarch_register_name (gdbarch, regnum));
133130803Smarcel    }
134130803Smarcel}
135