* ehopt.c: New file.
[deliverable/binutils-gdb.git] / gdb / d10v-tdep.c
CommitLineData
a9b9b407
SS
1/* Target-dependent code for Mitsubishi D10V, for GDB.
2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3
7b3fa778 4This file is part of GDB.
a9b9b407 5
7b3fa778
MH
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.
a9b9b407 10
7b3fa778
MH
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.
a9b9b407 15
7b3fa778
MH
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20/* Contributed by Martin Hunt, hunt@cygnus.com */
21
22#include "defs.h"
23#include "frame.h"
24#include "obstack.h"
25#include "symtab.h"
26#include "gdbtypes.h"
27#include "gdbcmd.h"
28#include "gdbcore.h"
81dc176f 29#include "gdb_string.h"
7b3fa778
MH
30#include "value.h"
31#include "inferior.h"
32#include "dis-asm.h"
3b1af95c
MH
33#include "symfile.h"
34#include "objfiles.h"
7b3fa778 35
a9b9b407
SS
36void d10v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
37 struct frame_saved_regs *fsr));
19414cdf 38static void d10v_pop_dummy_frame PARAMS ((struct frame_info *fi));
e05bda9f 39
a9b9b407
SS
40/* Discard from the stack the innermost frame, restoring all saved
41 registers. */
e05bda9f 42
7b3fa778
MH
43void
44d10v_pop_frame ()
45{
e05bda9f 46 struct frame_info *frame = get_current_frame ();
b70b03b0 47 CORE_ADDR fp;
e05bda9f
MH
48 int regnum;
49 struct frame_saved_regs fsr;
50 char raw_buffer[8];
51
b70b03b0 52 fp = FRAME_FP (frame);
19414cdf
MH
53 if (frame->dummy)
54 {
55 d10v_pop_dummy_frame(frame);
56 return;
57 }
58
e05bda9f
MH
59 /* fill out fsr with the address of where each */
60 /* register was stored in the frame */
61 get_frame_saved_regs (frame, &fsr);
62
e05bda9f
MH
63 /* now update the current registers with the old values */
64 for (regnum = A0_REGNUM; regnum < A0_REGNUM+2 ; regnum++)
65 {
66 if (fsr.regs[regnum])
67 {
81dc176f 68 read_memory (fsr.regs[regnum], raw_buffer, 8);
e05bda9f
MH
69 write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 8);
70 }
71 }
72 for (regnum = 0; regnum < SP_REGNUM; regnum++)
73 {
74 if (fsr.regs[regnum])
75 {
81dc176f 76 write_register (regnum, read_memory_unsigned_integer (fsr.regs[regnum], 2));
e05bda9f
MH
77 }
78 }
79 if (fsr.regs[PSW_REGNUM])
80 {
81dc176f 81 write_register (PSW_REGNUM, read_memory_unsigned_integer (fsr.regs[PSW_REGNUM], 2));
e05bda9f
MH
82 }
83
b70b03b0
MH
84 write_register (PC_REGNUM, read_register(13));
85 write_register (SP_REGNUM, fp + frame->size);
86 target_store_registers (-1);
e05bda9f
MH
87 flush_cached_frames ();
88}
89
90static int
91check_prologue (op)
92 unsigned short op;
93{
94 /* st rn, @-sp */
95 if ((op & 0x7E1F) == 0x6C1F)
96 return 1;
97
98 /* st2w rn, @-sp */
99 if ((op & 0x7E3F) == 0x6E1F)
100 return 1;
101
102 /* subi sp, n */
103 if ((op & 0x7FE1) == 0x01E1)
104 return 1;
105
106 /* mv r11, sp */
107 if (op == 0x417E)
108 return 1;
109
110 /* nop */
111 if (op == 0x5E00)
112 return 1;
113
114 /* st rn, @sp */
115 if ((op & 0x7E1F) == 0x681E)
116 return 1;
117
118 /* st2w rn, @sp */
119 if ((op & 0x7E3F) == 0x3A1E)
120 return 1;
121
e05bda9f 122 return 0;
7b3fa778
MH
123}
124
125CORE_ADDR
e05bda9f
MH
126d10v_skip_prologue (pc)
127 CORE_ADDR pc;
7b3fa778 128{
e05bda9f
MH
129 unsigned long op;
130 unsigned short op1, op2;
d716b33d
MH
131 CORE_ADDR func_addr, func_end;
132 struct symtab_and_line sal;
e05bda9f 133
d716b33d
MH
134 /* If we have line debugging information, then the end of the */
135 /* prologue should the first assembly instruction of the first source line */
136 if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
137 {
138 sal = find_pc_line (func_addr, 0);
294f72b2 139 if ( sal.end && sal.end < func_end)
d716b33d
MH
140 return sal.end;
141 }
142
e05bda9f
MH
143 if (target_read_memory (pc, (char *)&op, 4))
144 return pc; /* Can't access it -- assume no prologue. */
145
146 while (1)
147 {
81dc176f 148 op = (unsigned long)read_memory_integer (pc, 4);
e05bda9f
MH
149 if ((op & 0xC0000000) == 0xC0000000)
150 {
151 /* long instruction */
152 if ( ((op & 0x3FFF0000) != 0x01FF0000) && /* add3 sp,sp,n */
153 ((op & 0x3F0F0000) != 0x340F0000) && /* st rn, @(offset,sp) */
154 ((op & 0x3F1F0000) != 0x350F0000)) /* st2w rn, @(offset,sp) */
155 break;
156 }
157 else
158 {
159 /* short instructions */
21260fe1
MH
160 if ((op & 0xC0000000) == 0x80000000)
161 {
162 op2 = (op & 0x3FFF8000) >> 15;
163 op1 = op & 0x7FFF;
164 }
165 else
166 {
167 op1 = (op & 0x3FFF8000) >> 15;
168 op2 = op & 0x7FFF;
169 }
170 if (check_prologue(op1))
171 {
172 if (!check_prologue(op2))
173 {
174 /* if the previous opcode was really part of the prologue */
175 /* and not just a NOP, then we want to break after both instructions */
176 if (op1 != 0x5E00)
177 pc += 4;
178 break;
179 }
180 }
181 else
e05bda9f
MH
182 break;
183 }
184 pc += 4;
185 }
186 return pc;
7b3fa778 187}
19414cdf 188
e05bda9f
MH
189/* Given a GDB frame, determine the address of the calling function's frame.
190 This will be used to create a new GDB frame struct, and then
191 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
81dc176f 192*/
e05bda9f 193
7b3fa778
MH
194CORE_ADDR
195d10v_frame_chain (frame)
196 struct frame_info *frame;
197{
e05bda9f 198 struct frame_saved_regs fsr;
3b1af95c 199
e05bda9f 200 d10v_frame_find_saved_regs (frame, &fsr);
3b1af95c 201
77636dea 202 if (frame->return_pc == IMEM_START || inside_entry_file(frame->return_pc))
21260fe1
MH
203 return (CORE_ADDR)0;
204
3b1af95c
MH
205 if (!fsr.regs[FP_REGNUM])
206 {
21260fe1
MH
207 if (!fsr.regs[SP_REGNUM] || fsr.regs[SP_REGNUM] == STACK_START)
208 return (CORE_ADDR)0;
209
210 return fsr.regs[SP_REGNUM];
3b1af95c 211 }
21260fe1
MH
212
213 if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM],2))
214 return (CORE_ADDR)0;
215
216 return read_memory_unsigned_integer(fsr.regs[FP_REGNUM],2)| DMEM_START;
7b3fa778
MH
217}
218
21260fe1 219static int next_addr, uses_frame;
e05bda9f
MH
220
221static int
222prologue_find_regs (op, fsr, addr)
223 unsigned short op;
224 struct frame_saved_regs *fsr;
225 CORE_ADDR addr;
226{
227 int n;
228
229 /* st rn, @-sp */
230 if ((op & 0x7E1F) == 0x6C1F)
231 {
232 n = (op & 0x1E0) >> 5;
233 next_addr -= 2;
234 fsr->regs[n] = next_addr;
235 return 1;
236 }
237
238 /* st2w rn, @-sp */
239 else if ((op & 0x7E3F) == 0x6E1F)
240 {
241 n = (op & 0x1E0) >> 5;
242 next_addr -= 4;
243 fsr->regs[n] = next_addr;
244 fsr->regs[n+1] = next_addr+2;
245 return 1;
246 }
247
248 /* subi sp, n */
249 if ((op & 0x7FE1) == 0x01E1)
250 {
251 n = (op & 0x1E) >> 1;
252 if (n == 0)
253 n = 16;
254 next_addr -= n;
255 return 1;
256 }
257
258 /* mv r11, sp */
259 if (op == 0x417E)
21260fe1
MH
260 {
261 uses_frame = 1;
3b1af95c 262 return 1;
21260fe1 263 }
e05bda9f
MH
264
265 /* nop */
266 if (op == 0x5E00)
267 return 1;
268
269 /* st rn, @sp */
270 if ((op & 0x7E1F) == 0x681E)
271 {
272 n = (op & 0x1E0) >> 5;
273 fsr->regs[n] = next_addr;
274 return 1;
275 }
276
277 /* st2w rn, @sp */
278 if ((op & 0x7E3F) == 0x3A1E)
279 {
280 n = (op & 0x1E0) >> 5;
281 fsr->regs[n] = next_addr;
282 fsr->regs[n+1] = next_addr+2;
283 return 1;
284 }
285
286 return 0;
287}
288
7b3fa778
MH
289/* Put here the code to store, into a struct frame_saved_regs, the
290 addresses of the saved registers of frame described by FRAME_INFO.
291 This includes special registers such as pc and fp saved in special
292 ways in the stack frame. sp is even more special: the address we
293 return for it IS the sp for the next frame. */
294void
295d10v_frame_find_saved_regs (fi, fsr)
296 struct frame_info *fi;
297 struct frame_saved_regs *fsr;
e05bda9f
MH
298{
299 CORE_ADDR fp, pc;
300 unsigned long op;
301 unsigned short op1, op2;
302 int i;
303
304 fp = fi->frame;
305 memset (fsr, 0, sizeof (*fsr));
306 next_addr = 0;
307
308 pc = get_pc_function_start (fi->pc);
309
21260fe1 310 uses_frame = 0;
e05bda9f
MH
311 while (1)
312 {
81dc176f 313 op = (unsigned long)read_memory_integer (pc, 4);
e05bda9f
MH
314 if ((op & 0xC0000000) == 0xC0000000)
315 {
316 /* long instruction */
317 if ((op & 0x3FFF0000) == 0x01FF0000)
318 {
319 /* add3 sp,sp,n */
320 short n = op & 0xFFFF;
321 next_addr += n;
322 }
323 else if ((op & 0x3F0F0000) == 0x340F0000)
324 {
325 /* st rn, @(offset,sp) */
326 short offset = op & 0xFFFF;
327 short n = (op >> 20) & 0xF;
328 fsr->regs[n] = next_addr + offset;
329 }
330 else if ((op & 0x3F1F0000) == 0x350F0000)
331 {
332 /* st2w rn, @(offset,sp) */
333 short offset = op & 0xFFFF;
334 short n = (op >> 20) & 0xF;
335 fsr->regs[n] = next_addr + offset;
336 fsr->regs[n+1] = next_addr + offset + 2;
337 }
338 else
339 break;
340 }
341 else
342 {
343 /* short instructions */
21260fe1
MH
344 if ((op & 0xC0000000) == 0x80000000)
345 {
346 op2 = (op & 0x3FFF8000) >> 15;
347 op1 = op & 0x7FFF;
348 }
349 else
350 {
351 op1 = (op & 0x3FFF8000) >> 15;
352 op2 = op & 0x7FFF;
353 }
e05bda9f
MH
354 if (!prologue_find_regs(op1,fsr,pc) || !prologue_find_regs(op2,fsr,pc))
355 break;
356 }
357 pc += 4;
358 }
359
360 fi->size = -next_addr;
e05bda9f 361
21260fe1
MH
362 if (!(fp & 0xffff))
363 fp = read_register(SP_REGNUM) | DMEM_START;
364
3b1af95c 365 for (i=0; i<NUM_REGS-1; i++)
e05bda9f
MH
366 if (fsr->regs[i])
367 {
368 fsr->regs[i] = fp - (next_addr - fsr->regs[i]);
e05bda9f 369 }
81dc176f 370
21260fe1 371 if (fsr->regs[LR_REGNUM])
77636dea 372 fi->return_pc = (read_memory_unsigned_integer(fsr->regs[LR_REGNUM],2) << 2) | IMEM_START;
81dc176f 373 else
77636dea 374 fi->return_pc = (read_register(LR_REGNUM) << 2) | IMEM_START;
21260fe1 375
3b1af95c 376 /* th SP is not normally (ever?) saved, but check anyway */
b70b03b0 377 if (!fsr->regs[SP_REGNUM])
3b1af95c
MH
378 {
379 /* if the FP was saved, that means the current FP is valid, */
380 /* otherwise, it isn't being used, so we use the SP instead */
21260fe1 381 if (uses_frame)
3b1af95c
MH
382 fsr->regs[SP_REGNUM] = read_register(FP_REGNUM) + fi->size;
383 else
21260fe1
MH
384 {
385 fsr->regs[SP_REGNUM] = fp + fi->size;
386 fi->frameless = 1;
387 fsr->regs[FP_REGNUM] = 0;
388 }
3b1af95c 389 }
7b3fa778
MH
390}
391
392void
393d10v_init_extra_frame_info (fromleaf, fi)
394 int fromleaf;
395 struct frame_info *fi;
396{
397 struct frame_saved_regs dummy;
21260fe1 398 d10v_frame_find_saved_regs (fi, &dummy);
7b3fa778
MH
399}
400
401static void
402show_regs (args, from_tty)
403 char *args;
404 int from_tty;
405{
77636dea 406 LONGEST num1, num2;
7b3fa778 407 printf_filtered ("PC=%04x (0x%x) PSW=%04x RPT_S=%04x RPT_E=%04x RPT_C=%04x\n",
21260fe1 408 read_register (PC_REGNUM), (read_register (PC_REGNUM) << 2) + IMEM_START,
7b3fa778
MH
409 read_register (PSW_REGNUM),
410 read_register (24),
411 read_register (25),
412 read_register (23));
413 printf_filtered ("R0-R7 %04x %04x %04x %04x %04x %04x %04x %04x\n",
414 read_register (0),
415 read_register (1),
416 read_register (2),
417 read_register (3),
418 read_register (4),
419 read_register (5),
420 read_register (6),
421 read_register (7));
422 printf_filtered ("R8-R15 %04x %04x %04x %04x %04x %04x %04x %04x\n",
423 read_register (8),
424 read_register (9),
425 read_register (10),
426 read_register (11),
427 read_register (12),
428 read_register (13),
429 read_register (14),
430 read_register (15));
19414cdf
MH
431 printf_filtered ("IMAP0 %04x IMAP1 %04x DMAP %04x\n",
432 read_register (IMAP0_REGNUM),
433 read_register (IMAP1_REGNUM),
434 read_register (DMAP_REGNUM));
7b3fa778
MH
435 read_register_gen (A0_REGNUM, (char *)&num1);
436 read_register_gen (A0_REGNUM+1, (char *)&num2);
437 printf_filtered ("A0-A1 %010llx %010llx\n",num1, num2);
81dc176f 438}
7b3fa778 439
19414cdf
MH
440static CORE_ADDR
441d10v_xlate_addr (addr)
442 int addr;
7b3fa778 443{
19414cdf
MH
444 int imap;
445
446 if (addr < 0x20000)
447 imap = (int)read_register(IMAP0_REGNUM);
448 else
449 imap = (int)read_register(IMAP1_REGNUM);
7b3fa778 450
19414cdf
MH
451 if (imap & 0x1000)
452 return (CORE_ADDR)(addr + 0x1000000);
453 return (CORE_ADDR)(addr + (imap & 0xff)*0x20000);
454}
455
456
457CORE_ADDR
458d10v_read_pc (pid)
459 int pid;
460{
461 int save_pid, retval;
7b3fa778
MH
462
463 save_pid = inferior_pid;
464 inferior_pid = pid;
19414cdf 465 retval = (int)read_register (PC_REGNUM);
7b3fa778 466 inferior_pid = save_pid;
19414cdf 467 return d10v_xlate_addr(retval << 2);
7b3fa778
MH
468}
469
470void
19414cdf 471d10v_write_pc (val, pid)
21260fe1 472 CORE_ADDR val;
7b3fa778
MH
473 int pid;
474{
475 int save_pid;
476
7b3fa778
MH
477 save_pid = inferior_pid;
478 inferior_pid = pid;
19414cdf 479 write_register (PC_REGNUM, (val & 0x3ffff) >> 2);
7b3fa778
MH
480 inferior_pid = save_pid;
481}
3b1af95c 482
19414cdf 483CORE_ADDR
21260fe1 484d10v_read_sp ()
19414cdf 485{
21260fe1 486 return (read_register(SP_REGNUM) | DMEM_START);
19414cdf
MH
487}
488
489void
21260fe1
MH
490d10v_write_sp (val)
491 CORE_ADDR val;
19414cdf 492{
21260fe1 493 write_register (SP_REGNUM, (LONGEST)(val & 0xffff));
19414cdf 494}
3b1af95c 495
77636dea
FF
496void
497d10v_write_fp (val)
498 CORE_ADDR val;
499{
500 write_register (FP_REGNUM, (LONGEST)(val & 0xffff));
501}
502
503CORE_ADDR
504d10v_read_fp ()
505{
506 return (read_register(FP_REGNUM) | DMEM_START);
507}
508
21260fe1 509CORE_ADDR
3b1af95c
MH
510d10v_fix_call_dummy (dummyname, start_sp, fun, nargs, args, type, gcc_p)
511 char *dummyname;
512 CORE_ADDR start_sp;
513 CORE_ADDR fun;
514 int nargs;
515 value_ptr *args;
516 struct type *type;
517 int gcc_p;
518{
21260fe1 519 int regnum;
3b1af95c
MH
520 CORE_ADDR sp;
521 char buffer[MAX_REGISTER_RAW_SIZE];
19414cdf 522 struct frame_info *frame = get_current_frame ();
81a6f5b2 523 frame->dummy = start_sp;
21260fe1
MH
524 start_sp |= DMEM_START;
525
3b1af95c 526 sp = start_sp;
21260fe1 527 for (regnum = 0; regnum < NUM_REGS; regnum++)
3b1af95c 528 {
21260fe1 529 sp -= REGISTER_RAW_SIZE(regnum);
3b1af95c
MH
530 store_address (buffer, REGISTER_RAW_SIZE(regnum), read_register(regnum));
531 write_memory (sp, buffer, REGISTER_RAW_SIZE(regnum));
3b1af95c 532 }
21260fe1 533 write_register (SP_REGNUM, (LONGEST)(sp & 0xffff));
19414cdf 534 /* now we need to load LR with the return address */
21260fe1
MH
535 write_register (LR_REGNUM, (LONGEST)(d10v_call_dummy_address() & 0xffff) >> 2);
536 return sp;
3b1af95c
MH
537}
538
19414cdf
MH
539static void
540d10v_pop_dummy_frame (fi)
541 struct frame_info *fi;
542{
81a6f5b2 543 CORE_ADDR sp = fi->dummy;
21260fe1
MH
544 int regnum;
545
81a6f5b2 546 for (regnum = 0; regnum < NUM_REGS; regnum++)
19414cdf 547 {
81a6f5b2 548 sp -= REGISTER_RAW_SIZE(regnum);
21260fe1 549 write_register(regnum, read_memory_unsigned_integer (sp, REGISTER_RAW_SIZE(regnum)));
19414cdf 550 }
81a6f5b2 551 flush_cached_frames (); /* needed? */
19414cdf
MH
552}
553
554
3b1af95c
MH
555CORE_ADDR
556d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
557 int nargs;
558 value_ptr *args;
559 CORE_ADDR sp;
560 int struct_return;
561 CORE_ADDR struct_addr;
562{
81a6f5b2
MH
563 int i, len, index=0, regnum=2;
564 char buffer[4], *contents;
19414cdf 565 LONGEST val;
81a6f5b2
MH
566 CORE_ADDR ptrs[10];
567
568 /* Pass 1. Put all large args on stack */
3b1af95c
MH
569 for (i = 0; i < nargs; i++)
570 {
571 value_ptr arg = args[i];
572 struct type *arg_type = check_typedef (VALUE_TYPE (arg));
81a6f5b2
MH
573 len = TYPE_LENGTH (arg_type);
574 contents = VALUE_CONTENTS(arg);
81a6f5b2
MH
575 if (len > 4)
576 {
577 /* put on stack and pass pointers */
578 sp -= len;
579 write_memory (sp, contents, len);
580 ptrs[index++] = sp;
3b1af95c 581 }
81a6f5b2
MH
582 }
583
584 index = 0;
585
586 for (i = 0; i < nargs; i++)
587 {
588 value_ptr arg = args[i];
589 struct type *arg_type = check_typedef (VALUE_TYPE (arg));
3b1af95c 590 len = TYPE_LENGTH (arg_type);
81a6f5b2
MH
591 if (len > 4)
592 {
593 /* use a pointer to previously saved data */
594 if (regnum < 6)
595 write_register (regnum++, ptrs[index++]);
596 else
597 {
598 /* no more registers available. put it on the stack */
599 sp -= 2;
600 store_address (buffer, 2, ptrs[index++]);
601 write_memory (sp, buffer, 2);
602 }
603 }
604 else
605 {
77636dea
FF
606 contents = VALUE_CONTENTS(arg);
607 val = extract_signed_integer (contents, len);
608 /* printf("push: type=%d len=%d val=0x%x\n",arg_type->code,len,val); */
609 if (arg_type->code == TYPE_CODE_PTR)
610 {
611 if ( (val & 0x3000000) == 0x1000000)
612 {
613 /* function pointer */
614 val = (val & 0x3FFFF) >> 2;
615 len = 2;
616 }
617 else
618 {
619 /* data pointer */
620 val &= 0xFFFF;
621 len = 2;
622 }
623 }
624
81a6f5b2
MH
625 if (regnum < 6 )
626 {
627 if (len == 4)
628 write_register (regnum++, val>>16);
629 write_register (regnum++, val & 0xffff);
630 }
631 else
632 {
633 sp -= len;
634 store_address (buffer, len, val);
635 write_memory (sp, buffer, len);
636 }
637 }
3b1af95c 638 }
21260fe1 639 return sp;
3b1af95c
MH
640}
641
19414cdf 642
81a6f5b2
MH
643/* pick an out-of-the-way place to set the return value */
644/* for an inferior function call. The link register is set to this */
645/* value and a momentary breakpoint is set there. When the breakpoint */
646/* is hit, the dummy frame is popped and the previous environment is */
647/* restored. */
648
3b1af95c
MH
649CORE_ADDR
650d10v_call_dummy_address ()
651{
19414cdf 652 CORE_ADDR entry;
3b1af95c
MH
653 struct minimal_symbol *sym;
654
655 entry = entry_point_address ();
656
657 if (entry != 0)
19414cdf 658 return entry;
3b1af95c
MH
659
660 sym = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
661
662 if (!sym || MSYMBOL_TYPE (sym) != mst_text)
19414cdf 663 return 0;
3b1af95c 664 else
19414cdf 665 return SYMBOL_VALUE_ADDRESS (sym);
3b1af95c
MH
666}
667
668/* Given a return value in `regbuf' with a type `valtype',
669 extract and copy its value into `valbuf'. */
670
671void
672d10v_extract_return_value (valtype, regbuf, valbuf)
673 struct type *valtype;
674 char regbuf[REGISTER_BYTES];
675 char *valbuf;
676{
77636dea
FF
677 int len;
678 /* printf("RET: VALTYPE=%d len=%d r2=0x%x\n",valtype->code, TYPE_LENGTH (valtype), (int)*(short *)(regbuf+REGISTER_BYTE(2))); */
679 if (valtype->code == TYPE_CODE_PTR)
680 {
681 short snum;
682 snum = (short)extract_address (regbuf + REGISTER_BYTE (2), 2);
683 store_address ( valbuf, 4, D10V_MAKE_DADDR(snum));
684 }
685 else
686 {
687 len = TYPE_LENGTH (valtype);
688 if (len == 1)
689 {
690 unsigned short c = extract_unsigned_integer (regbuf + REGISTER_BYTE (2), 2);
691 store_unsigned_integer (valbuf, 1, c);
692 }
693 else
694 memcpy (valbuf, regbuf + REGISTER_BYTE (2), len);
695 }
48712b30
SS
696}
697
698/* The following code implements access to, and display of, the D10V's
699 instruction trace buffer. The buffer consists of 64K or more
700 4-byte words of data, of which each words includes an 8-bit count,
a9b9b407 701 an 8-bit segment number, and a 16-bit instruction address.
48712b30
SS
702
703 In theory, the trace buffer is continuously capturing instruction
704 data that the CPU presents on its "debug bus", but in practice, the
705 ROMified GDB stub only enables tracing when it continues or steps
706 the program, and stops tracing when the program stops; so it
707 actually works for GDB to read the buffer counter out of memory and
708 then read each trace word. The counter records where the tracing
709 stops, but there is no record of where it started, so we remember
710 the PC when we resumed and then search backwards in the trace
711 buffer for a word that includes that address. This is not perfect,
712 because you will miss trace data if the resumption PC is the target
713 of a branch. (The value of the buffer counter is semi-random, any
714 trace data from a previous program stop is gone.) */
715
716/* The address of the last word recorded in the trace buffer. */
717
718#define DBBC_ADDR (0xd80000)
719
720/* The base of the trace buffer, at least for the "Board_0". */
721
722#define TRACE_BUFFER_BASE (0xf40000)
723
724static void trace_command PARAMS ((char *, int));
725
726static void untrace_command PARAMS ((char *, int));
727
728static void trace_info PARAMS ((char *, int));
729
730static void tdisassemble_command PARAMS ((char *, int));
731
732static void display_trace PARAMS ((int, int));
733
734/* True when instruction traces are being collected. */
735
736static int tracing;
737
738/* Remembered PC. */
739
740static CORE_ADDR last_pc;
741
a9b9b407
SS
742/* True when trace output should be displayed whenever program stops. */
743
48712b30
SS
744static int trace_display;
745
a9b9b407
SS
746/* True when trace listing should include source lines. */
747
748static int default_trace_show_source = 1;
749
48712b30
SS
750struct trace_buffer {
751 int size;
752 short *counts;
753 CORE_ADDR *addrs;
754} trace_data;
755
756static void
757trace_command (args, from_tty)
758 char *args;
759 int from_tty;
760{
761 /* Clear the host-side trace buffer, allocating space if needed. */
762 trace_data.size = 0;
763 if (trace_data.counts == NULL)
764 trace_data.counts = (short *) xmalloc (65536 * sizeof(short));
765 if (trace_data.addrs == NULL)
766 trace_data.addrs = (CORE_ADDR *) xmalloc (65536 * sizeof(CORE_ADDR));
767
768 tracing = 1;
769
770 printf_filtered ("Tracing is now on.\n");
771}
772
773static void
774untrace_command (args, from_tty)
775 char *args;
776 int from_tty;
777{
778 tracing = 0;
779
780 printf_filtered ("Tracing is now off.\n");
781}
782
783static void
784trace_info (args, from_tty)
785 char *args;
786 int from_tty;
787{
788 int i;
789
a9b9b407 790 if (trace_data.size)
48712b30 791 {
a9b9b407
SS
792 printf_filtered ("%d entries in trace buffer:\n", trace_data.size);
793
794 for (i = 0; i < trace_data.size; ++i)
795 {
796 printf_filtered ("%d: %d instruction%s at 0x%x\n",
797 i, trace_data.counts[i],
798 (trace_data.counts[i] == 1 ? "" : "s"),
799 trace_data.addrs[i]);
800 }
48712b30 801 }
a9b9b407
SS
802 else
803 printf_filtered ("No entries in trace buffer.\n");
48712b30
SS
804
805 printf_filtered ("Tracing is currently %s.\n", (tracing ? "on" : "off"));
806}
807
808/* Print the instruction at address MEMADDR in debugged memory,
809 on STREAM. Returns length of the instruction, in bytes. */
810
811static int
812print_insn (memaddr, stream)
813 CORE_ADDR memaddr;
814 GDB_FILE *stream;
815{
816 /* If there's no disassembler, something is very wrong. */
817 if (tm_print_insn == NULL)
818 abort ();
819
820 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
821 tm_print_insn_info.endian = BFD_ENDIAN_BIG;
822 else
823 tm_print_insn_info.endian = BFD_ENDIAN_LITTLE;
824 return (*tm_print_insn) (memaddr, &tm_print_insn_info);
825}
826
827void
828d10v_eva_prepare_to_trace ()
829{
830 if (!tracing)
831 return;
832
833 last_pc = read_register (PC_REGNUM);
834}
835
836/* Collect trace data from the target board and format it into a form
837 more useful for display. */
838
839void
840d10v_eva_get_trace_data ()
841{
842 int count, i, j, oldsize;
843 int trace_addr, trace_seg, trace_cnt, next_cnt;
844 unsigned int last_trace, trace_word, next_word;
845 unsigned int *tmpspace;
846
847 if (!tracing)
848 return;
849
850 tmpspace = xmalloc (65536 * sizeof(unsigned int));
851
852 last_trace = read_memory_unsigned_integer (DBBC_ADDR, 2) << 2;
853
48712b30
SS
854 /* Collect buffer contents from the target, stopping when we reach
855 the word recorded when execution resumed. */
856
857 count = 0;
858 while (last_trace > 0)
859 {
860 QUIT;
861 trace_word =
862 read_memory_unsigned_integer (TRACE_BUFFER_BASE + last_trace, 4);
863 trace_addr = trace_word & 0xffff;
48712b30
SS
864 last_trace -= 4;
865 /* Ignore an apparently nonsensical entry. */
866 if (trace_addr == 0xffd5)
867 continue;
868 tmpspace[count++] = trace_word;
869 if (trace_addr == last_pc)
870 break;
871 if (count > 65535)
872 break;
873 }
874
875 /* Move the data to the host-side trace buffer, adjusting counts to
876 include the last instruction executed and transforming the address
877 into something that GDB likes. */
878
879 for (i = 0; i < count; ++i)
880 {
881 trace_word = tmpspace[i];
882 next_word = ((i == 0) ? 0 : tmpspace[i - 1]);
883 trace_addr = trace_word & 0xffff;
884 next_cnt = (next_word >> 24) & 0xff;
885 j = trace_data.size + count - i - 1;
886 trace_data.addrs[j] = (trace_addr << 2) + 0x1000000;
887 trace_data.counts[j] = next_cnt + 1;
888 }
889
890 oldsize = trace_data.size;
891 trace_data.size += count;
892
893 free (tmpspace);
894
48712b30
SS
895 if (trace_display)
896 display_trace (oldsize, trace_data.size);
897}
898
899static void
900tdisassemble_command (arg, from_tty)
901 char *arg;
902 int from_tty;
903{
904 int i, count;
905 CORE_ADDR low, high;
906 char *space_index;
907
908 if (!arg)
909 {
910 low = 0;
911 high = trace_data.size;
912 }
913 else if (!(space_index = (char *) strchr (arg, ' ')))
914 {
915 low = parse_and_eval_address (arg);
916 high = low + 5;
917 }
918 else
919 {
920 /* Two arguments. */
921 *space_index = '\0';
922 low = parse_and_eval_address (arg);
923 high = parse_and_eval_address (space_index + 1);
a9b9b407
SS
924 if (high < low)
925 high = low;
48712b30
SS
926 }
927
a9b9b407 928 printf_filtered ("Dump of trace from %d to %d:\n", low, high);
48712b30
SS
929
930 display_trace (low, high);
931
932 printf_filtered ("End of trace dump.\n");
933 gdb_flush (gdb_stdout);
934}
935
936static void
937display_trace (low, high)
938 int low, high;
939{
a9b9b407 940 int i, count, trace_show_source, first, suppress;
48712b30
SS
941 CORE_ADDR next_address;
942
a9b9b407
SS
943 trace_show_source = default_trace_show_source;
944 if (!have_full_symbols () && !have_partial_symbols())
945 {
946 trace_show_source = 0;
947 printf_filtered ("No symbol table is loaded. Use the \"file\" command.\n");
948 printf_filtered ("Trace will not display any source.\n");
949 }
950
951 first = 1;
952 suppress = 0;
48712b30
SS
953 for (i = low; i < high; ++i)
954 {
955 next_address = trace_data.addrs[i];
956 count = trace_data.counts[i];
957 while (count-- > 0)
958 {
959 QUIT;
a9b9b407
SS
960 if (trace_show_source)
961 {
962 struct symtab_and_line sal, sal_prev;
963
964 sal_prev = find_pc_line (next_address - 4, 0);
965 sal = find_pc_line (next_address, 0);
966
967 if (sal.symtab)
968 {
969 if (first || sal.line != sal_prev.line)
970 print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
971 suppress = 0;
972 }
973 else
974 {
975 if (!suppress)
976 /* FIXME-32x64--assumes sal.pc fits in long. */
977 printf_filtered ("No source file for address %s.\n",
978 local_hex_string((unsigned long) sal.pc));
979 suppress = 1;
980 }
981 }
982 first = 0;
48712b30
SS
983 print_address (next_address, gdb_stdout);
984 printf_filtered (":");
985 printf_filtered ("\t");
986 wrap_here (" ");
987 next_address = next_address + print_insn (next_address, gdb_stdout);
988 printf_filtered ("\n");
989 gdb_flush (gdb_stdout);
990 }
991 }
3b1af95c 992}
48712b30 993
a9b9b407
SS
994extern void (*target_resume_hook) PARAMS ((void));
995extern void (*target_wait_loop_hook) PARAMS ((void));
996
48712b30
SS
997void
998_initialize_d10v_tdep ()
999{
1000 tm_print_insn = print_insn_d10v;
1001
a9b9b407
SS
1002 target_resume_hook = d10v_eva_prepare_to_trace;
1003 target_wait_loop_hook = d10v_eva_get_trace_data;
1004
48712b30
SS
1005 add_com ("regs", class_vars, show_regs, "Print all registers");
1006
1007 add_com ("trace", class_support, trace_command,
1008 "Enable tracing of instruction execution.");
1009
1010 add_com ("untrace", class_support, untrace_command,
1011 "Disable tracing of instruction execution.");
1012
1013 add_com ("tdisassemble", class_vars, tdisassemble_command,
1014 "Disassemble the trace buffer.\n\
1015Two optional arguments specify a range of trace buffer entries\n\
1016as reported by info trace (NOT addresses!).");
1017
1018 add_info ("trace", trace_info,
1019 "Display info about the trace data buffer.");
1020
1021 add_show_from_set (add_set_cmd ("tracedisplay", no_class,
1022 var_integer, (char *)&trace_display,
1023 "Set automatic display of trace.\n", &setlist),
1024 &showlist);
a9b9b407
SS
1025 add_show_from_set (add_set_cmd ("tracesource", no_class,
1026 var_integer, (char *)&default_trace_show_source,
1027 "Set display of source code with trace.\n", &setlist),
1028 &showlist);
48712b30
SS
1029
1030}
This page took 0.111102 seconds and 4 git commands to generate.