2007-05-31 Markus Deuling <deuling@de.ibm.com>
[external/binutils.git] / gdb / score-tdep.c
1 /* Target-dependent code for the S+core architecture, for GDB,
2    the GNU Debugger.
3
4    Copyright (C) 2006, 2007 Free Software Foundation, Inc.
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
45 typedef struct{
46     unsigned int v;
47     unsigned int raw;
48     char         is15;
49 }inst_t;
50
51 struct score_frame_cache
52 {
53   CORE_ADDR base;
54   CORE_ADDR fp;
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
76 typedef struct frame_extra_info
77 {
78   CORE_ADDR p_frame;
79   unsigned int pdr[P_SIZE];
80 } extra_info_t;
81
82 struct obj_priv
83 {
84   bfd_size_type size;
85   char *contents;
86 };
87
88 static bfd *the_bfd;
89
90 static int
91 score_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
103 static void
104 score_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     {
119       error ("Error: Can't find section in file:%s, line:%d!",
120              __FILE__, __LINE__);
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
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
187 #if 0
188 /* Open these functions if build with simulator.  */
189
190 int
191 score_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
203 int
204 score_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
216 int
217 score_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
229 int
230 score_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
242 int
243 score_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
255 int
256 score_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
269 static struct type *
270 score_register_type (struct gdbarch *gdbarch, int regnum)
271 {
272   gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
273   return builtin_type_uint32;
274 }
275
276 static CORE_ADDR
277 score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
278 {
279   return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
280 }
281
282 static CORE_ADDR
283 score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
284 {
285   return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
286 }
287
288 static const char *
289 score_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
309 static int
310 score_register_sim_regno (int regnum)
311 {
312   gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS);
313   return regnum;
314 }
315
316 static int
317 score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
318 {
319   if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
320     return print_insn_big_score (memaddr, info);
321   else
322     return print_insn_little_score (memaddr, info);
323 }
324
325 static const gdb_byte *
326 score_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     {
334       error ("Error: target_read_memory in file:%s, line:%d!",
335              __FILE__, __LINE__);
336     }
337   raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
338
339   if (gdbarch_byte_order (current_gdbarch) == 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
379 static CORE_ADDR
380 score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
381 {
382   return align_down (addr, 16);
383 }
384
385 static void
386 score_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:
405       error ("Error: score_xfer_register in file:%s, line:%d!",
406              __FILE__, __LINE__);
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
417 static enum return_value_convention
418 score_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,
438                                gdbarch_byte_order (current_gdbarch),
439                                readbuf, writebuf, offset);
440         }
441       return RETURN_VALUE_REGISTER_CONVENTION;
442     }
443 }
444
445 static struct frame_id
446 score_unwind_dummy_id (struct gdbarch *gdbarch,
447                        struct frame_info *next_frame)
448 {
449   return frame_id_build (
450            frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM),
451            frame_pc_unwind (next_frame));
452 }
453
454 static int
455 score_type_needs_double_align (struct type *type)
456 {
457   enum type_code typecode = TYPE_CODE (type);
458
459   if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
460       || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
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
475 static CORE_ADDR
476 score_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
500   /* Step 3, Check if struct return then save the struct address to
501      r4 and increase the stack_offset by 4.  */
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:
509      If arg length is too long (> 4 bytes), then split the arg and
510      save every parts.  */
511   for (argnum = 0; argnum < nargs; argnum++)
512     {
513       struct value *arg = args[argnum];
514       struct type *arg_type = check_typedef (value_type (arg));
515       enum type_code typecode = TYPE_CODE (arg_type);
516       const gdb_byte *val = value_contents (arg);
517       int downward_offset = 0;
518       int odd_sized_struct_p;
519       int arg_last_part_p = 0;
520
521       arglen = TYPE_LENGTH (arg_type);
522       odd_sized_struct_p = (arglen > SCORE_REGSIZE
523                             && arglen % SCORE_REGSIZE != 0);
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
548       if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
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
561              gdbarch_byte_order is BFD_ENDIAN_BIG.  */
562           if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
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
591 static char *
592 score_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
618 static void
619 score_free_memblock (char *memblock)
620 {
621   xfree (memblock);
622 }
623
624 static void
625 score_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
644 static inst_t *
645 score_fetch_inst (CORE_ADDR addr, char *memblock)
646 {
647   static inst_t inst = { 0, 0 };
648   char buf[SCORE_INSTLEN] = { 0 };
649   int big;
650   int ret;
651
652   if (target_has_execution && memblock != NULL)
653     {
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         }
667     }
668
669   inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN);
670   inst.is15 = !(inst.raw & 0x80008000);
671   inst.v = RM_PBITS (inst.raw);
672   big = (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG);
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
683 static CORE_ADDR
684 score_skip_prologue (CORE_ADDR pc)
685 {
686   CORE_ADDR cpc = pc;
687   int iscan = 32, stack_sub = 0;
688   while (iscan-- > 0)
689     {
690       inst_t *inst = score_fetch_inst (cpc, NULL);
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
732 static int
733 score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
734 {
735   inst_t *inst = score_fetch_inst (cur_pc, NULL);
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
756 static void
757 score_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;
762   CORE_ADDR fp;
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
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
780   sp = frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
781   fp = frame_unwind_register_unsigned (next_frame, SCORE_FP_REGNUM);
782
783   for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
784     {
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
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 =
899                     score_fetch_inst (cur_pc + SCORE_INSTLEN, NULL);
900                   if (inst2->v == 0x23)
901                     {
902                       /* mv! r0, r2 */
903                       sp_offset -= G_FLD (save_v, 16, 1);
904                     }
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
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);
938 }
939
940 static struct score_frame_cache *
941 score_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
969 static void
970 score_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);
975   (*this_id) = frame_id_build (info->base,
976                                frame_func_unwind (next_frame, NORMAL_FRAME));
977 }
978
979 static void
980 score_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
992 static const struct frame_unwind score_prologue_unwind =
993 {
994   NORMAL_FRAME,
995   score_prologue_this_id,
996   score_prologue_prev_register
997 };
998
999 static const struct frame_unwind *
1000 score_prologue_sniffer (struct frame_info *next_frame)
1001 {
1002   return &score_prologue_unwind;
1003 }
1004
1005 static CORE_ADDR
1006 score_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);
1011   return info->fp;
1012 }
1013
1014 static 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
1022 static const struct frame_base *
1023 score_prologue_frame_base_sniffer (struct frame_info *next_frame)
1024 {
1025   return &score_prologue_frame_base;
1026 }
1027
1028 static struct gdbarch *
1029 score_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);
1054   set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
1055   set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
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);
1059
1060   /* Watchpoint hooks.  */
1061   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
1062
1063   /* Dummy frame hooks.  */
1064   set_gdbarch_return_value (gdbarch, score_return_value);
1065   set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
1066   set_gdbarch_unwind_dummy_id (gdbarch, score_unwind_dummy_id);
1067   set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
1068
1069   /* Normal frame hooks.  */
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
1078 extern initialize_file_ftype _initialize_score_tdep;
1079
1080 void
1081 _initialize_score_tdep (void)
1082 {
1083   gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
1084 }