bfd/
[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{
319 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
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
339 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
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;
437 score_xfer_register (regcache, regnum, xfer, TARGET_BYTE_ORDER,
438 readbuf, writebuf, offset);
439 }
440 return RETURN_VALUE_REGISTER_CONVENTION;
441 }
442}
443
444static struct frame_id
5e29c264
Q
445score_unwind_dummy_id (struct gdbarch *gdbarch,
446 struct frame_info *next_frame)
27fd2f50
Q
447{
448 return frame_id_build (
449 frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM),
450 frame_pc_unwind (next_frame));
451}
452
453static int
454score_type_needs_double_align (struct type *type)
455{
456 enum type_code typecode = TYPE_CODE (type);
457
5e29c264
Q
458 if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
459 || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
27fd2f50
Q
460 return 1;
461 else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
462 {
463 int i, n;
464
465 n = TYPE_NFIELDS (type);
466 for (i = 0; i < n; i++)
467 if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
468 return 1;
469 return 0;
470 }
471 return 0;
472}
473
474static CORE_ADDR
475score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
476 struct regcache *regcache, CORE_ADDR bp_addr,
477 int nargs, struct value **args, CORE_ADDR sp,
478 int struct_return, CORE_ADDR struct_addr)
479{
480 int argnum;
481 int argreg;
482 int arglen = 0;
483 CORE_ADDR stack_offset = 0;
484 CORE_ADDR addr = 0;
485
486 /* Step 1, Save RA. */
487 regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
488
489 /* Step 2, Make space on the stack for the args. */
490 struct_addr = align_down (struct_addr, 16);
491 sp = align_down (sp, 16);
492 for (argnum = 0; argnum < nargs; argnum++)
493 arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
494 SCORE_REGSIZE);
495 sp -= align_up (arglen, 16);
496
497 argreg = SCORE_BEGIN_ARG_REGNUM;
498
5e29c264
Q
499 /* Step 3, Check if struct return then save the struct address to
500 r4 and increase the stack_offset by 4. */
27fd2f50
Q
501 if (struct_return)
502 {
503 regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
504 stack_offset += SCORE_REGSIZE;
505 }
506
507 /* Step 4, Load arguments:
5e29c264
Q
508 If arg length is too long (> 4 bytes), then split the arg and
509 save every parts. */
27fd2f50
Q
510 for (argnum = 0; argnum < nargs; argnum++)
511 {
512 struct value *arg = args[argnum];
513 struct type *arg_type = check_typedef (value_type (arg));
27fd2f50
Q
514 enum type_code typecode = TYPE_CODE (arg_type);
515 const gdb_byte *val = value_contents (arg);
516 int downward_offset = 0;
1cfd2c3e
JB
517 int odd_sized_struct_p;
518 int arg_last_part_p = 0;
27fd2f50 519
1cfd2c3e
JB
520 arglen = TYPE_LENGTH (arg_type);
521 odd_sized_struct_p = (arglen > SCORE_REGSIZE
5e29c264 522 && arglen % SCORE_REGSIZE != 0);
27fd2f50
Q
523
524 /* If a arg should be aligned to 8 bytes (long long or double),
525 the value should be put to even register numbers. */
526 if (score_type_needs_double_align (arg_type))
527 {
528 if (argreg & 1)
529 argreg++;
530 }
531
532 /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
533 the default "downward"/"upward" method:
534
535 Example:
536
537 struct struc
538 {
539 char a; char b; char c;
540 } s = {'a', 'b', 'c'};
541
542 Big endian: s = {X, 'a', 'b', 'c'}
543 Little endian: s = {'a', 'b', 'c', X}
544
545 Where X is a hole. */
546
547 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
548 && (typecode == TYPE_CODE_STRUCT
549 || typecode == TYPE_CODE_UNION)
550 && argreg > SCORE_LAST_ARG_REGNUM
551 && arglen < SCORE_REGSIZE)
552 downward_offset += (SCORE_REGSIZE - arglen);
553
554 while (arglen > 0)
555 {
556 int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
557 ULONGEST regval = extract_unsigned_integer (val, partial_len);
558
559 /* The last part of a arg should shift left when
560 TARGET_BYTE_ORDER is BFD_ENDIAN_BIG. */
561 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
562 && arg_last_part_p == 1
563 && (typecode == TYPE_CODE_STRUCT
564 || typecode == TYPE_CODE_UNION))
565 regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
566
567 /* Always increase the stack_offset and save args to stack. */
568 addr = sp + stack_offset + downward_offset;
569 write_memory (addr, val, partial_len);
570
571 if (argreg <= SCORE_LAST_ARG_REGNUM)
572 {
573 regcache_cooked_write_unsigned (regcache, argreg++, regval);
574 if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
575 arg_last_part_p = 1;
576 }
577
578 val += partial_len;
579 arglen -= partial_len;
580 stack_offset += align_up (partial_len, SCORE_REGSIZE);
581 }
582 }
583
584 /* Step 5, Save SP. */
585 regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
586
587 return sp;
588}
589
5e29c264
Q
590static char *
591score_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size)
592{
593 int ret;
594 char *memblock = NULL;
595
596 if (size < 0)
597 {
598 error ("Error: malloc size < 0 in file:%s, line:%d!",
599 __FILE__, __LINE__);
600 return NULL;
601 }
602 else if (size == 0)
603 return NULL;
604
605 memblock = (char *) xmalloc (size);
606 memset (memblock, 0, size);
607 ret = target_read_memory (addr & ~0x3, memblock, size);
608 if (ret)
609 {
610 error ("Error: target_read_memory in file:%s, line:%d!",
611 __FILE__, __LINE__);
612 return NULL;
613 }
614 return memblock;
615}
616
617static void
618score_free_memblock (char *memblock)
619{
620 xfree (memblock);
621}
622
623static void
624score_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc,
625 CORE_ADDR cur_pc)
626{
627 if (prev_pc == -1)
628 {
629 /* First time call this function, do nothing. */
630 }
631 else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0)
632 {
633 /* First 16-bit instruction, then 32-bit instruction. */
634 *memblock += SCORE_INSTLEN;
635 }
636 else if (cur_pc - prev_pc == 4)
637 {
638 /* Is 32-bit instruction, increase MEMBLOCK by 4. */
639 *memblock += SCORE_INSTLEN;
640 }
641}
642
27fd2f50 643static inst_t *
5e29c264 644score_fetch_inst (CORE_ADDR addr, char *memblock)
27fd2f50
Q
645{
646 static inst_t inst = { 0, 0 };
5e29c264 647 char buf[SCORE_INSTLEN] = { 0 };
27fd2f50 648 int big;
5e29c264 649 int ret;
27fd2f50 650
5e29c264 651 if (target_has_execution && memblock != NULL)
27fd2f50 652 {
5e29c264
Q
653 /* Fetch instruction from local MEMBLOCK. */
654 memcpy (buf, memblock, SCORE_INSTLEN);
655 }
656 else
657 {
658 /* Fetch instruction from target. */
659 ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
660 if (ret)
661 {
662 error ("Error: target_read_memory in file:%s, line:%d!",
663 __FILE__, __LINE__);
664 return 0;
665 }
27fd2f50 666 }
5e29c264 667
27fd2f50
Q
668 inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
669 inst.is15 = !(inst.raw & 0x80008000);
670 inst.v = RM_PBITS (inst.raw);
671 big = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
27fd2f50
Q
672 if (inst.is15)
673 {
674 if (big ^ ((addr & 0x2) == 2))
675 inst.v = G_FLD (inst.v, 29, 15);
676 else
677 inst.v = G_FLD (inst.v, 14, 0);
678 }
679 return &inst;
680}
681
682static CORE_ADDR
683score_skip_prologue (CORE_ADDR pc)
684{
685 CORE_ADDR cpc = pc;
686 int iscan = 32, stack_sub = 0;
687 while (iscan-- > 0)
688 {
5e29c264 689 inst_t *inst = score_fetch_inst (cpc, NULL);
27fd2f50
Q
690 if (!inst)
691 break;
692 if (!inst->is15 && !stack_sub
693 && (G_FLD (inst->v, 29, 25) == 0x1
694 && G_FLD (inst->v, 24, 20) == 0x0))
695 {
696 /* addi r0, offset */
697 pc = stack_sub = cpc + SCORE_INSTLEN;
698 }
699 else if (!inst->is15
700 && inst->v == RM_PBITS (0x8040bc56))
701 {
702 /* mv r2, r0 */
703 pc = cpc + SCORE_INSTLEN;
704 break;
705 }
706 else if (inst->is15
707 && inst->v == RM_PBITS (0x0203))
708 {
709 /* mv! r2, r0 */
710 pc = cpc + SCORE16_INSTLEN;
711 break;
712 }
713 else if (inst->is15
714 && ((G_FLD (inst->v, 14, 12) == 3) /* j15 form */
715 || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
716 || (G_FLD (inst->v, 14, 12) == 0x0
717 && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
718 break;
719 else if (!inst->is15
720 && ((G_FLD (inst->v, 29, 25) == 2) /* j32 form */
721 || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
722 || (G_FLD (inst->v, 29, 25) == 0x0
723 && G_FLD (inst->v, 6, 1) == 0x4))) /* br */
724 break;
725
726 cpc += inst->is15 ? SCORE16_INSTLEN : SCORE_INSTLEN;
727 }
728 return pc;
729}
730
731static int
732score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
733{
5e29c264 734 inst_t *inst = score_fetch_inst (cur_pc, NULL);
27fd2f50
Q
735
736 if (inst->v == 0x23)
737 return 1; /* mv! r0, r2 */
738 else if (G_FLD (inst->v, 14, 12) == 0x2
739 && G_FLD (inst->v, 3, 0) == 0xa)
740 return 1; /* pop! */
741 else if (G_FLD (inst->v, 14, 12) == 0x0
742 && G_FLD (inst->v, 7, 0) == 0x34)
743 return 1; /* br! r3 */
744 else if (G_FLD (inst->v, 29, 15) == 0x2
745 && G_FLD (inst->v, 6, 1) == 0x2b)
746 return 1; /* mv r0, r2 */
747 else if (G_FLD (inst->v, 29, 25) == 0x0
748 && G_FLD (inst->v, 6, 1) == 0x4
749 && G_FLD (inst->v, 19, 15) == 0x3)
750 return 1; /* br r3 */
751 else
752 return 0;
753}
754
755static void
756score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
757 struct frame_info *next_frame,
758 struct score_frame_cache *this_cache)
759{
760 CORE_ADDR sp;
5e29c264 761 CORE_ADDR fp;
27fd2f50
Q
762 CORE_ADDR cur_pc = startaddr;
763
764 int sp_offset = 0;
765 int ra_offset = 0;
766 int fp_offset = 0;
767 int ra_offset_p = 0;
768 int fp_offset_p = 0;
769 int inst_len = 0;
770
5e29c264
Q
771 char *memblock = NULL;
772 char *memblock_ptr = NULL;
773 CORE_ADDR prev_pc = -1;
774
775 /* Allocate MEMBLOCK if PC - STARTADDR > 0. */
776 memblock_ptr = memblock =
777 score_malloc_and_get_memblock (startaddr, pc - startaddr);
778
27fd2f50 779 sp = frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
5e29c264 780 fp = frame_unwind_register_unsigned (next_frame, SCORE_FP_REGNUM);
27fd2f50 781
5e29c264 782 for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
27fd2f50 783 {
5e29c264
Q
784 inst_t *inst = NULL;
785 if (memblock != NULL)
786 {
787 /* Reading memory block from target succefully and got all
788 the instructions(from STARTADDR to PC) needed. */
789 score_adjust_memblock_ptr (&memblock, prev_pc, cur_pc);
790 inst = score_fetch_inst (cur_pc, memblock);
791 }
792 else
793 {
794 /* Otherwise, we fetch 4 bytes from target, and GDB also
795 work correctly. */
796 inst = score_fetch_inst (cur_pc, NULL);
797 }
798
27fd2f50
Q
799 if (inst->is15 == 1)
800 {
801 inst_len = SCORE16_INSTLEN;
802
803 if (G_FLD (inst->v, 14, 12) == 0x2
804 && G_FLD (inst->v, 3, 0) == 0xe)
805 {
806 /* push! */
807 sp_offset += 4;
808
809 if (G_FLD (inst->v, 11, 7) == 0x6
810 && ra_offset_p == 0)
811 {
812 /* push! r3, [r0] */
813 ra_offset = sp_offset;
814 ra_offset_p = 1;
815 }
816 else if (G_FLD (inst->v, 11, 7) == 0x4
817 && fp_offset_p == 0)
818 {
819 /* push! r2, [r0] */
820 fp_offset = sp_offset;
821 fp_offset_p = 1;
822 }
823 }
824 else if (G_FLD (inst->v, 14, 12) == 0x2
825 && G_FLD (inst->v, 3, 0) == 0xa)
826 {
827 /* pop! */
828 sp_offset -= 4;
829 }
830 else if (G_FLD (inst->v, 14, 7) == 0xc1
831 && G_FLD (inst->v, 2, 0) == 0x0)
832 {
833 /* subei! r0, n */
834 sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
835 }
836 else if (G_FLD (inst->v, 14, 7) == 0xc0
837 && G_FLD (inst->v, 2, 0) == 0x0)
838 {
839 /* addei! r0, n */
840 sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
841 }
842 }
843 else
844 {
845 inst_len = SCORE_INSTLEN;
846
847 if (G_FLD (inst->v, 29, 15) == 0xc60
848 && G_FLD (inst->v, 2, 0) == 0x4)
849 {
850 /* sw r3, [r0, offset]+ */
851 sp_offset += SCORE_INSTLEN;
852 if (ra_offset_p == 0)
853 {
854 ra_offset = sp_offset;
855 ra_offset_p = 1;
856 }
857 }
858 if (G_FLD (inst->v, 29, 15) == 0xc40
859 && G_FLD (inst->v, 2, 0) == 0x4)
860 {
861 /* sw r2, [r0, offset]+ */
862 sp_offset += SCORE_INSTLEN;
863 if (fp_offset_p == 0)
864 {
865 fp_offset = sp_offset;
866 fp_offset_p = 1;
867 }
868 }
869 else if (G_FLD (inst->v, 29, 15) == 0x1c60
870 && G_FLD (inst->v, 2, 0) == 0x0)
871 {
872 /* lw r3, [r0]+, 4 */
873 sp_offset -= SCORE_INSTLEN;
874 ra_offset_p = 1;
875 }
876 else if (G_FLD (inst->v, 29, 15) == 0x1c40
877 && G_FLD (inst->v, 2, 0) == 0x0)
878 {
879 /* lw r2, [r0]+, 4 */
880 sp_offset -= SCORE_INSTLEN;
881 fp_offset_p = 1;
882 }
883
884 else if (G_FLD (inst->v, 29, 17) == 0x100
885 && G_FLD (inst->v, 0, 0) == 0x0)
886 {
887 /* addi r0, -offset */
888 sp_offset += 65536 - G_FLD (inst->v, 16, 1);
889 }
890 else if (G_FLD (inst->v, 29, 17) == 0x110
891 && G_FLD (inst->v, 0, 0) == 0x0)
892 {
893 /* addi r2, offset */
894 if (pc - cur_pc > 4)
895 {
896 unsigned int save_v = inst->v;
897 inst_t *inst2 =
5e29c264 898 score_fetch_inst (cur_pc + SCORE_INSTLEN, NULL);
27fd2f50 899 if (inst2->v == 0x23)
5e29c264
Q
900 {
901 /* mv! r0, r2 */
902 sp_offset -= G_FLD (save_v, 16, 1);
903 }
27fd2f50
Q
904 }
905 }
906 }
907 }
908
909 /* Save RA. */
910 if (ra_offset_p == 1)
911 {
912 if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
913 this_cache->saved_regs[SCORE_PC_REGNUM].addr =
914 sp + sp_offset - ra_offset;
915 }
916 else
917 {
918 this_cache->saved_regs[SCORE_PC_REGNUM] =
919 this_cache->saved_regs[SCORE_RA_REGNUM];
920 }
921
922 /* Save FP. */
923 if (fp_offset_p == 1)
924 {
925 if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
926 this_cache->saved_regs[SCORE_FP_REGNUM].addr =
927 sp + sp_offset - fp_offset;
928 }
929
5e29c264
Q
930 /* Save SP and FP. */
931 this_cache->base = sp + sp_offset;
932 this_cache->fp = fp;
933
934 /* Don't forget to free MEMBLOCK if we allocated it. */
935 if (memblock_ptr != NULL)
936 score_free_memblock (memblock_ptr);
27fd2f50
Q
937}
938
939static struct score_frame_cache *
940score_make_prologue_cache (struct frame_info *next_frame, void **this_cache)
941{
942 struct score_frame_cache *cache;
943
944 if ((*this_cache) != NULL)
945 return (*this_cache);
946
947 cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
948 (*this_cache) = cache;
949 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
950
951 /* Analyze the prologue. */
952 {
953 const CORE_ADDR pc = frame_pc_unwind (next_frame);
954 CORE_ADDR start_addr;
955
956 find_pc_partial_function (pc, NULL, &start_addr, NULL);
957 if (start_addr == 0)
958 return cache;
959 score_analyze_prologue (start_addr, pc, next_frame, *this_cache);
960 }
961
962 /* Save SP. */
963 trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
964
965 return (*this_cache);
966}
967
968static void
969score_prologue_this_id (struct frame_info *next_frame, void **this_cache,
970 struct frame_id *this_id)
971{
972 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
973 this_cache);
93d42b30 974 (*this_id) = frame_id_build (info->base,
5e29c264 975 frame_func_unwind (next_frame, NORMAL_FRAME));
27fd2f50
Q
976}
977
978static void
979score_prologue_prev_register (struct frame_info *next_frame,
980 void **this_cache,
981 int regnum, int *optimizedp,
982 enum lval_type *lvalp, CORE_ADDR * addrp,
983 int *realnump, gdb_byte * valuep)
984{
985 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
986 this_cache);
987 trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
988 optimizedp, lvalp, addrp, realnump, valuep);
989}
990
991static const struct frame_unwind score_prologue_unwind =
992{
993 NORMAL_FRAME,
994 score_prologue_this_id,
995 score_prologue_prev_register
996};
997
998static const struct frame_unwind *
999score_prologue_sniffer (struct frame_info *next_frame)
1000{
1001 return &score_prologue_unwind;
1002}
1003
1004static CORE_ADDR
1005score_prologue_frame_base_address (struct frame_info *next_frame,
1006 void **this_cache)
1007{
1008 struct score_frame_cache *info =
1009 score_make_prologue_cache (next_frame, this_cache);
5e29c264 1010 return info->fp;
27fd2f50
Q
1011}
1012
1013static const struct frame_base score_prologue_frame_base =
1014{
1015 &score_prologue_unwind,
1016 score_prologue_frame_base_address,
1017 score_prologue_frame_base_address,
1018 score_prologue_frame_base_address,
1019};
1020
1021static const struct frame_base *
1022score_prologue_frame_base_sniffer (struct frame_info *next_frame)
1023{
1024 return &score_prologue_frame_base;
1025}
1026
1027static struct gdbarch *
1028score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
1029{
1030 struct gdbarch *gdbarch;
1031
1032 arches = gdbarch_list_lookup_by_info (arches, &info);
1033 if (arches != NULL)
1034 {
1035 return (arches->gdbarch);
1036 }
1037 gdbarch = gdbarch_alloc (&info, 0);
1038
1039 set_gdbarch_short_bit (gdbarch, 16);
1040 set_gdbarch_int_bit (gdbarch, 32);
1041 set_gdbarch_float_bit (gdbarch, 32);
1042 set_gdbarch_double_bit (gdbarch, 64);
1043 set_gdbarch_long_double_bit (gdbarch, 64);
1044 set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
1045 set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
1046 set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
1047 set_gdbarch_num_regs (gdbarch, SCORE_NUM_REGS);
1048 set_gdbarch_register_name (gdbarch, score_register_name);
1049 set_gdbarch_breakpoint_from_pc (gdbarch, score_breakpoint_from_pc);
1050 set_gdbarch_register_type (gdbarch, score_register_type);
1051 set_gdbarch_frame_align (gdbarch, score_frame_align);
1052 set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
27fd2f50 1053 set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
30244cd8 1054 set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
27fd2f50
Q
1055 set_gdbarch_print_insn (gdbarch, score_print_insn);
1056 set_gdbarch_skip_prologue (gdbarch, score_skip_prologue);
1057 set_gdbarch_in_function_epilogue_p (gdbarch, score_in_function_epilogue_p);
5e29c264
Q
1058
1059 /* Watchpoint hooks. */
1060 set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
1061
1062 /* Dummy frame hooks. */
27fd2f50 1063 set_gdbarch_return_value (gdbarch, score_return_value);
5e29c264 1064 set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
27fd2f50
Q
1065 set_gdbarch_unwind_dummy_id (gdbarch, score_unwind_dummy_id);
1066 set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
1067
5e29c264 1068 /* Normal frame hooks. */
27fd2f50
Q
1069 frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
1070 frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
1071 frame_unwind_append_sniffer (gdbarch, score_prologue_sniffer);
1072 frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
1073
1074 return gdbarch;
1075}
1076
1077extern initialize_file_ftype _initialize_score_tdep;
1078
1079void
1080_initialize_score_tdep (void)
1081{
1082 gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
1083}
This page took 0.099007 seconds and 4 git commands to generate.