* interp.c (MEM_SIZE): It's now bytes, not a power of 2.
[deliverable/binutils-gdb.git] / gdb / v850-tdep.c
CommitLineData
e2810631
SG
1/* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
2 Copyright 1986, 1996
3 Free Software Foundation, Inc.
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21/* ??? Support for calling functions from gdb in sparc64 is unfinished. */
22
23#include "defs.h"
24#include "frame.h"
25#include "inferior.h"
26#include "obstack.h"
27#include "target.h"
28#include "value.h"
29#include "bfd.h"
30#include "gdb_string.h"
31
32#include "gdbcore.h"
e5a2ac8b
SG
33
34\f
35/* This function actually figures out the frame address for a given pc and
36 sp. This is tricky on the v850 because we only use an explicit frame
37 pointer when using alloca(). The only reliable way to get this info is to
38 examine the prologue.
39*/
40
41void
42v850_init_extra_frame_info (fi)
43 struct frame_info *fi;
44{
45 struct symtab_and_line sal;
46 CORE_ADDR func_addr, prologue_end, current_pc;
47 int reg;
48 int frameoffset;
49 int framereg;
50
51 if (fi->next)
52 fi->pc = v850_find_callers_reg (fi->next, RP_REGNUM);
53
54 /* First, figure out the bounds of the prologue so that we can limit the
55 search to something reasonable. */
56
57 if (find_pc_partial_function (fi->pc, NULL, &func_addr, NULL))
58 {
59 sal = find_pc_line (func_addr, 0);
60
61 prologue_end = sal.end;
62 }
63 else
64 prologue_end = func_addr + 100; /* We're in the boondocks */
65
66 prologue_end = min (prologue_end, fi->pc);
67
68 /* Now, search the prologue looking for instructions that setup fp, save
69 rp, adjust sp and such. */
70
71 framereg = SP_REGNUM;
72 frameoffset = 0;
73 memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
74
75 for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2)
76 {
77 int insn;
78
79 insn = read_memory_integer (current_pc, 2);
80
81 if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
82 frameoffset = (insn & 0x1f) | ~0x1f;
83 else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
84 {
85 current_pc += 2;
86
87 frameoffset = read_memory_integer (current_pc, 2);
88 }
89 else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */
90 framereg = FP_REGNUM; /* Setting up fp */
91 else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM)) /* st.w <reg>,<offset>[sp] */
92 {
93 reg = (insn >> 11) & 0x1f; /* Extract <reg> */
94 current_pc += 2;
95
96 insn = read_memory_integer (current_pc, 2) & ~1;
97
98 fi->fsr.regs[reg] = insn + frameoffset;
99 }
100 else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM)) /* st.w <reg>,<offset>[fp] */
101 {
102 reg = (insn >> 11) & 0x1f; /* Extract <reg> */
103 current_pc += 2;
104
105 insn = read_memory_integer (current_pc, 2) & ~1;
106
107 fi->fsr.regs[reg] = insn;
108 }
109 }
110
111#if 0
112 if (!fi->next)
113 fi->frame = read_register (framereg);
114 else
115 if (framereg == SP_REGNUM)
116 fi->frame = fi->next->frame;
117 else
118 fi->frame = v850_find_callers_reg (fi, framereg);
119
120 if (framereg == SP_REGNUM)
121 fi->frame -= frameoffset;
122#else
123 if (!fi->next && framereg == SP_REGNUM)
124 fi->frame = read_register (framereg) - frameoffset;
125#endif
126
127 for (reg = 0; reg < NUM_REGS; reg++)
128 if (fi->fsr.regs[reg] != 0)
129 fi->fsr.regs[reg] += fi->frame;
130}
131
132/* Find the caller of this frame. We do this by seeing if RP_REGNUM is saved
133 in the stack anywhere, otherwise we get it from the registers. */
134
135CORE_ADDR
136v850_find_callers_reg (fi, regnum)
137 struct frame_info *fi;
138 int regnum;
139{
140 for (; fi; fi = fi->next)
141 if (fi->fsr.regs[regnum] != 0)
142 return read_memory_integer (fi->fsr.regs[regnum], 4);
143
144 return read_register (regnum);
145}
146
147CORE_ADDR
148v850_frame_chain (fi)
149 struct frame_info *fi;
150{
151 CORE_ADDR callers_pc, callers_sp;
152 struct frame_info temp_fi;
153 CORE_ADDR func_addr, prologue_end, current_pc;
154 int frameoffset;
155
156 /* First, find out who called us */
157
158 callers_pc = v850_find_callers_reg (fi, RP_REGNUM);
159
160 /* Next, figure out where his prologue is. */
161
162 if (find_pc_partial_function (callers_pc, NULL, &func_addr, NULL))
163 {
164 struct symtab_and_line sal;
165
166 sal = find_pc_line (func_addr, 0);
167
168 prologue_end = sal.end;
169 }
170 else
171 prologue_end = func_addr + 100; /* We're in the boondocks */
172
173 prologue_end = min (prologue_end, callers_pc);
174
175 /* Now, figure out the frame location of the caller by examining his prologue.
176 We're looking for either a load of the frame pointer register, or a stack
177 adjustment. */
178
179 frameoffset = 0;
180
181 for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2)
182 {
183 int insn;
184
185 insn = read_memory_integer (current_pc, 2);
186
187 if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
188 frameoffset = (insn & 0x1f) | ~0x1f;
189 else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
190 {
191 current_pc += 2;
192
193 frameoffset = read_memory_integer (current_pc, 2);
194 }
195 else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */
196 return v850_find_callers_reg (fi, FP_REGNUM); /* It's using a frame pointer reg */
197 else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM)) /* st.w <reg>,<offset>[sp] */
198 current_pc += 2;
199 else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM)) /* st.w <reg>,<offset>[fp] */
200 current_pc += 2;
201 }
202
203 return fi->frame - frameoffset;
204}
205
206CORE_ADDR
207v850_skip_prologue (pc)
208 CORE_ADDR pc;
209{
210 CORE_ADDR func_addr, func_end;
211
212 /* See what the symbol table says */
213
214 if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
215 {
216 struct symtab_and_line sal;
217
218 sal = find_pc_line (func_addr, 0);
219
220 if (sal.end < func_end)
221 return sal.end;
222 else
223 /* The line after the prologue is after the end of the function. In
224 this case, there probably isn't a prologue. */
225 return pc;
226 }
227
228/* We can't find the start of this function, so there's nothing we can do. */
229 return pc;
230}
231
232struct frame_info *
233v850_pop_frame (frame)
234 struct frame_info *frame;
235{
236 int regnum;
237
238 write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
239
240 for (regnum = 0; regnum < NUM_REGS; regnum++)
241 if (frame->fsr.regs[regnum] != 0)
242 write_register (regnum, read_memory_integer (frame->fsr.regs[regnum], 4));
243
244 write_register (SP_REGNUM, FRAME_FP (frame));
245 flush_cached_frames ();
246
247 return NULL;
248}
e2810631
SG
249\f
250void
251_initialize_sparc_tdep ()
252{
253 tm_print_insn = print_insn_v850;
254}
This page took 0.036564 seconds and 4 git commands to generate.