add comment
[deliverable/binutils-gdb.git] / gdb / sh-tdep.c
CommitLineData
9faacb92
SC
1/* Target-machine dependent code for Hitachi Super-H, for GDB.
2 Copyright (C) 1993 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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/* Prologue looks like
37 [mov.l <regs>,@-r15]...
38 [sts.l pr,@-r15]
39 [mov.l r14,@-r15]
40 [mov r15,r14]
41*/
42
43#define IS_STS(x) ((x) == 0x4f22)
44#define IS_PUSH(x) (((x) & 0xff0f) == 0x2f06)
45#define GET_PUSHED_REG(x) (((x) >> 4) & 0xf)
46#define IS_MOV_SP_FP(x) ((x) == 0x6ef3)
47#define IS_ADD_SP(x) (((x) & 0xff00) == 0x7f00)
48
49
50/* Skip any prologue before the guts of a function */
51
52CORE_ADDR
53sh_skip_prologue (start_pc)
54 CORE_ADDR start_pc;
55
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 {
64 start_pc += 2;
65 w = read_memory_integer (start_pc, 2);
66 }
67
68 return start_pc;
69}
70
71/* Disassemble an instruction */
72
73int
74print_insn (memaddr, stream)
75 CORE_ADDR memaddr;
76 FILE *stream;
77{
78 disassemble_info info;
79 GDB_INIT_DISASSEMBLE_INFO (info, stream);
80 return print_insn_sh (memaddr, &info);
81}
82
83/* Given a GDB frame, determine the address of the calling function's frame.
84 This will be used to create a new GDB frame struct, and then
85 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
86
87 For us, the frame address is its stack pointer value, so we look up
88 the function prologue to determine the caller's sp value, and return it. */
89
90FRAME_ADDR
91sh_frame_chain (thisframe)
92 FRAME thisframe;
93{
94 if (!inside_entry_file (thisframe->pc))
95 return (read_memory_integer (FRAME_FP (thisframe), 4));
96 else
97 return 0;
98}
99
100/* Put here the code to store, into a struct frame_saved_regs,
101 the addresses of the saved registers of frame described by FRAME_INFO.
102 This includes special registers such as pc and fp saved in special
103 ways in the stack frame. sp is even more special:
104 the address we return for it IS the sp for the next frame. */
105
106
107void
108frame_find_saved_regs (fi, fsr)
109 struct frame_info *fi;
110 struct frame_saved_regs *fsr;
111{
112 int where[16];
113 int rn;
114 int have_fp = 0;
115 int depth;
116 int pc;
117 int opc;
118 int insn;
119
120 opc = pc = get_pc_function_start (fi->pc);
121
122 insn = read_memory_integer (pc, 2);
123
124 for (rn = 0; rn < NUM_REGS; rn++)
125 where[rn] = -1;
126
127 depth = 0;
128
129 /* Loop around examining the prologue insns, but give up
130 after 15 of them, since we're getting silly then */
131 while (pc < opc + 15 * 2)
132 {
133 /* See where the registers will be saved to */
134 if (IS_PUSH (insn))
135 {
136 pc += 2;
137 rn = GET_PUSHED_REG (insn);
138 where[rn] = depth;
139 insn = read_memory_integer (pc, 2);
140 depth += 4;
141 }
142 else if (IS_STS (insn))
143 {
144 pc += 2;
145 where[PR_REGNUM] = depth;
146 insn = read_memory_integer (pc, 2);
147 depth += 4;
148 }
149 else if (IS_ADD_SP (insn))
150 {
151 pc += 2;
152 depth += -((char) (insn & 0xff));
153 insn = read_memory_integer (pc, 2);
154 }
155 else break;
156 }
157
158 /* Now we know how deep things are, we can work out their addresses */
159
160 for (rn = 0; rn < NUM_REGS; rn++)
161 {
162 if (where[rn] >= 0)
163 {
164 if (rn == FP_REGNUM)
165 have_fp = 1;
166
167 fsr->regs[rn] = fi->frame - where[rn] + depth - 4;
168 }
169 else
170 {
171 fsr->regs[rn] = 0;
172 }
173 }
174
175 if (have_fp)
176 {
177
178 fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[FP_REGNUM], 4);
179 }
180 else
181 {
182 fsr->regs[SP_REGNUM] = fi->frame - 4;
183 }
184
185 /* Remember the address of the frame pointer */
186
187 /* Work out the return pc - either from the saved pr or the pr
188 value */
189
190 if (fsr->regs[PR_REGNUM])
191 {
192 fi->return_pc = read_memory_integer (fsr->regs[PR_REGNUM], 4) + 4;
193 }
194 else
195 {
196 fi->return_pc = read_register (PR_REGNUM) + 4;
197 }
198}
199
200/* initialize the extra info saved in a FRAME */
201
202void
203init_extra_frame_info (fromleaf, fi)
204 int fromleaf;
205 struct frame_info *fi;
206{
207 struct frame_saved_regs dummy;
208 frame_find_saved_regs (fi, &dummy);
209}
210
211
212/* Discard from the stack the innermost frame,
213 restoring all saved registers. */
214
215void
216pop_frame ()
217{
218 register FRAME frame = get_current_frame ();
219 register CORE_ADDR fp;
220 register int regnum;
221 struct frame_saved_regs fsr;
222 struct frame_info *fi;
223
224 fi = get_frame_info (frame);
225 fp = fi->frame;
226 get_frame_saved_regs (fi, &fsr);
227
228 /* Copy regs from where they were saved in the frame */
229 for (regnum = 0; regnum < NUM_REGS; regnum++)
230 {
231 if (fsr.regs[regnum])
232 {
233 write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
234 }
235 }
236
237 write_register (PC_REGNUM, fi->return_pc);
238 write_register (SP_REGNUM, fp + 4);
239 flush_cached_frames ();
240 set_current_frame (create_new_frame (read_register (FP_REGNUM),
241 read_pc ()));
242}
This page took 0.039866 seconds and 4 git commands to generate.