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