87fde344952eaf1a54ec5323601205cc9443236b
[deliverable/binutils-gdb.git] / gdb / d10v-tdep.c
1 /* Target-dependent code for MItsubishi D10V, for GDB.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of GDB.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15
16 /* Contributed by Martin Hunt, hunt@cygnus.com */
17
18 #include "defs.h"
19 #include "frame.h"
20 #include "obstack.h"
21 #include "symtab.h"
22 #include "gdbtypes.h"
23 #include "gdbcmd.h"
24 #include "gdbcore.h"
25 #include "value.h"
26 #include "inferior.h"
27 #include "dis-asm.h"
28
29 void d10v_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *fsr));
30
31 /* Discard from the stack the innermost frame,
32 restoring all saved registers. */
33
34 void
35 d10v_pop_frame ()
36 {
37 struct frame_info *frame = get_current_frame ();
38 CORE_ADDR fp, r13;
39 int regnum;
40 struct frame_saved_regs fsr;
41 char raw_buffer[8];
42
43 fp = FRAME_FP (frame);
44 /* printf("pop_frame 0x%x\n",fp); */
45
46 /* fill out fsr with the address of where each */
47 /* register was stored in the frame */
48 get_frame_saved_regs (frame, &fsr);
49
50 /* r13 contains the old PC. save it. */
51 r13 = read_register (13);
52
53 /* now update the current registers with the old values */
54 for (regnum = A0_REGNUM; regnum < A0_REGNUM+2 ; regnum++)
55 {
56 if (fsr.regs[regnum])
57 {
58 read_memory (fsr.regs[regnum] & 0xFFFF, raw_buffer, 8);
59 write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 8);
60 }
61 }
62 for (regnum = 0; regnum < SP_REGNUM; regnum++)
63 {
64 if (fsr.regs[regnum])
65 {
66 write_register (regnum, read_memory_integer (fsr.regs[regnum] & 0xFFFF, 2));
67 }
68 }
69 if (fsr.regs[PSW_REGNUM])
70 {
71 write_register (PSW_REGNUM, read_memory_integer (fsr.regs[PSW_REGNUM] & 0xFFFF, 2));
72 }
73
74 /* PC is set to r13 */
75 write_register (PC_REGNUM, r13);
76 /* printf("setting stack to %x\n",fp - frame->size); */
77 write_register (SP_REGNUM, fp - frame->size);
78 flush_cached_frames ();
79 }
80
81 static int
82 check_prologue (op)
83 unsigned short op;
84 {
85 /* st rn, @-sp */
86 if ((op & 0x7E1F) == 0x6C1F)
87 return 1;
88
89 /* st2w rn, @-sp */
90 if ((op & 0x7E3F) == 0x6E1F)
91 return 1;
92
93 /* subi sp, n */
94 if ((op & 0x7FE1) == 0x01E1)
95 return 1;
96
97 /* mv r11, sp */
98 if (op == 0x417E)
99 return 1;
100
101 /* nop */
102 if (op == 0x5E00)
103 return 1;
104
105 /* st rn, @sp */
106 if ((op & 0x7E1F) == 0x681E)
107 return 1;
108
109 /* st2w rn, @sp */
110 if ((op & 0x7E3F) == 0x3A1E)
111 return 1;
112
113
114 return 0;
115 }
116
117 CORE_ADDR
118 d10v_skip_prologue (pc)
119 CORE_ADDR pc;
120 {
121 unsigned long op;
122 unsigned short op1, op2;
123
124 if (target_read_memory (pc, (char *)&op, 4))
125 return pc; /* Can't access it -- assume no prologue. */
126
127 while (1)
128 {
129 op = read_memory_integer (pc, 4);
130 if ((op & 0xC0000000) == 0xC0000000)
131 {
132 /* long instruction */
133 if ( ((op & 0x3FFF0000) != 0x01FF0000) && /* add3 sp,sp,n */
134 ((op & 0x3F0F0000) != 0x340F0000) && /* st rn, @(offset,sp) */
135 ((op & 0x3F1F0000) != 0x350F0000)) /* st2w rn, @(offset,sp) */
136 break;
137 }
138 else
139 {
140 /* short instructions */
141 op1 = (op & 0x3FFF8000) >> 15;
142 op2 = op & 0x7FFF;
143 if (!check_prologue(op1) || !check_prologue(op2))
144 break;
145 }
146 pc += 4;
147 }
148 return pc;
149 }
150
151 /* Given a GDB frame, determine the address of the calling function's frame.
152 This will be used to create a new GDB frame struct, and then
153 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
154
155 For us, the frame address is its stack pointer value, so we look up
156 the function prologue to determine the caller's sp value, and return it. */
157
158 CORE_ADDR
159 d10v_frame_chain (frame)
160 struct frame_info *frame;
161 {
162 struct frame_saved_regs fsr;
163 /* printf("frame_chain %x\n",frame->frame); */
164 d10v_frame_find_saved_regs (frame, &fsr);
165 /* printf("pc=%x\n",fsr.regs[PC_REGNUM]);
166 printf("fp=%x (%x)\n",fsr.regs[FP_REGNUM],read_memory_integer(fsr.regs[FP_REGNUM],2) & 0xffff); */
167 return read_memory_integer(fsr.regs[FP_REGNUM],2) & 0xffff;
168 }
169
170 static int next_addr;
171
172 static int
173 prologue_find_regs (op, fsr, addr)
174 unsigned short op;
175 struct frame_saved_regs *fsr;
176 CORE_ADDR addr;
177 {
178 int n;
179
180 /* st rn, @-sp */
181 if ((op & 0x7E1F) == 0x6C1F)
182 {
183 n = (op & 0x1E0) >> 5;
184 next_addr -= 2;
185 fsr->regs[n] = next_addr;
186 return 1;
187 }
188
189 /* st2w rn, @-sp */
190 else if ((op & 0x7E3F) == 0x6E1F)
191 {
192 n = (op & 0x1E0) >> 5;
193 next_addr -= 4;
194 fsr->regs[n] = next_addr;
195 fsr->regs[n+1] = next_addr+2;
196 return 1;
197 }
198
199 /* subi sp, n */
200 if ((op & 0x7FE1) == 0x01E1)
201 {
202 n = (op & 0x1E) >> 1;
203 if (n == 0)
204 n = 16;
205 next_addr -= n;
206 return 1;
207 }
208
209 /* mv r11, sp */
210 if (op == 0x417E)
211 return 1;
212
213 /* nop */
214 if (op == 0x5E00)
215 return 1;
216
217 /* st rn, @sp */
218 if ((op & 0x7E1F) == 0x681E)
219 {
220 n = (op & 0x1E0) >> 5;
221 fsr->regs[n] = next_addr;
222 return 1;
223 }
224
225 /* st2w rn, @sp */
226 if ((op & 0x7E3F) == 0x3A1E)
227 {
228 n = (op & 0x1E0) >> 5;
229 fsr->regs[n] = next_addr;
230 fsr->regs[n+1] = next_addr+2;
231 return 1;
232 }
233
234 return 0;
235 }
236
237 /* Put here the code to store, into a struct frame_saved_regs, the
238 addresses of the saved registers of frame described by FRAME_INFO.
239 This includes special registers such as pc and fp saved in special
240 ways in the stack frame. sp is even more special: the address we
241 return for it IS the sp for the next frame. */
242 void
243 d10v_frame_find_saved_regs (fi, fsr)
244 struct frame_info *fi;
245 struct frame_saved_regs *fsr;
246 {
247 CORE_ADDR fp, pc;
248 unsigned long op;
249 unsigned short op1, op2;
250 int i;
251
252 fp = fi->frame;
253 memset (fsr, 0, sizeof (*fsr));
254 next_addr = 0;
255
256 pc = get_pc_function_start (fi->pc);
257
258 while (1)
259 {
260 op = read_memory_integer (pc, 4);
261 if ((op & 0xC0000000) == 0xC0000000)
262 {
263 /* long instruction */
264 if ((op & 0x3FFF0000) == 0x01FF0000)
265 {
266 /* add3 sp,sp,n */
267 short n = op & 0xFFFF;
268 next_addr += n;
269 }
270 else if ((op & 0x3F0F0000) == 0x340F0000)
271 {
272 /* st rn, @(offset,sp) */
273 short offset = op & 0xFFFF;
274 short n = (op >> 20) & 0xF;
275 fsr->regs[n] = next_addr + offset;
276 }
277 else if ((op & 0x3F1F0000) == 0x350F0000)
278 {
279 /* st2w rn, @(offset,sp) */
280 short offset = op & 0xFFFF;
281 short n = (op >> 20) & 0xF;
282 fsr->regs[n] = next_addr + offset;
283 fsr->regs[n+1] = next_addr + offset + 2;
284 }
285 else
286 break;
287 }
288 else
289 {
290 /* short instructions */
291 op1 = (op & 0x3FFF8000) >> 15;
292 op2 = op & 0x7FFF;
293 if (!prologue_find_regs(op1,fsr,pc) || !prologue_find_regs(op2,fsr,pc))
294 break;
295 }
296 pc += 4;
297 }
298
299 fi->size = -next_addr;
300 fi->return_pc = read_register (13);
301
302 for (i=0; i<NUM_REGS; i++)
303 if (fsr->regs[i])
304 {
305 fsr->regs[i] = fp - (next_addr - fsr->regs[i]);
306 /* printf("register %d = *(%x) = %x\n",i,fsr->regs[i],read_memory_integer((fsr->regs[i]) & 0xffff, 2)); */
307 }
308 }
309
310 void
311 d10v_init_extra_frame_info (fromleaf, fi)
312 int fromleaf;
313 struct frame_info *fi;
314 {
315 struct frame_saved_regs dummy;
316 /* printf("extra init %x next=%x pc=%x\n",fi->frame,fi->next,fi->pc); */
317
318 /* fi->pc = fi->next->return_pc; */
319 d10v_frame_find_saved_regs (fi, &dummy);
320 /* printf(" %x next=%x pc=%x\n",fi->frame,fi->next,fi->pc); */
321 }
322
323 static void
324 show_regs (args, from_tty)
325 char *args;
326 int from_tty;
327 {
328 long long num1, num2;
329 printf_filtered ("PC=%04x (0x%x) PSW=%04x RPT_S=%04x RPT_E=%04x RPT_C=%04x\n",
330 read_register (PC_REGNUM), read_register (PC_REGNUM) << 2,
331 read_register (PSW_REGNUM),
332 read_register (24),
333 read_register (25),
334 read_register (23));
335 printf_filtered ("R0-R7 %04x %04x %04x %04x %04x %04x %04x %04x\n",
336 read_register (0),
337 read_register (1),
338 read_register (2),
339 read_register (3),
340 read_register (4),
341 read_register (5),
342 read_register (6),
343 read_register (7));
344 printf_filtered ("R8-R15 %04x %04x %04x %04x %04x %04x %04x %04x\n",
345 read_register (8),
346 read_register (9),
347 read_register (10),
348 read_register (11),
349 read_register (12),
350 read_register (13),
351 read_register (14),
352 read_register (15));
353 read_register_gen (A0_REGNUM, (char *)&num1);
354 read_register_gen (A0_REGNUM+1, (char *)&num2);
355 printf_filtered ("A0-A1 %010llx %010llx\n",num1, num2);
356 }
357
358 void
359 _initialize_d10v_tdep ()
360 {
361 struct cmd_list_element *c;
362 tm_print_insn = print_insn_d10v;
363 add_com ("regs", class_vars, show_regs, "Print all registers");
364 }
365
366 CORE_ADDR
367 d10v_read_register_pid (regno, pid)
368 int regno, pid;
369 {
370 int save_pid;
371 CORE_ADDR retval;
372
373 if (pid == inferior_pid)
374 return (read_register(regno)) << 2;
375
376 save_pid = inferior_pid;
377 inferior_pid = pid;
378 retval = read_register (regno);
379 inferior_pid = save_pid;
380 return (retval << 2);
381 }
382
383 void
384 d10v_write_register_pid (regno, val, pid)
385 int regno;
386 LONGEST val;
387 int pid;
388 {
389 int save_pid;
390
391 val >>= 2;
392
393 if (pid == inferior_pid)
394 {
395 write_register (regno, val);
396 return;
397 }
398
399 save_pid = inferior_pid;
400 inferior_pid = pid;
401 write_register (regno, val);
402 inferior_pid = save_pid;
403 }
This page took 0.03732 seconds and 4 git commands to generate.