* gdbarch.sh (read_sp): Remove.
[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;
54 struct trad_frame_saved_reg *saved_regs;
55};
56
57#if 0
58/* If S+core GCC will generate these instructions in the prologue:
59
60 lw rx, imm1
61 addi rx, -imm2
62 mv! r2, rx
63
64 then .pdr section is used. */
65
66#define P_SIZE 8
67#define PI_SYM 0
68#define PI_R_MSK 1
69#define PI_R_OFF 2
70#define PI_R_LEF 4
71#define PI_F_OFF 5
72#define PI_F_REG 6
73#define PI_RAREG 7
74
75typedef struct frame_extra_info
76{
77 CORE_ADDR p_frame;
78 unsigned int pdr[P_SIZE];
79} extra_info_t;
80
81struct obj_priv
82{
83 bfd_size_type size;
84 char *contents;
85};
86
87static bfd *the_bfd;
88
89static int
90score_compare_pdr_entries (const void *a, const void *b)
91{
92 CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
93 CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
94 if (lhs < rhs)
95 return -1;
96 else if (lhs == rhs)
97 return 0;
98 else
99 return 1;
100}
101
102static void
103score_analyze_pdr_section (CORE_ADDR startaddr, CORE_ADDR pc,
104 struct frame_info *next_frame,
105 struct score_frame_cache *this_cache)
106{
107 struct symbol *sym;
108 struct obj_section *sec;
109 extra_info_t *fci_ext;
110 CORE_ADDR leaf_ra_stack_addr = -1;
111
112 gdb_assert (startaddr <= pc);
113 gdb_assert (this_cache != NULL);
114
115 fci_ext = frame_obstack_zalloc (sizeof (extra_info_t));
116 if ((sec = find_pc_section (pc)) == NULL)
117 {
118 error ("Can't find section in file:%s, line:%d!", __FILE__, __LINE__);
119 return;
120 }
121
122 /* Anylyze .pdr section and get coresponding fields. */
123 {
124 static struct obj_priv *priv = NULL;
125
126 if (priv == NULL)
127 {
128 asection *bfdsec;
129 priv = obstack_alloc (&sec->objfile->objfile_obstack,
130 sizeof (struct obj_priv));
131 if ((bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr")))
132 {
133 priv->size = bfd_section_size (sec->objfile->obfd, bfdsec);
134 priv->contents = obstack_alloc (&sec->objfile->objfile_obstack,
135 priv->size);
136 bfd_get_section_contents (sec->objfile->obfd, bfdsec,
137 priv->contents, 0, priv->size);
138 the_bfd = sec->objfile->obfd;
139 qsort (priv->contents, priv->size / 32, 32,
140 score_compare_pdr_entries);
141 the_bfd = NULL;
142 }
143 else
144 priv->size = 0;
145 }
146 if (priv->size != 0)
147 {
148 int low = 0, mid, high = priv->size / 32;
149 char *ptr;
150 do
151
152 {
153 CORE_ADDR pdr_pc;
154 mid = (low + high) / 2;
155 ptr = priv->contents + mid * 32;
156 pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
157 pdr_pc += ANOFFSET (sec->objfile->section_offsets,
158 SECT_OFF_TEXT (sec->objfile));
159 if (pdr_pc == startaddr)
160 break;
161 if (pdr_pc > startaddr)
162 high = mid;
163 else
164 low = mid + 1;
165 }
166 while (low != high);
167
168 if (low != high)
169 {
170 gdb_assert (bfd_get_32 (sec->objfile->obfd, ptr) == startaddr);
171#define EXT_PDR(_pi) bfd_get_32(sec->objfile->obfd, ptr+((_pi)<<2))
172 fci_ext->pdr[PI_SYM] = EXT_PDR (PI_SYM);
173 fci_ext->pdr[PI_R_MSK] = EXT_PDR (PI_R_MSK);
174 fci_ext->pdr[PI_R_OFF] = EXT_PDR (PI_R_OFF);
175 fci_ext->pdr[PI_R_LEF] = EXT_PDR (PI_R_LEF);
176 fci_ext->pdr[PI_F_OFF] = EXT_PDR (PI_F_OFF);
177 fci_ext->pdr[PI_F_REG] = EXT_PDR (PI_F_REG);
178 fci_ext->pdr[PI_RAREG] = EXT_PDR (PI_RAREG);
179#undef EXT_PDR
180 }
181 }
182 }
183}
184#endif
185
186static struct type *
187score_register_type (struct gdbarch *gdbarch, int regnum)
188{
189 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
190 return builtin_type_uint32;
191}
192
27fd2f50 193static CORE_ADDR
30244cd8 194score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
27fd2f50 195{
30244cd8 196 return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
27fd2f50
Q
197}
198
199static CORE_ADDR
30244cd8 200score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
27fd2f50 201{
30244cd8 202 return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
27fd2f50
Q
203}
204
205static const char *
206score_register_name (int regnum)
207{
208 const char *score_register_names[] = {
209 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
210 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
211 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
212 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
213
214 "PSR", "COND", "ECR", "EXCPVEC",
215 "CCR", "EPC", "EMA", "TLBLOCK",
216 "TLBPT", "PEADDR", "TLBRPT", "PEVN",
217 "PECTX", "LIMPFN", "LDMPFN", "PREV",
218 "DREG", "PC", "DSAVE", "COUNTER",
219 "LDCR", "STCR", "CEH", "CEL",
220 };
221
222 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
223 return score_register_names[regnum];
224}
225
226static int
227score_register_sim_regno (int regnum)
228{
229 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
230 return regnum;
231}
232
233static int
234score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
235{
236 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
237 return print_insn_big_score (memaddr, info);
238 else
239 return print_insn_little_score (memaddr, info);
240}
241
242static const gdb_byte *
243score_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
244{
245 gdb_byte buf[SCORE_INSTLEN] = { 0 };
246 int ret;
247 unsigned int raw;
248
249 if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
250 {
251 memory_error (ret, *pcptr);
252 }
253 raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
254
255 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
256 {
257 if (!(raw & 0x80008000))
258 {
259 /* 16bits instruction. */
260 static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
261 *pcptr &= ~0x1;
262 *lenptr = sizeof (big_breakpoint16);
263 return big_breakpoint16;
264 }
265 else
266 {
267 /* 32bits instruction. */
268 static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
269 *pcptr &= ~0x3;
270 *lenptr = sizeof (big_breakpoint32);
271 return big_breakpoint32;
272 }
273 }
274 else
275 {
276 if (!(raw & 0x80008000))
277 {
278 /* 16bits instruction. */
279 static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
280 *pcptr &= ~0x1;
281 *lenptr = sizeof (little_breakpoint16);
282 return little_breakpoint16;
283 }
284 else
285 {
286 /* 32bits instruction. */
287 static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
288 *pcptr &= ~0x3;
289 *lenptr = sizeof (little_breakpoint32);
290 return little_breakpoint32;
291 }
292 }
293}
294
295static CORE_ADDR
296score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
297{
298 return align_down (addr, 16);
299}
300
301static void
302score_xfer_register (struct regcache *regcache, int regnum, int length,
303 enum bfd_endian endian, gdb_byte *readbuf,
304 const gdb_byte *writebuf, int buf_offset)
305{
306 int reg_offset = 0;
307 gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
308
309 switch (endian)
310 {
311 case BFD_ENDIAN_BIG:
312 reg_offset = SCORE_REGSIZE - length;
313 break;
314 case BFD_ENDIAN_LITTLE:
315 reg_offset = 0;
316 break;
317 case BFD_ENDIAN_UNKNOWN:
318 reg_offset = 0;
319 break;
320 default:
321 internal_error (__FILE__, __LINE__, _("score_xfer_register error!"));
322 }
323
324 if (readbuf != NULL)
325 regcache_cooked_read_part (regcache, regnum, reg_offset, length,
326 readbuf + buf_offset);
327 if (writebuf != NULL)
328 regcache_cooked_write_part (regcache, regnum, reg_offset, length,
329 writebuf + buf_offset);
330}
331
332static enum return_value_convention
333score_return_value (struct gdbarch *gdbarch, struct type *type,
334 struct regcache *regcache,
335 gdb_byte * readbuf, const gdb_byte * writebuf)
336{
337 if (TYPE_CODE (type) == TYPE_CODE_STRUCT
338 || TYPE_CODE (type) == TYPE_CODE_UNION
339 || TYPE_CODE (type) == TYPE_CODE_ARRAY)
340 return RETURN_VALUE_STRUCT_CONVENTION;
341 else
342 {
343 int offset;
344 int regnum;
345 for (offset = 0, regnum = SCORE_A0_REGNUM;
346 offset < TYPE_LENGTH (type);
347 offset += SCORE_REGSIZE, regnum++)
348 {
349 int xfer = SCORE_REGSIZE;
350 if (offset + xfer > TYPE_LENGTH (type))
351 xfer = TYPE_LENGTH (type) - offset;
352 score_xfer_register (regcache, regnum, xfer, TARGET_BYTE_ORDER,
353 readbuf, writebuf, offset);
354 }
355 return RETURN_VALUE_REGISTER_CONVENTION;
356 }
357}
358
359static struct frame_id
360score_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
361{
362 return frame_id_build (
363 frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM),
364 frame_pc_unwind (next_frame));
365}
366
367static int
368score_type_needs_double_align (struct type *type)
369{
370 enum type_code typecode = TYPE_CODE (type);
371
372 if (typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
373 return 1;
374 if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
375 return 1;
376 else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
377 {
378 int i, n;
379
380 n = TYPE_NFIELDS (type);
381 for (i = 0; i < n; i++)
382 if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
383 return 1;
384 return 0;
385 }
386 return 0;
387}
388
389static CORE_ADDR
390score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
391 struct regcache *regcache, CORE_ADDR bp_addr,
392 int nargs, struct value **args, CORE_ADDR sp,
393 int struct_return, CORE_ADDR struct_addr)
394{
395 int argnum;
396 int argreg;
397 int arglen = 0;
398 CORE_ADDR stack_offset = 0;
399 CORE_ADDR addr = 0;
400
401 /* Step 1, Save RA. */
402 regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
403
404 /* Step 2, Make space on the stack for the args. */
405 struct_addr = align_down (struct_addr, 16);
406 sp = align_down (sp, 16);
407 for (argnum = 0; argnum < nargs; argnum++)
408 arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
409 SCORE_REGSIZE);
410 sp -= align_up (arglen, 16);
411
412 argreg = SCORE_BEGIN_ARG_REGNUM;
413
414 /* Step 3, Check if struct return then save the struct address to r4 and
415 increase the stack_offset by 4. */
416 if (struct_return)
417 {
418 regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
419 stack_offset += SCORE_REGSIZE;
420 }
421
422 /* Step 4, Load arguments:
423 If arg length is too long (> 4 bytes),
424 then split the arg and save every parts. */
425 for (argnum = 0; argnum < nargs; argnum++)
426 {
427 struct value *arg = args[argnum];
428 struct type *arg_type = check_typedef (value_type (arg));
27fd2f50
Q
429 enum type_code typecode = TYPE_CODE (arg_type);
430 const gdb_byte *val = value_contents (arg);
431 int downward_offset = 0;
1cfd2c3e
JB
432 int odd_sized_struct_p;
433 int arg_last_part_p = 0;
27fd2f50 434
1cfd2c3e
JB
435 arglen = TYPE_LENGTH (arg_type);
436 odd_sized_struct_p = (arglen > SCORE_REGSIZE
27fd2f50 437 && arglen % SCORE_REGSIZE != 0);
27fd2f50
Q
438
439 /* If a arg should be aligned to 8 bytes (long long or double),
440 the value should be put to even register numbers. */
441 if (score_type_needs_double_align (arg_type))
442 {
443 if (argreg & 1)
444 argreg++;
445 }
446
447 /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
448 the default "downward"/"upward" method:
449
450 Example:
451
452 struct struc
453 {
454 char a; char b; char c;
455 } s = {'a', 'b', 'c'};
456
457 Big endian: s = {X, 'a', 'b', 'c'}
458 Little endian: s = {'a', 'b', 'c', X}
459
460 Where X is a hole. */
461
462 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
463 && (typecode == TYPE_CODE_STRUCT
464 || typecode == TYPE_CODE_UNION)
465 && argreg > SCORE_LAST_ARG_REGNUM
466 && arglen < SCORE_REGSIZE)
467 downward_offset += (SCORE_REGSIZE - arglen);
468
469 while (arglen > 0)
470 {
471 int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
472 ULONGEST regval = extract_unsigned_integer (val, partial_len);
473
474 /* The last part of a arg should shift left when
475 TARGET_BYTE_ORDER is BFD_ENDIAN_BIG. */
476 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
477 && arg_last_part_p == 1
478 && (typecode == TYPE_CODE_STRUCT
479 || typecode == TYPE_CODE_UNION))
480 regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
481
482 /* Always increase the stack_offset and save args to stack. */
483 addr = sp + stack_offset + downward_offset;
484 write_memory (addr, val, partial_len);
485
486 if (argreg <= SCORE_LAST_ARG_REGNUM)
487 {
488 regcache_cooked_write_unsigned (regcache, argreg++, regval);
489 if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
490 arg_last_part_p = 1;
491 }
492
493 val += partial_len;
494 arglen -= partial_len;
495 stack_offset += align_up (partial_len, SCORE_REGSIZE);
496 }
497 }
498
499 /* Step 5, Save SP. */
500 regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
501
502 return sp;
503}
504
505static inst_t *
506score_fetch_instruction (CORE_ADDR addr)
507{
508 static inst_t inst = { 0, 0 };
509 char buf[SCORE_INSTLEN];
510 int big;
511 int ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
512 unsigned int raw;
513
514 if (ret)
515 {
516 memory_error (ret, addr);
517 return 0;
518 }
519 inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
520 inst.is15 = !(inst.raw & 0x80008000);
521 inst.v = RM_PBITS (inst.raw);
522 big = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
523
524 if (inst.is15)
525 {
526 if (big ^ ((addr & 0x2) == 2))
527 inst.v = G_FLD (inst.v, 29, 15);
528 else
529 inst.v = G_FLD (inst.v, 14, 0);
530 }
531 return &inst;
532}
533
534static CORE_ADDR
535score_skip_prologue (CORE_ADDR pc)
536{
537 CORE_ADDR cpc = pc;
538 int iscan = 32, stack_sub = 0;
539 while (iscan-- > 0)
540 {
541 inst_t *inst = score_fetch_instruction (cpc);
542 if (!inst)
543 break;
544 if (!inst->is15 && !stack_sub
545 && (G_FLD (inst->v, 29, 25) == 0x1
546 && G_FLD (inst->v, 24, 20) == 0x0))
547 {
548 /* addi r0, offset */
549 pc = stack_sub = cpc + SCORE_INSTLEN;
550 }
551 else if (!inst->is15
552 && inst->v == RM_PBITS (0x8040bc56))
553 {
554 /* mv r2, r0 */
555 pc = cpc + SCORE_INSTLEN;
556 break;
557 }
558 else if (inst->is15
559 && inst->v == RM_PBITS (0x0203))
560 {
561 /* mv! r2, r0 */
562 pc = cpc + SCORE16_INSTLEN;
563 break;
564 }
565 else if (inst->is15
566 && ((G_FLD (inst->v, 14, 12) == 3) /* j15 form */
567 || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
568 || (G_FLD (inst->v, 14, 12) == 0x0
569 && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
570 break;
571 else if (!inst->is15
572 && ((G_FLD (inst->v, 29, 25) == 2) /* j32 form */
573 || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
574 || (G_FLD (inst->v, 29, 25) == 0x0
575 && G_FLD (inst->v, 6, 1) == 0x4))) /* br */
576 break;
577
578 cpc += inst->is15 ? SCORE16_INSTLEN : SCORE_INSTLEN;
579 }
580 return pc;
581}
582
583static int
584score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
585{
586 inst_t *inst = score_fetch_instruction (cur_pc);
587
588 if (inst->v == 0x23)
589 return 1; /* mv! r0, r2 */
590 else if (G_FLD (inst->v, 14, 12) == 0x2
591 && G_FLD (inst->v, 3, 0) == 0xa)
592 return 1; /* pop! */
593 else if (G_FLD (inst->v, 14, 12) == 0x0
594 && G_FLD (inst->v, 7, 0) == 0x34)
595 return 1; /* br! r3 */
596 else if (G_FLD (inst->v, 29, 15) == 0x2
597 && G_FLD (inst->v, 6, 1) == 0x2b)
598 return 1; /* mv r0, r2 */
599 else if (G_FLD (inst->v, 29, 25) == 0x0
600 && G_FLD (inst->v, 6, 1) == 0x4
601 && G_FLD (inst->v, 19, 15) == 0x3)
602 return 1; /* br r3 */
603 else
604 return 0;
605}
606
607static void
608score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
609 struct frame_info *next_frame,
610 struct score_frame_cache *this_cache)
611{
612 CORE_ADDR sp;
613 CORE_ADDR cur_pc = startaddr;
614
615 int sp_offset = 0;
616 int ra_offset = 0;
617 int fp_offset = 0;
618 int ra_offset_p = 0;
619 int fp_offset_p = 0;
620 int inst_len = 0;
621
622 sp = frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
623
624 for (; cur_pc < pc; cur_pc += inst_len)
625 {
626 inst_t *inst = score_fetch_instruction (cur_pc);
627 if (inst->is15 == 1)
628 {
629 inst_len = SCORE16_INSTLEN;
630
631 if (G_FLD (inst->v, 14, 12) == 0x2
632 && G_FLD (inst->v, 3, 0) == 0xe)
633 {
634 /* push! */
635 sp_offset += 4;
636
637 if (G_FLD (inst->v, 11, 7) == 0x6
638 && ra_offset_p == 0)
639 {
640 /* push! r3, [r0] */
641 ra_offset = sp_offset;
642 ra_offset_p = 1;
643 }
644 else if (G_FLD (inst->v, 11, 7) == 0x4
645 && fp_offset_p == 0)
646 {
647 /* push! r2, [r0] */
648 fp_offset = sp_offset;
649 fp_offset_p = 1;
650 }
651 }
652 else if (G_FLD (inst->v, 14, 12) == 0x2
653 && G_FLD (inst->v, 3, 0) == 0xa)
654 {
655 /* pop! */
656 sp_offset -= 4;
657 }
658 else if (G_FLD (inst->v, 14, 7) == 0xc1
659 && G_FLD (inst->v, 2, 0) == 0x0)
660 {
661 /* subei! r0, n */
662 sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
663 }
664 else if (G_FLD (inst->v, 14, 7) == 0xc0
665 && G_FLD (inst->v, 2, 0) == 0x0)
666 {
667 /* addei! r0, n */
668 sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
669 }
670 }
671 else
672 {
673 inst_len = SCORE_INSTLEN;
674
675 if (G_FLD (inst->v, 29, 15) == 0xc60
676 && G_FLD (inst->v, 2, 0) == 0x4)
677 {
678 /* sw r3, [r0, offset]+ */
679 sp_offset += SCORE_INSTLEN;
680 if (ra_offset_p == 0)
681 {
682 ra_offset = sp_offset;
683 ra_offset_p = 1;
684 }
685 }
686 if (G_FLD (inst->v, 29, 15) == 0xc40
687 && G_FLD (inst->v, 2, 0) == 0x4)
688 {
689 /* sw r2, [r0, offset]+ */
690 sp_offset += SCORE_INSTLEN;
691 if (fp_offset_p == 0)
692 {
693 fp_offset = sp_offset;
694 fp_offset_p = 1;
695 }
696 }
697 else if (G_FLD (inst->v, 29, 15) == 0x1c60
698 && G_FLD (inst->v, 2, 0) == 0x0)
699 {
700 /* lw r3, [r0]+, 4 */
701 sp_offset -= SCORE_INSTLEN;
702 ra_offset_p = 1;
703 }
704 else if (G_FLD (inst->v, 29, 15) == 0x1c40
705 && G_FLD (inst->v, 2, 0) == 0x0)
706 {
707 /* lw r2, [r0]+, 4 */
708 sp_offset -= SCORE_INSTLEN;
709 fp_offset_p = 1;
710 }
711
712 else if (G_FLD (inst->v, 29, 17) == 0x100
713 && G_FLD (inst->v, 0, 0) == 0x0)
714 {
715 /* addi r0, -offset */
716 sp_offset += 65536 - G_FLD (inst->v, 16, 1);
717 }
718 else if (G_FLD (inst->v, 29, 17) == 0x110
719 && G_FLD (inst->v, 0, 0) == 0x0)
720 {
721 /* addi r2, offset */
722 if (pc - cur_pc > 4)
723 {
724 unsigned int save_v = inst->v;
725 inst_t *inst2 =
726 score_fetch_instruction (cur_pc + SCORE_INSTLEN);
727 if (inst2->v == 0x23)
728 /* mv! r0, r2 */
729 sp_offset -= G_FLD (save_v, 16, 1);
730 }
731 }
732 }
733 }
734
735 /* Save RA. */
736 if (ra_offset_p == 1)
737 {
738 if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
739 this_cache->saved_regs[SCORE_PC_REGNUM].addr =
740 sp + sp_offset - ra_offset;
741 }
742 else
743 {
744 this_cache->saved_regs[SCORE_PC_REGNUM] =
745 this_cache->saved_regs[SCORE_RA_REGNUM];
746 }
747
748 /* Save FP. */
749 if (fp_offset_p == 1)
750 {
751 if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
752 this_cache->saved_regs[SCORE_FP_REGNUM].addr =
753 sp + sp_offset - fp_offset;
754 }
755
756 /* Save SP. */
757 this_cache->base =
758 frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM) + sp_offset;
759}
760
761static struct score_frame_cache *
762score_make_prologue_cache (struct frame_info *next_frame, void **this_cache)
763{
764 struct score_frame_cache *cache;
765
766 if ((*this_cache) != NULL)
767 return (*this_cache);
768
769 cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
770 (*this_cache) = cache;
771 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
772
773 /* Analyze the prologue. */
774 {
775 const CORE_ADDR pc = frame_pc_unwind (next_frame);
776 CORE_ADDR start_addr;
777
778 find_pc_partial_function (pc, NULL, &start_addr, NULL);
779 if (start_addr == 0)
780 return cache;
781 score_analyze_prologue (start_addr, pc, next_frame, *this_cache);
782 }
783
784 /* Save SP. */
785 trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
786
787 return (*this_cache);
788}
789
790static void
791score_prologue_this_id (struct frame_info *next_frame, void **this_cache,
792 struct frame_id *this_id)
793{
794 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
795 this_cache);
93d42b30
DJ
796 (*this_id) = frame_id_build (info->base,
797 frame_func_unwind (next_frame, NORMAL_FRAME));
27fd2f50
Q
798}
799
800static void
801score_prologue_prev_register (struct frame_info *next_frame,
802 void **this_cache,
803 int regnum, int *optimizedp,
804 enum lval_type *lvalp, CORE_ADDR * addrp,
805 int *realnump, gdb_byte * valuep)
806{
807 struct score_frame_cache *info = score_make_prologue_cache (next_frame,
808 this_cache);
809 trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
810 optimizedp, lvalp, addrp, realnump, valuep);
811}
812
813static const struct frame_unwind score_prologue_unwind =
814{
815 NORMAL_FRAME,
816 score_prologue_this_id,
817 score_prologue_prev_register
818};
819
820static const struct frame_unwind *
821score_prologue_sniffer (struct frame_info *next_frame)
822{
823 return &score_prologue_unwind;
824}
825
826static CORE_ADDR
827score_prologue_frame_base_address (struct frame_info *next_frame,
828 void **this_cache)
829{
830 struct score_frame_cache *info =
831 score_make_prologue_cache (next_frame, this_cache);
832 return info->base;
833}
834
835static const struct frame_base score_prologue_frame_base =
836{
837 &score_prologue_unwind,
838 score_prologue_frame_base_address,
839 score_prologue_frame_base_address,
840 score_prologue_frame_base_address,
841};
842
843static const struct frame_base *
844score_prologue_frame_base_sniffer (struct frame_info *next_frame)
845{
846 return &score_prologue_frame_base;
847}
848
849static struct gdbarch *
850score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
851{
852 struct gdbarch *gdbarch;
853
854 arches = gdbarch_list_lookup_by_info (arches, &info);
855 if (arches != NULL)
856 {
857 return (arches->gdbarch);
858 }
859 gdbarch = gdbarch_alloc (&info, 0);
860
861 set_gdbarch_short_bit (gdbarch, 16);
862 set_gdbarch_int_bit (gdbarch, 32);
863 set_gdbarch_float_bit (gdbarch, 32);
864 set_gdbarch_double_bit (gdbarch, 64);
865 set_gdbarch_long_double_bit (gdbarch, 64);
866 set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
867 set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
868 set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
869 set_gdbarch_num_regs (gdbarch, SCORE_NUM_REGS);
870 set_gdbarch_register_name (gdbarch, score_register_name);
871 set_gdbarch_breakpoint_from_pc (gdbarch, score_breakpoint_from_pc);
872 set_gdbarch_register_type (gdbarch, score_register_type);
873 set_gdbarch_frame_align (gdbarch, score_frame_align);
874 set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
27fd2f50 875 set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
30244cd8 876 set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
27fd2f50
Q
877 set_gdbarch_print_insn (gdbarch, score_print_insn);
878 set_gdbarch_skip_prologue (gdbarch, score_skip_prologue);
879 set_gdbarch_in_function_epilogue_p (gdbarch, score_in_function_epilogue_p);
880 set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
881 set_gdbarch_return_value (gdbarch, score_return_value);
882 set_gdbarch_unwind_dummy_id (gdbarch, score_unwind_dummy_id);
883 set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
884
885 frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
886 frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
887 frame_unwind_append_sniffer (gdbarch, score_prologue_sniffer);
888 frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
889
890 return gdbarch;
891}
892
893extern initialize_file_ftype _initialize_score_tdep;
894
895void
896_initialize_score_tdep (void)
897{
898 gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
899}
This page took 0.137439 seconds and 4 git commands to generate.