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