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