]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/sh-tdep.c
The point of these changes is to avoid reading the frame pointer
[thirdparty/binutils-gdb.git] / gdb / sh-tdep.c
1 /* Target-machine dependent code for Hitachi Super-H, for GDB.
2 Copyright (C) 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 Contributed by Steve Chamberlain
22 sac@cygnus.com
23 */
24
25 #include "defs.h"
26 #include "frame.h"
27 #include "obstack.h"
28 #include "symtab.h"
29 #include "gdbtypes.h"
30 #include "gdbcmd.h"
31 #include "value.h"
32 #include "dis-asm.h"
33 #include "../opcodes/sh-opc.h"
34
35
36
37
38 /* Prologue looks like
39 [mov.l <regs>,@-r15]...
40 [sts.l pr,@-r15]
41 [mov.l r14,@-r15]
42 [mov r15,r14]
43 */
44
45 #define IS_STS(x) ((x) == 0x4f22)
46 #define IS_PUSH(x) (((x) & 0xff0f) == 0x2f06)
47 #define GET_PUSHED_REG(x) (((x) >> 4) & 0xf)
48 #define IS_MOV_SP_FP(x) ((x) == 0x6ef3)
49 #define IS_ADD_SP(x) (((x) & 0xff00) == 0x7f00)
50 #define IS_MOV_R3(x) (((x) & 0xff00) == 0x1a00)
51 #define IS_SHLL_R3(x) ((x) == 0x4300)
52 #define IS_ADD_R3SP(x) ((x) == 0x3f3c)
53
54 /* Skip any prologue before the guts of a function */
55
56 CORE_ADDR
57 sh_skip_prologue (start_pc)
58 CORE_ADDR start_pc;
59
60 {
61 int w;
62
63 w = read_memory_integer (start_pc, 2);
64 while (IS_STS (w)
65 || IS_PUSH (w)
66 || IS_MOV_SP_FP (w)
67 || IS_MOV_R3(w)
68 || IS_ADD_R3SP(w)
69 || IS_ADD_SP(w)
70 || IS_SHLL_R3(w))
71 {
72 start_pc += 2;
73 w = read_memory_integer (start_pc, 2);
74 }
75
76 return start_pc;
77 }
78
79 /* Disassemble an instruction */
80
81 int
82 print_insn (memaddr, stream)
83 CORE_ADDR memaddr;
84 GDB_FILE *stream;
85 {
86 disassemble_info info;
87 GDB_INIT_DISASSEMBLE_INFO (info, stream);
88 return print_insn_sh (memaddr, &info);
89 }
90
91 /* Given a GDB frame, determine the address of the calling function's frame.
92 This will be used to create a new GDB frame struct, and then
93 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
94
95 For us, the frame address is its stack pointer value, so we look up
96 the function prologue to determine the caller's sp value, and return it. */
97
98 FRAME_ADDR
99 sh_frame_chain (thisframe)
100 FRAME thisframe;
101 {
102 if (!inside_entry_file (thisframe->pc))
103 return (read_memory_integer (FRAME_FP (thisframe) + thisframe->f_offset, 4));
104 else
105 return 0;
106 }
107
108 /* Put here the code to store, into a struct frame_saved_regs,
109 the addresses of the saved registers of frame described by FRAME_INFO.
110 This includes special registers such as pc and fp saved in special
111 ways in the stack frame. sp is even more special:
112 the address we return for it IS the sp for the next frame. */
113
114
115 void
116 frame_find_saved_regs (fi, fsr)
117 struct frame_info *fi;
118 struct frame_saved_regs *fsr;
119 {
120 int where[NUM_REGS];
121 int rn;
122 int have_fp = 0;
123 int depth;
124 int pc;
125 int opc;
126 int insn;
127 int hadf;
128 int r3_val = 0;
129
130 opc = pc = get_pc_function_start (fi->pc);
131
132 insn = read_memory_integer (pc, 2);
133
134 fi->leaf_function = 1;
135 fi->f_offset = 0;
136
137 for (rn = 0; rn < NUM_REGS; rn++)
138 where[rn] = -1;
139
140 depth = 0;
141
142 /* Loop around examining the prologue insns, but give up
143 after 15 of them, since we're getting silly then */
144 while (pc < opc + 15 * 2)
145 {
146 /* See where the registers will be saved to */
147 if (IS_PUSH (insn))
148 {
149 pc += 2;
150 rn = GET_PUSHED_REG (insn);
151 where[rn] = depth;
152 insn = read_memory_integer (pc, 2);
153 depth += 4;
154 }
155 else if (IS_STS (insn))
156 {
157 pc += 2;
158 where[PR_REGNUM] = depth;
159 insn = read_memory_integer (pc, 2);
160 /* If we're storing the pr then this isn't a leaf */
161 fi->leaf_function = 0;
162 depth += 4;
163 }
164 else if (IS_MOV_R3 (insn))
165 {
166 r3_val = (char)(insn & 0xff);
167 pc+=2;
168 insn = read_memory_integer (pc, 2);
169 }
170 else if (IS_SHLL_R3 (insn))
171 {
172 r3_val <<=1;
173 pc+=2;
174 insn = read_memory_integer (pc, 2);
175 }
176 else if (IS_ADD_R3SP (insn))
177 {
178 depth += -r3_val;
179 pc+=2;
180 insn = read_memory_integer (pc, 2);
181 }
182 else if (IS_ADD_SP (insn))
183 {
184 pc += 2;
185 depth += -((char) (insn & 0xff));
186 insn = read_memory_integer (pc, 2);
187 }
188 else
189 break;
190 }
191
192 /* Now we know how deep things are, we can work out their addresses */
193
194 for (rn = 0; rn < NUM_REGS; rn++)
195 {
196 if (where[rn] >= 0)
197 {
198 if (rn == FP_REGNUM)
199 have_fp = 1;
200
201 fsr->regs[rn] = fi->frame - where[rn] + depth - 4;
202 }
203 else
204 {
205 fsr->regs[rn] = 0;
206 }
207 }
208
209 if (have_fp)
210 {
211 fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[FP_REGNUM], 4);
212 }
213 else
214 {
215 fsr->regs[SP_REGNUM] = fi->frame - 4;
216 }
217
218 fi->f_offset = depth - where[FP_REGNUM] - 4;
219 /* Work out the return pc - either from the saved pr or the pr
220 value */
221 /* Just called, so dig out the real return */
222 if (fi->return_pc == 0)
223 {
224 fi->return_pc = read_register (PR_REGNUM) + 4;
225 }
226 else {
227
228 if (fsr->regs[PR_REGNUM])
229 {
230 fi->return_pc = read_memory_integer (fsr->regs[PR_REGNUM], 4) + 4;
231 }
232 else
233 {
234 fi->return_pc = read_register (PR_REGNUM) + 4;
235 }
236 }
237 }
238
239 /* initialize the extra info saved in a FRAME */
240
241 void
242 init_extra_frame_info (fromleaf, fi)
243 int fromleaf;
244 struct frame_info *fi;
245 {
246 struct frame_saved_regs dummy;
247 frame_find_saved_regs (fi, &dummy);
248 }
249
250
251 /* Discard from the stack the innermost frame,
252 restoring all saved registers. */
253
254 void
255 pop_frame ()
256 {
257 register FRAME frame = get_current_frame ();
258 register CORE_ADDR fp;
259 register int regnum;
260 struct frame_saved_regs fsr;
261 struct frame_info *fi;
262
263 fi = get_frame_info (frame);
264 fp = fi->frame;
265 get_frame_saved_regs (fi, &fsr);
266
267 /* Copy regs from where they were saved in the frame */
268 for (regnum = 0; regnum < NUM_REGS; regnum++)
269 {
270 if (fsr.regs[regnum])
271 {
272 write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
273 }
274 }
275
276 write_register (PC_REGNUM, fi->return_pc);
277 write_register (SP_REGNUM, fp + 4);
278 flush_cached_frames ();
279 }
280
281 /* Print the registers in a form similar to the E7000 */
282 static void
283 show_regs (args, from_tty)
284 char *args;
285 int from_tty;
286 {
287 printf_filtered("PC=%08x SR=%08x PR=%08x MACH=%08x MACHL=%08x\n",
288 read_register(PC_REGNUM),
289 read_register(SR_REGNUM),
290 read_register(PR_REGNUM),
291 read_register(MACH_REGNUM),
292 read_register(MACL_REGNUM));
293
294 printf_filtered("R0-R7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
295 read_register(0),
296 read_register(1),
297 read_register(2),
298 read_register(3),
299 read_register(4),
300 read_register(5),
301 read_register(6),
302 read_register(7));
303 printf_filtered("R8-R15 %08x %08x %08x %08x %08x %08x %08x %08x\n",
304 read_register(8),
305 read_register(9),
306 read_register(10),
307 read_register(11),
308 read_register(12),
309 read_register(13),
310 read_register(14),
311 read_register(15));
312 }
313 \f
314
315 void
316 _initialize_sh_tdep ()
317 {
318 extern int sim_memory_size;
319 /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
320 add_show_from_set
321 (add_set_cmd ("memory_size", class_support, var_uinteger,
322 (char *) &sim_memory_size,
323 "Set simulated memory size of simulator target.", &setlist),
324 &showlist);
325
326 add_com("regs", class_vars, show_regs, "Print all registers");
327 }