2007-05-31 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / score-tdep.c
CommitLineData
27fd2f50
Q
1/* Target-dependent code for the S+core architecture, for GDB,
2 the GNU Debugger.
3
6aba47ca 4 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
27fd2f50
Q
5
6 Contributed by Qinwei (qinwei@sunnorth.com.cn)
7 Contributed by Ching-Peng Lin (cplin@sunplus.com)
8
9 This file is part of GDB.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 Boston, MA 02110-1301, USA. */
25
26#include "defs.h"
27#include "gdb_assert.h"
28#include "inferior.h"
29#include "symtab.h"
30#include "objfiles.h"
31#include "gdbcore.h"
32#include "target.h"
33#include "arch-utils.h"
34#include "regcache.h"
35#include "dis-asm.h"
36#include "frame-unwind.h"
37#include "frame-base.h"
38#include "trad-frame.h"
39#include "dwarf2-frame.h"
40#include "score-tdep.h"
41
42#define G_FLD(_i,_ms,_ls) (((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls)))
43#define RM_PBITS(_raw) ((G_FLD(_raw, 31, 16) << 15) | G_FLD(_raw, 14, 0))
44
45typedef struct{
46 unsigned int v;
47 unsigned int raw;
48 char is15;
49}inst_t;
50
51struct score_frame_cache
52{
53 CORE_ADDR base;
5e29c264 54 CORE_ADDR fp;
27fd2f50
Q
55 struct trad_frame_saved_reg *saved_regs;
56};
57
58#if 0
59/* If S+core GCC will generate these instructions in the prologue:
60
61 lw rx, imm1
62 addi rx, -imm2
63 mv! r2, rx
64
65 then .pdr section is used. */
66
67#define P_SIZE 8
68#define PI_SYM 0
69#define PI_R_MSK 1
70#define PI_R_OFF 2
71#define PI_R_LEF 4
72#define PI_F_OFF 5
73#define PI_F_REG 6
74#define PI_RAREG 7
75
76typedef struct frame_extra_info
77{
78 CORE_ADDR p_frame;
79 unsigned int pdr[P_SIZE];
80} extra_info_t;
81
82struct obj_priv
83{
84 bfd_size_type size;
85 char *contents;
86};
87
88static bfd *the_bfd;
89
90static int
91score_compare_pdr_entries (const void *a, const void *b)
92{
93 CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
94 CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
95 if (lhs < rhs)
96 return -1;
97 else if (lhs == rhs)
98 return 0;
99 else
100 return 1;
101}
102
103static void
104score_analyze_pdr_section (CORE_ADDR startaddr, CORE_ADDR pc,
105 struct frame_info *next_frame,
106 struct score_frame_cache *this_cache)
107{
108 struct symbol *sym;
109 struct obj_section *sec;
110 extra_info_t *fci_ext;
111 CORE_ADDR leaf_ra_stack_addr = -1;
112
113 gdb_assert (startaddr <= pc);
114 gdb_assert (this_cache != NULL);
115
116 fci_ext = frame_obstack_zalloc (sizeof (extra_info_t));
117 if ((sec = find_pc_section (pc)) == NULL)
118 {
5e29c264
Q
119 error ("Error: Can't find section in file:%s, line:%d!",
120 __FILE__, __LINE__);
27fd2f50
Q
121 return;
122 }
123
124 /* Anylyze .pdr section and get coresponding fields. */
125 {
126 static struct obj_priv *priv = NULL;
127
128 if (priv == NULL)
129 {
130 asection *bfdsec;
131 priv = obstack_alloc (&sec->objfile->objfile_obstack,
132 sizeof (struct obj_priv));
133 if ((bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr")))
134 {
135 priv->size = bfd_section_size (sec->objfile->obfd, bfdsec);
136 priv->contents = obstack_alloc (&sec->objfile->objfile_obstack,
137 priv->size);
138 bfd_get_section_contents (sec->objfile->obfd, bfdsec,
139 priv->contents, 0, priv->size);
140 the_bfd = sec->objfile->obfd;
141 qsort (priv->contents, priv->size / 32, 32,
142 score_compare_pdr_entries);
143 the_bfd = NULL;
144 }
145 else
146 priv->size = 0;
147 }
148 if (priv->size != 0)
149 {
150 int low = 0, mid, high = priv->size / 32;
151 char *ptr;
152 do
27fd2f50
Q
153 {
154 CORE_ADDR pdr_pc;
155 mid = (low + high) / 2;
156 ptr = priv->contents + mid * 32;
157 pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
158 pdr_pc += ANOFFSET (sec->objfile->section_offsets,
159 SECT_OFF_TEXT (sec->objfile));
160 if (pdr_pc == startaddr)
161 break;
162 if (pdr_pc > startaddr)
163 high = mid;
164 else
165 low = mid + 1;
166 }
167 while (low != high);
168
169 if (low != high)
170 {
171 gdb_assert (bfd_get_32 (sec->objfile->obfd, ptr) == startaddr);
172#define EXT_PDR(_pi) bfd_get_32(sec->objfile->obfd, ptr+((_pi)<<2))
173 fci_ext->pdr[PI_SYM] = EXT_PDR (PI_SYM);
174 fci_ext->pdr[PI_R_MSK] = EXT_PDR (PI_R_MSK);
175 fci_ext->pdr[PI_R_OFF] = EXT_PDR (PI_R_OFF);
176 fci_ext->pdr[PI_R_LEF] = EXT_PDR (PI_R_LEF);
177 fci_ext->pdr[PI_F_OFF] = EXT_PDR (PI_F_OFF);
178 fci_ext->pdr[PI_F_REG] = EXT_PDR (PI_F_REG);
179 fci_ext->pdr[PI_RAREG] = EXT_PDR (PI_RAREG);
180#undef EXT_PDR
181 }
182 }
183 }
184}
185#endif
186
5e29c264
Q
187#if 0
188/* Open these functions if build with simulator. */
189
190int
191score_target_can_use_watch (int type, int cnt, int othertype)
192{
193 if (strcmp (current_target.to_shortname, "sim") == 0)
194 {
195 return soc_gh_can_use_watch (type, cnt);
196 }
197 else
198 {
199 return (*current_target.to_can_use_hw_breakpoint) (type, cnt, othertype);
200 }
201}
202
203int
204score_stopped_by_watch (void)
205{
206 if (strcmp (current_target.to_shortname, "sim") == 0)
207 {
208 return soc_gh_stopped_by_watch ();
209 }
210 else
211 {
212 return (*current_target.to_stopped_by_watchpoint) ();
213 }
214}
215
216int
217score_target_insert_watchpoint (CORE_ADDR addr, int len, int type)
218{
219 if (strcmp (current_target.to_shortname, "sim") == 0)
220 {
221 return soc_gh_add_watch (addr, len, type);
222 }
223 else
224 {
225 return (*current_target.to_insert_watchpoint) (addr, len, type);
226 }
227}
228
229int
230score_target_remove_watchpoint (CORE_ADDR addr, int len, int type)
231{
232 if (strcmp (current_target.to_shortname, "sim") == 0)
233 {
234 return soc_gh_del_watch (addr, len, type);
235 }
236 else
237 {
238 return (*current_target.to_remove_watchpoint) (addr, len, type);
239 }
240}
241
242int
243score_target_insert_hw_breakpoint (struct bp_target_info * bp_tgt)
244{
245 if (strcmp (current_target.to_shortname, "sim") == 0)
246 {
247 return soc_gh_add_hardbp (bp_tgt->placed_address);
248 }
249 else
250 {
251 return (*current_target.to_insert_hw_breakpoint) (bp_tgt);
252 }
253}
254
255int
256score_target_remove_hw_breakpoint (struct bp_target_info * bp_tgt)
257{
258 if (strcmp (current_target.to_shortname, "sim") == 0)
259 {
260 return soc_gh_del_hardbp (bp_tgt->placed_address);
261 }
262 else
263 {
264 return (*current_target.to_remove_hw_breakpoint) (bp_tgt);
265 }
266}
267#endif
268
27fd2f50
Q
269static struct type *
270score_register_type (struct gdbarch *gdbarch, int regnum)
271{
272 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
273 return builtin_type_uint32;
274}
275
27fd2f50 276static CORE_ADDR
30244cd8 277score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
27fd2f50 278{
30244cd8 279 return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
27fd2f50
Q
280}
281
282static CORE_ADDR
30244cd8 283score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
27fd2f50 284{
30244cd8 285 return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
27fd2f50
Q
286}
287
288static const char *
289score_register_name (int regnum)
290{
291 const char *score_register_names[] = {
292 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
293 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
294 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
295 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
296
297 "PSR", "COND", "ECR", "EXCPVEC",
298 "CCR", "EPC", "EMA", "TLBLOCK",
299 "TLBPT", "PEADDR", "TLBRPT", "PEVN",
300 "PECTX", "LIMPFN", "LDMPFN", "PREV",
301 "DREG", "PC", "DSAVE", "COUNTER",
302 "LDCR", "STCR", "CEH", "CEL",
303 };
304
305 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
306 return score_register_names[regnum];
307}
308
309static int
310score_register_sim_regno (int regnum)
311{
312 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
313 return regnum;
314}
315
316static int
317score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
318{
4c6b5505 319 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
27fd2f50
Q
320 return print_insn_big_score (memaddr, info);
321 else
322 return print_insn_little_score (memaddr, info);
323}
324
325static const gdb_byte *
326score_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
327{
328 gdb_byte buf[SCORE_INSTLEN] = { 0 };
329 int ret;
330 unsigned int raw;
331
332 if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
333 {
5e29c264
Q
334 error ("Error: target_read_memory in file:%s, line:%d!",
335 __FILE__, __LINE__);
27fd2f50
Q
336 }
337 raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
338
4c6b5505 339 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
27fd2f50
Q
340 {
341 if (!(raw & 0x80008000))
342 {
343 /* 16bits instruction. */
344 static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
345 *pcptr &= ~0x1;
346 *lenptr = sizeof (big_breakpoint16);
347 return big_breakpoint16;
348 }
349 else
350 {
351 /* 32bits instruction. */
352 static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
353 *pcptr &= ~0x3;
354 *lenptr = sizeof (big_breakpoint32);
355 return big_breakpoint32;
356 }
357 }
358 else
359 {
360 if (!(raw & 0x80008000))
361 {
362 /* 16bits instruction. */
363 static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
364 *pcptr &= ~0x1;
365 *lenptr = sizeof (little_breakpoint16);
366 return little_breakpoint16;
367 }
368 else
369 {
370 /* 32bits instruction. */
371 static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
372 *pcptr &= ~0x3;
373 *lenptr = sizeof (little_breakpoint32);
374 return little_breakpoint32;
375 }
376 }
377}
378
379static CORE_ADDR
380score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
381{
382 return align_down (addr, 16);
383}
384
385static void
386score_xfer_register (struct regcache *regcache, int regnum, int length,
387 enum bfd_endian endian, gdb_byte *readbuf,
388 const gdb_byte *writebuf, int buf_offset)
389{
390 int reg_offset = 0;
391 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
392
393 switch (endian)
394 {
395 case BFD_ENDIAN_BIG:
396 reg_offset = SCORE_REGSIZE - length;
397 break;
398 case BFD_ENDIAN_LITTLE:
399 reg_offset = 0;
400 break;
401 case BFD_ENDIAN_UNKNOWN:
402 reg_offset = 0;
403 break;
404 default:
5e29c264
Q
405 error ("Error: score_xfer_register in file:%s, line:%d!",
406 __FILE__, __LINE__);
27fd2f50
Q
407 }
408
409 if (readbuf != NULL)
410 regcache_cooked_read_part (regcache, regnum, reg_offset, length,
411 readbuf + buf_offset);
412 if (writebuf != NULL)
413 regcache_cooked_write_part (regcache, regnum, reg_offset, length,
414 writebuf + buf_offset);
415}
416
417static enum return_value_convention
418score_return_value (struct gdbarch *gdbarch, struct type *type,
419 struct regcache *regcache,
420 gdb_byte * readbuf, const gdb_byte * writebuf)
421{
422 if (TYPE_CODE (type) == TYPE_CODE_STRUCT
423 || TYPE_CODE (type) == TYPE_CODE_UNION
424 || TYPE_CODE (type) == TYPE_CODE_ARRAY)
425 return RETURN_VALUE_STRUCT_CONVENTION;
426 else
427 {
428 int offset;
429 int regnum;
430 for (offset = 0, regnum = SCORE_A0_REGNUM;
431 offset < TYPE_LENGTH (type);
432 offset += SCORE_REGSIZE, regnum++)
433 {
434 int xfer = SCORE_REGSIZE;
435 if (offset + xfer > TYPE_LENGTH (type))
436 xfer = TYPE_LENGTH (type) - offset;
4c6b5505
UW
437 score_xfer_register (regcache, regnum, xfer,
438 gdbarch_byte_order (current_gdbarch),
27fd2f50
Q
439 readbuf, writebuf, offset);
440 }
441 return RETURN_VALUE_REGISTER_CONVENTION;
442 }
443}
444
445static struct frame_id
5e29c264
Q
446score_unwind_dummy_id (struct gdbarch *gdbarch,
447 struct frame_info *next_frame)
27fd2f50
Q
448{
449 return frame_id_build (
450 frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM),
451 frame_pc_unwind (next_frame));
452}
453
454static int
455score_type_needs_double_align (struct type *type)
456{
457 enum type_code typecode = TYPE_CODE (type);
458
5e29c264
Q
459 if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
460 || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
27fd2f50
Q
461 return 1;
462 else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
463 {
464 int i, n;
465
466 n = TYPE_NFIELDS (type);
467 for (i = 0; i < n; i++)
468 if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
469 return 1;
470 return 0;
471 }
472 return 0;
473}
474
475static CORE_ADDR
476score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
477 struct regcache *regcache, CORE_ADDR bp_addr,
478 int nargs, struct value **args, CORE_ADDR sp,
479 int struct_return, CORE_ADDR struct_addr)
480{
481 int argnum;
482 int argreg;
483 int arglen = 0;
484 CORE_ADDR stack_offset = 0;
485 CORE_ADDR addr = 0;
486
487 /* Step 1, Save RA. */
488 regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
489
490 /* Step 2, Make space on the stack for the args. */
491 struct_addr = align_down (struct_addr, 16);
492 sp = align_down (sp, 16);
493 for (argnum = 0; argnum < nargs; argnum++)
494 arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
495 SCORE_REGSIZE);
496 sp -= align_up (arglen, 16);
497
498 argreg = SCORE_BEGIN_ARG_REGNUM;
499
5e29c264
Q
500 /* Step 3, Check if struct return then save the struct address to
501 r4 and increase the stack_offset by 4. */
27fd2f50
Q
502 if (struct_return)
503 {
504 regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
505 stack_offset += SCORE_REGSIZE;
506 }
507
508 /* Step 4, Load arguments:
5e29c264
Q
509 If arg length is too long (> 4 bytes), then split the arg and
510 save every parts. */
27fd2f50
Q
511 for (argnum = 0; argnum < nargs; argnum++)
512 {
513 struct value *arg = args[argnum];
514 struct type *arg_type = check_typedef (value_type (arg));
27fd2f50
Q
515 enum type_code typecode = TYPE_CODE (arg_type);
516 const gdb_byte *val = value_contents (arg);
517 int downward_offset = 0;
1cfd2c3e
JB
518 int odd_sized_struct_p;
519 int arg_last_part_p = 0;
27fd2f50 520
1cfd2c3e
JB
521 arglen = TYPE_LENGTH (arg_type);
522 odd_sized_struct_p = (arglen > SCORE_REGSIZE
5e29c264 523 && arglen % SCORE_REGSIZE != 0);
27fd2f50
Q
524
525 /* If a arg should be aligned to 8 bytes (long long or double),
526 the value should be put to even register numbers. */
527 if (score_type_needs_double_align (arg_type))
528 {
529 if (argreg & 1)
530 argreg++;
531 }
532
533 /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
534 the default "downward"/"upward" method:
535
536 Example:
537
538 struct struc
539 {
540 char a; char b; char c;
541 } s = {'a', 'b', 'c'};
542
543 Big endian: s = {X, 'a', 'b', 'c'}
544 Little endian: s = {'a', 'b', 'c', X}
545
546 Where X is a hole. */
547
4c6b5505 548 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
27fd2f50
Q
549 && (typecode == TYPE_CODE_STRUCT
550 || typecode == TYPE_CODE_UNION)
551 && argreg > SCORE_LAST_ARG_REGNUM
552 && arglen < SCORE_REGSIZE)
553 downward_offset += (SCORE_REGSIZE - arglen);
554
555 while (arglen > 0)
556 {
557 int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
558 ULONGEST regval = extract_unsigned_integer (val, partial_len);
559
560 /* The last part of a arg should shift left when
4c6b5505
UW
561 gdbarch_byte_order is BFD_ENDIAN_BIG. */
562 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
27fd2f50
Q
563 && arg_last_part_p == 1
564 && (typecode == TYPE_CODE_STRUCT
565 || typecode == TYPE_CODE_UNION))
566 regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
567
568 /* Always increase the stack_offset and save args to stack. */
569 addr = sp + stack_offset + downward_offset;
570 write_memory (addr, val, partial_len);
571
572 if (argreg <= SCORE_LAST_ARG_REGNUM)
573 {
574 regcache_cooked_write_unsigned (regcache, argreg++, regval);
575 if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
576 arg_last_part_p = 1;
577 }
578
579 val += partial_len;
580 arglen -= partial_len;
581 stack_offset += align_up (partial_len, SCORE_REGSIZE);
582 }
583 }
584
585 /* Step 5, Save SP. */
586 regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
587
588 return sp;
589}
590
5e29c264
Q
591static char *
592score_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size)
593{
594 int ret;
595 char *memblock = NULL;
596
597 if (size < 0)
598 {
599 error ("Error: malloc size < 0 in file:%s, line:%d!",
600 __FILE__, __LINE__);
601 return NULL;
602 }
603 else if (size == 0)
604 return NULL;
605
606 memblock = (char *) xmalloc (size);
607 memset (memblock, 0, size);
608 ret = target_read_memory (addr & ~0x3, memblock, size);
609 if (ret)
610 {
611 error ("Error: target_read_memory in file:%s, line:%d!",
612 __FILE__, __LINE__);
613 return NULL;
614 }
615 return memblock;
616}
617
618static void
619score_free_memblock (char *memblock)
620{
621 xfree (memblock);
622}
623
624static void
625score_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc,
626 CORE_ADDR cur_pc)
627{
628 if (prev_pc == -1)
629 {
630 /* First time call this function, do nothing. */
631 }
632 else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0)
633 {
634 /* First 16-bit instruction, then 32-bit instruction. */
635 *memblock += SCORE_INSTLEN;
636 }
637 else if (cur_pc - prev_pc == 4)
638 {
639 /* Is 32-bit instruction, increase MEMBLOCK by 4. */
640 *memblock += SCORE_INSTLEN;
641 }
642}
643
27fd2f50 644static inst_t *
5e29c264 645score_fetch_inst (CORE_ADDR addr, char *memblock)
27fd2f50
Q
646{
647 static inst_t inst = { 0, 0 };
5e29c264 648 char buf[SCORE_INSTLEN] = { 0 };
27fd2f50 649 int big;
5e29c264 650 int ret;
27fd2f50 651
5e29c264 652 if (target_has_execution && memblock != NULL)
27fd2f50 653 {
5e29c264
Q
654 /* Fetch instruction from local MEMBLOCK. */
655 memcpy (buf, memblock, SCORE_INSTLEN);
656 }
657 else
658 {
659 /* Fetch instruction from target. */
660 ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
661 if (ret)
662 {
663 error ("Error: target_read_memory in file:%s, line:%d!",
664 __FILE__, __LINE__);
665 return 0;
666 }
27fd2f50 667 }
5e29c264 668
27fd2f50
Q
669 inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
670 inst.is15 = !(inst.raw & 0x80008000);
671 inst.v = RM_PBITS (inst.raw);
4c6b5505 672 big = (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG);
27fd2f50
Q
673 if (inst.is15)
674 {
675 if (big ^ ((addr & 0x2) == 2))
676 inst.v = G_FLD (inst.v, 29, 15);
677 else
678 inst.v = G_FLD (inst.v, 14, 0);
679 }
680 return &inst;
681}
682
683static CORE_ADDR
684score_skip_prologue (CORE_ADDR pc)
685{
686 CORE_ADDR cpc = pc;
687 int iscan = 32, stack_sub = 0;
688 while (iscan-- > 0)
689 {
5e29c264 690 inst_t *inst = score_fetch_inst (cpc, NULL);
27fd2f50
Q
691 if (!inst)
692 break;
693 if (!inst->is15 && !stack_sub
694 && (G_FLD (inst->v, 29, 25) == 0x1
695 && G_FLD (inst->v, 24, 20) == 0x0))
696 {
697 /* addi r0, offset */
698 pc = stack_sub = cpc + SCORE_INSTLEN;
699 }
700 else if (!inst->is15
701 && inst->v == RM_PBITS (0x8040bc56))
702 {
703 /* mv r2, r0 */
704 pc = cpc + SCORE_INSTLEN;
705 break;
706 }
707 else if (inst->is15
708 && inst->v == RM_PBITS (0x0203))
709 {
710 /* mv! r2, r0 */
711 pc = cpc + SCORE16_INSTLEN;
712 break;
713 }
714 else if (inst->is15
715 && ((G_FLD (inst->v, 14, 12) == 3) /* j15 form */
716 || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
717 || (G_FLD (inst->v, 14, 12) == 0x0
718 && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
719 break;
720 else if (!inst->is15
721 && ((G_FLD (inst->v, 29, 25) == 2) /* j32 form */
722 || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
723 || (G_FLD (inst->v, 29, 25) == 0x0
724 && G_FLD (inst->v, 6, 1) == 0x4))) /* br */
725 break;
726
727 cpc += inst->is15 ? SCORE16_INSTLEN : SCORE_INSTLEN;
728 }
729 return pc;
730}
731
732static int
733score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
734{
5e29c264 735 inst_t *inst = score_fetch_inst (cur_pc, NULL);
27fd2f50
Q
736
737 if (inst->v == 0x23)
738 return 1; /* mv! r0, r2 */
739 else if (G_FLD (inst->v, 14, 12) == 0x2
740 && G_FLD (inst->v, 3, 0) == 0xa)
741 return 1; /* pop! */
742 else if (G_FLD (inst->v, 14, 12) == 0x0
743 && G_FLD (inst->v, 7, 0) == 0x34)
744 return 1; /* br! r3 */
745 else if (G_FLD (inst->v, 29, 15) == 0x2
746 && G_FLD (inst->v, 6, 1) == 0x2b)
747 return 1; /* mv r0, r2 */
748 else if (G_FLD (inst->v, 29, 25) == 0x0
749 && G_FLD (inst->v, 6, 1) == 0x4
750 && G_FLD (inst->v, 19, 15) == 0x3)
751 return 1; /* br r3 */
752 else
753 return 0;
754}
755
756static void
757score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
758 struct frame_info *next_frame,
759 struct score_frame_cache *this_cache)
760{
761 CORE_ADDR sp;
5e29c264 762 CORE_ADDR fp;
27fd2f50
Q
763 CORE_ADDR cur_pc = startaddr;
764
765 int sp_offset = 0;
766 int ra_offset = 0;
767 int fp_offset = 0;
768 int ra_offset_p = 0;
769 int fp_offset_p = 0;
770 int inst_len = 0;
771
5e29c264
Q
772 char *memblock = NULL;
773 char *memblock_ptr = NULL;
774 CORE_ADDR prev_pc = -1;
775
776 /* Allocate MEMBLOCK if PC - STARTADDR > 0. */
777 memblock_ptr = memblock =
778 score_malloc_and_get_memblock (startaddr, pc - startaddr);
779
27fd2f50 780 sp = frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
5e29c264 781 fp = frame_unwind_register_unsigned (next_frame, SCORE_FP_REGNUM);
27fd2f50 782
5e29c264 783 for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
27fd2f50 784 {
5e29c264
Q
785 inst_t *inst = NULL;
786 if (memblock != NULL)
787 {
788 /* Reading memory block from target succefully and got all
789 the instructions(from STARTADDR to PC) needed. */
790 score_adjust_memblock_ptr (&memblock, prev_pc, cur_pc);
791 inst = score_fetch_inst (cur_pc, memblock);
792 }
793 else
794 {
795 /* Otherwise, we fetch 4 bytes from target, and GDB also
796 work correctly. */
797 inst = score_fetch_inst (cur_pc, NULL);
798 }
799
27fd2f50
Q
800 if (inst->is15 == 1)
801 {
802 inst_len = SCORE16_INSTLEN;
803
804 if (G_FLD (inst->v, 14, 12) == 0x2
805 && G_FLD (inst->v, 3, 0) == 0xe)
806 {
807 /* push! */
808 sp_offset += 4;
809
810 if (G_FLD (inst->v, 11, 7) == 0x6
811 && ra_offset_p == 0)
812 {
813 /* push! r3, [r0] */
814 ra_offset = sp_offset;
815 ra_offset_p = 1;
816 }
817 else if (G_FLD (inst->v, 11, 7) == 0x4
818 && fp_offset_p == 0)
819 {
820 /* push! r2, [r0] */
821 fp_offset = sp_offset;
822 fp_offset_p = 1;
823 }
824 }
825 else if (G_FLD (inst->v, 14, 12) == 0x2
826 && G_FLD (inst->v, 3, 0) == 0xa)
827 {
828 /* pop! */
829 sp_offset -= 4;
830 }
831 else if (G_FLD (inst->v, 14, 7) == 0xc1
832 && G_FLD (inst->v, 2, 0) == 0x0)
833 {
834 /* subei! r0, n */
835 sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
836 }
837 else if (G_FLD (inst->v, 14, 7) == 0xc0
838 && G_FLD (inst->v, 2, 0) == 0x0)
839 {
840 /* addei! r0, n */
841 sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
842 }
843 }
844 else
845 {
846 inst_len = SCORE_INSTLEN;
847
848 if (G_FLD (inst->v, 29, 15) == 0xc60
849 && G_FLD (inst->v, 2, 0) == 0x4)
850 {
851 /* sw r3, [r0, offset]+ */
852 sp_offset += SCORE_INSTLEN;
853 if (ra_offset_p == 0)
854 {
855 ra_offset = sp_offset;
856 ra_offset_p = 1;
857 }
858 }
859 if (G_FLD (inst->v, 29, 15) == 0xc40
860 && G_FLD (inst->v, 2, 0) == 0x4)
861 {
862 /* sw r2, [r0, offset]+ */
863 sp_offset += SCORE_INSTLEN;
864 if (fp_offset_p == 0)
865 {
866 fp_offset = sp_offset;
867 fp_offset_p = 1;
868 }
869 }
870 else if (G_FLD (inst->v, 29, 15) == 0x1c60
871 && G_FLD (inst->v, 2, 0) == 0x0)
872 {
873 /* lw r3, [r0]+, 4 */
874 sp_offset -= SCORE_INSTLEN;
875 ra_offset_p = 1;
876 }
877 else if (G_FLD (inst->v, 29, 15) == 0x1c40
878 && G_FLD (inst->v, 2, 0) == 0x0)
879 {
880 /* lw r2, [r0]+, 4 */
881 sp_offset -= SCORE_INSTLEN;
882 fp_offset_p = 1;
883 }
884
885 else if (G_FLD (inst->v, 29, 17) == 0x100
886 && G_FLD (inst->v, 0, 0) == 0x0)
887 {
888 /* addi r0, -offset */
889 sp_offset += 65536 - G_FLD (inst->v, 16, 1);
890 }
891 else if (G_FLD (inst->v, 29, 17) == 0x110
892 && G_FLD (inst->v, 0, 0) == 0x0)
893 {
894 /* addi r2, offset */
895 if (pc - cur_pc > 4)
896 {
897 unsigned int save_v = inst->v;
898 inst_t *inst2 =
5e29c264 899 score_fetch_inst (cur_pc + SCORE_INSTLEN, NULL);
27fd2f50 900 if (inst2->v == 0x23)
5e29c264
Q
901 {
902 /* mv! r0, r2 */
903 sp_offset -= G_FLD (save_v, 16, 1);
904 }
27fd2f50
Q
905 }
906 }
907 }
908 }
909
910 /* Save RA. */
911 if (ra_offset_p == 1)
912 {
913 if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
914 this_cache->saved_regs[SCORE_PC_REGNUM].addr =
915 sp + sp_offset - ra_offset;
916 }
917 else
918 {
919 this_cache->saved_regs[SCORE_PC_REGNUM] =
920 this_cache->saved_regs[SCORE_RA_REGNUM];
921 }
922
923 /* Save FP. */
924 if (fp_offset_p == 1)
925 {
926 if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
927 this_cache->saved_regs[SCORE_FP_REGNUM].addr =
928 sp + sp_offset - fp_offset;
929 }
930
5e29c264
Q
931 /* Save SP and FP. */
932 this_cache->base = sp + sp_offset;
933 this_cache->fp = fp;
934
935 /* Don't forget to free MEMBLOCK if we allocated it. */
936 if (memblock_ptr != NULL)
937 score_free_memblock (memblock_ptr);
27fd2f50
Q
938}
939
940static struct score_frame_cache *
941score_make_prologue_cache (struct frame_info *next_frame, void **this_cache)
942{
943 struct score_frame_cache *cache;
944
945 if ((*this_cache) != NULL)
946 return (*this_cache);
947
948 cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
949 (*this_cache) = cache;
950 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
951
952 /* Analyze the prologue. */
953 {
954 const CORE_ADDR pc = frame_pc_unwind (next_frame);
955 CORE_ADDR start_addr;
956
957 find_pc_partial_function (pc, NULL, &start_addr, NULL);
958 if (start_addr == 0)
959 return cache;
960 score_analyze_prologue (start_addr, pc, next_frame, *this_cache);
961 }
962
963 /* Save SP. */
964 trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
965
966 return (*this_cache);
967}
968
969static void
970score_prologue_this_id (struct frame_info *next_frame, void **this_cache,
971 struct frame_id *this_id)
972{
973 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
974 this_cache);
93d42b30 975 (*this_id) = frame_id_build (info->base,
5e29c264 976 frame_func_unwind (next_frame, NORMAL_FRAME));
27fd2f50
Q
977}
978
979static void
980score_prologue_prev_register (struct frame_info *next_frame,
981 void **this_cache,
982 int regnum, int *optimizedp,
983 enum lval_type *lvalp, CORE_ADDR * addrp,
984 int *realnump, gdb_byte * valuep)
985{
986 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
987 this_cache);
988 trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
989 optimizedp, lvalp, addrp, realnump, valuep);
990}
991
992static const struct frame_unwind score_prologue_unwind =
993{
994 NORMAL_FRAME,
995 score_prologue_this_id,
996 score_prologue_prev_register
997};
998
999static const struct frame_unwind *
1000score_prologue_sniffer (struct frame_info *next_frame)
1001{
1002 return &score_prologue_unwind;
1003}
1004
1005static CORE_ADDR
1006score_prologue_frame_base_address (struct frame_info *next_frame,
1007 void **this_cache)
1008{
1009 struct score_frame_cache *info =
1010 score_make_prologue_cache (next_frame, this_cache);
5e29c264 1011 return info->fp;
27fd2f50
Q
1012}
1013
1014static const struct frame_base score_prologue_frame_base =
1015{
1016 &score_prologue_unwind,
1017 score_prologue_frame_base_address,
1018 score_prologue_frame_base_address,
1019 score_prologue_frame_base_address,
1020};
1021
1022static const struct frame_base *
1023score_prologue_frame_base_sniffer (struct frame_info *next_frame)
1024{
1025 return &score_prologue_frame_base;
1026}
1027
1028static struct gdbarch *
1029score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
1030{
1031 struct gdbarch *gdbarch;
1032
1033 arches = gdbarch_list_lookup_by_info (arches, &info);
1034 if (arches != NULL)
1035 {
1036 return (arches->gdbarch);
1037 }
1038 gdbarch = gdbarch_alloc (&info, 0);
1039
1040 set_gdbarch_short_bit (gdbarch, 16);
1041 set_gdbarch_int_bit (gdbarch, 32);
1042 set_gdbarch_float_bit (gdbarch, 32);
1043 set_gdbarch_double_bit (gdbarch, 64);
1044 set_gdbarch_long_double_bit (gdbarch, 64);
1045 set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
1046 set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
1047 set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
1048 set_gdbarch_num_regs (gdbarch, SCORE_NUM_REGS);
1049 set_gdbarch_register_name (gdbarch, score_register_name);
1050 set_gdbarch_breakpoint_from_pc (gdbarch, score_breakpoint_from_pc);
1051 set_gdbarch_register_type (gdbarch, score_register_type);
1052 set_gdbarch_frame_align (gdbarch, score_frame_align);
1053 set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
27fd2f50 1054 set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
30244cd8 1055 set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
27fd2f50
Q
1056 set_gdbarch_print_insn (gdbarch, score_print_insn);
1057 set_gdbarch_skip_prologue (gdbarch, score_skip_prologue);
1058 set_gdbarch_in_function_epilogue_p (gdbarch, score_in_function_epilogue_p);
5e29c264
Q
1059
1060 /* Watchpoint hooks. */
1061 set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
1062
1063 /* Dummy frame hooks. */
27fd2f50 1064 set_gdbarch_return_value (gdbarch, score_return_value);
5e29c264 1065 set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
27fd2f50
Q
1066 set_gdbarch_unwind_dummy_id (gdbarch, score_unwind_dummy_id);
1067 set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
1068
5e29c264 1069 /* Normal frame hooks. */
27fd2f50
Q
1070 frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
1071 frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
1072 frame_unwind_append_sniffer (gdbarch, score_prologue_sniffer);
1073 frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
1074
1075 return gdbarch;
1076}
1077
1078extern initialize_file_ftype _initialize_score_tdep;
1079
1080void
1081_initialize_score_tdep (void)
1082{
1083 gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
1084}
This page took 0.113253 seconds and 4 git commands to generate.