GDB (API)
/home/stan/gdb/src/gdb/score-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for the S+core architecture, for GDB,
00002    the GNU Debugger.
00003 
00004    Copyright (C) 2006-2013 Free Software Foundation, Inc.
00005 
00006    Contributed by Qinwei (qinwei@sunnorth.com.cn)
00007    Contributed by Ching-Peng Lin (cplin@sunplus.com)
00008 
00009    This file is part of GDB.
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; either version 3 of the License, or
00014    (at your option) any later version.
00015 
00016    This program is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019    GNU General Public License for more details.
00020 
00021    You should have received a copy of the GNU General Public License
00022    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00023 
00024 #include "defs.h"
00025 #include "gdb_assert.h"
00026 #include "inferior.h"
00027 #include "symtab.h"
00028 #include "objfiles.h"
00029 #include "gdbcore.h"
00030 #include "target.h"
00031 #include "arch-utils.h"
00032 #include "regcache.h"
00033 #include "regset.h"
00034 #include "dis-asm.h"
00035 #include "frame-unwind.h"
00036 #include "frame-base.h"
00037 #include "trad-frame.h"
00038 #include "dwarf2-frame.h"
00039 #include "score-tdep.h"
00040 
00041 #define G_FLD(_i,_ms,_ls) \
00042     ((unsigned)((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls)))
00043 
00044 typedef struct{
00045   unsigned long long v;
00046   unsigned long long raw;
00047   unsigned int len;
00048 }inst_t;
00049 
00050 struct score_frame_cache
00051 {
00052   CORE_ADDR base;
00053   CORE_ADDR fp;
00054   struct trad_frame_saved_reg *saved_regs;
00055 };
00056 
00057 static int target_mach = bfd_mach_score7;
00058 
00059 static struct type *
00060 score_register_type (struct gdbarch *gdbarch, int regnum)
00061 {
00062   gdb_assert (regnum >= 0 
00063               && regnum < ((target_mach == bfd_mach_score7)
00064                            ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
00065   return builtin_type (gdbarch)->builtin_uint32;
00066 }
00067 
00068 static CORE_ADDR
00069 score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
00070 {
00071   return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
00072 }
00073 
00074 static CORE_ADDR
00075 score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
00076 {
00077   return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
00078 }
00079 
00080 static const char *
00081 score7_register_name (struct gdbarch *gdbarch, int regnum)
00082 {
00083   const char *score_register_names[] = {
00084     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
00085     "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
00086     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
00087     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
00088 
00089     "PSR",     "COND",  "ECR",     "EXCPVEC", "CCR",
00090     "EPC",     "EMA",   "TLBLOCK", "TLBPT",   "PEADDR",
00091     "TLBRPT",  "PEVN",  "PECTX",   "LIMPFN",  "LDMPFN", 
00092     "PREV",    "DREG",  "PC",      "DSAVE",   "COUNTER",
00093     "LDCR",    "STCR",  "CEH",     "CEL",
00094   };
00095 
00096   gdb_assert (regnum >= 0 && regnum < SCORE7_NUM_REGS);
00097   return score_register_names[regnum];
00098 }
00099 
00100 static const char *
00101 score3_register_name (struct gdbarch *gdbarch, int regnum)
00102 {
00103   const char *score_register_names[] = {
00104     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
00105     "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
00106     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
00107     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
00108 
00109     "PSR",      "COND",   "ECR",   "EXCPVEC",  "CCR",
00110     "EPC",      "EMA",    "PREV",  "DREG",     "DSAVE",
00111     "COUNTER",  "LDCR",   "STCR",  "CEH",      "CEL",
00112     "",         "",       "PC",
00113   };
00114 
00115   gdb_assert (regnum >= 0 && regnum < SCORE3_NUM_REGS);
00116   return score_register_names[regnum];
00117 }
00118 
00119 #if WITH_SIM
00120 static int
00121 score_register_sim_regno (struct gdbarch *gdbarch, int regnum)
00122 {
00123   gdb_assert (regnum >= 0 
00124               && regnum < ((target_mach == bfd_mach_score7)
00125                            ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
00126   return regnum;
00127 }
00128 #endif
00129 
00130 static int
00131 score_print_insn (bfd_vma memaddr, struct disassemble_info *info)
00132 {
00133   if (info->endian == BFD_ENDIAN_BIG)
00134     return print_insn_big_score (memaddr, info);
00135   else
00136     return print_insn_little_score (memaddr, info);
00137 }
00138 
00139 static inst_t *
00140 score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, gdb_byte *memblock)
00141 {
00142   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00143   static inst_t inst = { 0, 0, 0 };
00144   gdb_byte buf[SCORE_INSTLEN] = { 0 };
00145   int big;
00146   int ret;
00147 
00148   if (target_has_execution && memblock != NULL)
00149     {
00150       /* Fetch instruction from local MEMBLOCK.  */
00151       memcpy (buf, memblock, SCORE_INSTLEN);
00152     }
00153   else
00154     {
00155       /* Fetch instruction from target.  */
00156       ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN);
00157       if (ret)
00158         {
00159           error (_("Error: target_read_memory in file:%s, line:%d!"),
00160                   __FILE__, __LINE__);
00161           return 0;
00162         }
00163     }
00164 
00165   inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
00166   inst.len = (inst.raw & 0x80008000) ? 4 : 2;
00167   inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF); 
00168   big = (byte_order == BFD_ENDIAN_BIG);
00169   if (inst.len == 2)
00170     {
00171       if (big ^ ((addr & 0x2) == 2))
00172         inst.v = G_FLD (inst.v, 29, 15);
00173       else
00174         inst.v = G_FLD (inst.v, 14, 0);
00175     }
00176   return &inst;
00177 }
00178 
00179 static inst_t *
00180 score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr,
00181                                  enum bfd_endian byte_order)
00182 {
00183   static inst_t inst = { 0, 0, 0 };
00184 
00185   struct breakplace
00186   {
00187     int break_offset;
00188     int inst_len;
00189   };
00190   /*     raw        table 1 (column 2, 3, 4)
00191     *  0  1  0  *   # 2
00192     *  0  1  1  0   # 3
00193     0  1  1  0  *   # 6
00194                     table 2 (column 1, 2, 3)
00195     *  0  0  *  *   # 0, 4
00196     0  1  0  *  *   # 2
00197     1  1  0  *  *   # 6
00198    */
00199 
00200   static const struct breakplace bk_table[16] =
00201     {
00202       /* table 1 */
00203       {0, 0},
00204       {0, 0},
00205       {0, 4},
00206       {0, 6},
00207       {0, 0},
00208       {0, 0},
00209       {-2, 6},
00210       {0, 0},
00211       /* table 2 */
00212       {0, 2},
00213       {0, 0},
00214       {-2, 4},
00215       {0, 0},
00216       {0, 2},
00217       {0, 0},
00218       {-4, 6},
00219       {0, 0}
00220     };
00221 
00222 #define EXTRACT_LEN 2
00223   CORE_ADDR adjust_pc = *pcptr & ~0x1;
00224   gdb_byte buf[5][EXTRACT_LEN] =
00225     {
00226       {'\0', '\0'},
00227       {'\0', '\0'},
00228       {'\0', '\0'},
00229       {'\0', '\0'},
00230       {'\0', '\0'}
00231     };
00232   int ret;
00233   unsigned int raw;
00234   unsigned int cbits = 0;
00235   int bk_index;
00236   int i, count;
00237 
00238   inst.v = 0;
00239   inst.raw = 0;
00240   inst.len = 0;
00241 
00242   adjust_pc -= 4;
00243   for (i = 0; i < 5; i++)
00244     {
00245       ret = target_read_memory (adjust_pc + 2 * i, buf[i], EXTRACT_LEN);
00246       if (ret != 0)
00247         {
00248           buf[i][0] = '\0';
00249           buf[i][1] = '\0';
00250           if (i == 2)
00251             error (_("Error: target_read_memory in file:%s, line:%d!"),
00252                    __FILE__, __LINE__);
00253         }
00254 
00255       raw = extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
00256       cbits = (cbits << 1) | (raw >> 15); 
00257     }
00258   adjust_pc += 4;
00259 
00260   if (cbits & 0x4)
00261     {
00262       /* table 1 */
00263       cbits = (cbits >> 1) & 0x7;
00264       bk_index = cbits;
00265     }
00266   else
00267     {
00268       /* table 2 */
00269       cbits = (cbits >> 2) & 0x7;
00270       bk_index = cbits + 8; 
00271     }
00272 
00273   gdb_assert (!((bk_table[bk_index].break_offset == 0)
00274                 && (bk_table[bk_index].inst_len == 0)));
00275 
00276   inst.len = bk_table[bk_index].inst_len;
00277 
00278   i = (bk_table[bk_index].break_offset + 4) / 2;
00279   count = inst.len / 2;
00280   for (; count > 0; i++, count--)
00281     {
00282       inst.raw = (inst.raw << 16)
00283                  | extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order);
00284     }
00285 
00286   switch (inst.len)
00287     {
00288     case 2:
00289       inst.v = inst.raw & 0x7FFF;
00290       break;
00291     case 4:
00292       inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
00293       break;
00294     case 6:
00295       inst.v = ((inst.raw >> 32 & 0x7FFF) << 30)
00296                | ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF);
00297       break;
00298     }
00299 
00300   if (pcptr)
00301     *pcptr = adjust_pc + bk_table[bk_index].break_offset;
00302   if (lenptr)
00303     *lenptr = bk_table[bk_index].inst_len;
00304 
00305 #undef EXTRACT_LEN
00306 
00307   return &inst;
00308 }
00309 
00310 static const gdb_byte *
00311 score7_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
00312                            int *lenptr)
00313 {
00314   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00315   gdb_byte buf[SCORE_INSTLEN] = { 0 };
00316   int ret;
00317   unsigned int raw;
00318 
00319   if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
00320     {
00321       error (_("Error: target_read_memory in file:%s, line:%d!"),
00322              __FILE__, __LINE__);
00323     }
00324   raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
00325 
00326   if (byte_order == BFD_ENDIAN_BIG)
00327     {
00328       if (!(raw & 0x80008000))
00329         {
00330           /* 16bits instruction.  */
00331           static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
00332           *pcptr &= ~0x1;
00333           *lenptr = sizeof (big_breakpoint16);
00334           return big_breakpoint16;
00335         }
00336       else
00337         {
00338           /* 32bits instruction.  */
00339           static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
00340           *pcptr &= ~0x3;
00341           *lenptr = sizeof (big_breakpoint32);
00342           return big_breakpoint32;
00343         }
00344     }
00345   else
00346     {
00347       if (!(raw & 0x80008000))
00348         {
00349           /* 16bits instruction.  */
00350           static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
00351           *pcptr &= ~0x1;
00352           *lenptr = sizeof (little_breakpoint16);
00353           return little_breakpoint16;
00354         }
00355       else
00356         {
00357           /* 32bits instruction.  */
00358           static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
00359           *pcptr &= ~0x3;
00360           *lenptr = sizeof (little_breakpoint32);
00361           return little_breakpoint32;
00362         }
00363     }
00364 }
00365 
00366 static const gdb_byte *
00367 score3_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
00368                            int *lenptr)
00369 {
00370   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00371   CORE_ADDR adjust_pc = *pcptr; 
00372   int len;
00373   static gdb_byte score_break_insns[6][6] = {
00374     /* The following three instructions are big endian.  */
00375     { 0x00, 0x20 },
00376     { 0x80, 0x00, 0x00, 0x06 },
00377     { 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 },
00378     /* The following three instructions are little endian.  */
00379     { 0x20, 0x00 },
00380     { 0x00, 0x80, 0x06, 0x00 },
00381     { 0x00, 0x80, 0x00, 0x80, 0x00, 0x00 }};
00382 
00383   gdb_byte *p = NULL;
00384   int index = 0;
00385 
00386   score3_adjust_pc_and_fetch_inst (&adjust_pc, &len, byte_order);
00387 
00388   index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (len / 2 - 1);
00389   p = score_break_insns[index];
00390 
00391   *pcptr = adjust_pc;
00392   *lenptr = len;
00393 
00394   return p;
00395 }
00396 
00397 static CORE_ADDR
00398 score_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
00399 {
00400   CORE_ADDR adjust_pc = bpaddr; 
00401 
00402   if (target_mach == bfd_mach_score3)
00403     score3_adjust_pc_and_fetch_inst (&adjust_pc, NULL,
00404                                      gdbarch_byte_order (gdbarch));
00405   else
00406     adjust_pc = align_down (adjust_pc, 2);
00407   
00408   return adjust_pc;
00409 }
00410 
00411 static CORE_ADDR
00412 score_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
00413 {
00414   return align_down (addr, 16);
00415 }
00416 
00417 static void
00418 score_xfer_register (struct regcache *regcache, int regnum, int length,
00419                      enum bfd_endian endian, gdb_byte *readbuf,
00420                      const gdb_byte *writebuf, int buf_offset)
00421 {
00422   int reg_offset = 0;
00423   gdb_assert (regnum >= 0 
00424               && regnum < ((target_mach == bfd_mach_score7)
00425                            ? SCORE7_NUM_REGS : SCORE3_NUM_REGS));
00426 
00427   switch (endian)
00428     {
00429     case BFD_ENDIAN_BIG:
00430       reg_offset = SCORE_REGSIZE - length;
00431       break;
00432     case BFD_ENDIAN_LITTLE:
00433       reg_offset = 0;
00434       break;
00435     case BFD_ENDIAN_UNKNOWN:
00436       reg_offset = 0;
00437       break;
00438     default:
00439       error (_("Error: score_xfer_register in file:%s, line:%d!"),
00440              __FILE__, __LINE__);
00441     }
00442 
00443   if (readbuf != NULL)
00444     regcache_cooked_read_part (regcache, regnum, reg_offset, length,
00445                                readbuf + buf_offset);
00446   if (writebuf != NULL)
00447     regcache_cooked_write_part (regcache, regnum, reg_offset, length,
00448                                 writebuf + buf_offset);
00449 }
00450 
00451 static enum return_value_convention
00452 score_return_value (struct gdbarch *gdbarch, struct value *function,
00453                     struct type *type, struct regcache *regcache,
00454                     gdb_byte * readbuf, const gdb_byte * writebuf)
00455 {
00456   if (TYPE_CODE (type) == TYPE_CODE_STRUCT
00457       || TYPE_CODE (type) == TYPE_CODE_UNION
00458       || TYPE_CODE (type) == TYPE_CODE_ARRAY)
00459     return RETURN_VALUE_STRUCT_CONVENTION;
00460   else
00461     {
00462       int offset;
00463       int regnum;
00464       for (offset = 0, regnum = SCORE_A0_REGNUM;
00465            offset < TYPE_LENGTH (type);
00466            offset += SCORE_REGSIZE, regnum++)
00467         {
00468           int xfer = SCORE_REGSIZE;
00469 
00470           if (offset + xfer > TYPE_LENGTH (type))
00471             xfer = TYPE_LENGTH (type) - offset;
00472           score_xfer_register (regcache, regnum, xfer,
00473                                gdbarch_byte_order(gdbarch),
00474                                readbuf, writebuf, offset);
00475         }
00476       return RETURN_VALUE_REGISTER_CONVENTION;
00477     }
00478 }
00479 
00480 static struct frame_id
00481 score_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
00482 {
00483   return frame_id_build (get_frame_register_unsigned (this_frame,
00484                                                       SCORE_SP_REGNUM),
00485                          get_frame_pc (this_frame));
00486 }
00487 
00488 static int
00489 score_type_needs_double_align (struct type *type)
00490 {
00491   enum type_code typecode = TYPE_CODE (type);
00492 
00493   if ((typecode == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
00494       || (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
00495     return 1;
00496   else if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
00497     {
00498       int i, n;
00499 
00500       n = TYPE_NFIELDS (type);
00501       for (i = 0; i < n; i++)
00502         if (score_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
00503           return 1;
00504       return 0;
00505     }
00506   return 0;
00507 }
00508 
00509 static CORE_ADDR
00510 score_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
00511                        struct regcache *regcache, CORE_ADDR bp_addr,
00512                        int nargs, struct value **args, CORE_ADDR sp,
00513                        int struct_return, CORE_ADDR struct_addr)
00514 {
00515   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00516   int argnum;
00517   int argreg;
00518   int arglen = 0;
00519   CORE_ADDR stack_offset = 0;
00520   CORE_ADDR addr = 0;
00521 
00522   /* Step 1, Save RA.  */
00523   regcache_cooked_write_unsigned (regcache, SCORE_RA_REGNUM, bp_addr);
00524 
00525   /* Step 2, Make space on the stack for the args.  */
00526   struct_addr = align_down (struct_addr, 16);
00527   sp = align_down (sp, 16);
00528   for (argnum = 0; argnum < nargs; argnum++)
00529     arglen += align_up (TYPE_LENGTH (value_type (args[argnum])),
00530                         SCORE_REGSIZE);
00531   sp -= align_up (arglen, 16);
00532 
00533   argreg = SCORE_BEGIN_ARG_REGNUM;
00534 
00535   /* Step 3, Check if struct return then save the struct address to
00536      r4 and increase the stack_offset by 4.  */
00537   if (struct_return)
00538     {
00539       regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
00540       stack_offset += SCORE_REGSIZE;
00541     }
00542 
00543   /* Step 4, Load arguments:
00544      If arg length is too long (> 4 bytes), then split the arg and
00545      save every parts.  */
00546   for (argnum = 0; argnum < nargs; argnum++)
00547     {
00548       struct value *arg = args[argnum];
00549       struct type *arg_type = check_typedef (value_type (arg));
00550       enum type_code typecode = TYPE_CODE (arg_type);
00551       const gdb_byte *val = value_contents (arg);
00552       int downward_offset = 0;
00553       int odd_sized_struct_p;
00554       int arg_last_part_p = 0;
00555 
00556       arglen = TYPE_LENGTH (arg_type);
00557       odd_sized_struct_p = (arglen > SCORE_REGSIZE
00558                             && arglen % SCORE_REGSIZE != 0);
00559 
00560       /* If a arg should be aligned to 8 bytes (long long or double),
00561          the value should be put to even register numbers.  */
00562       if (score_type_needs_double_align (arg_type))
00563         {
00564           if (argreg & 1)
00565             argreg++;
00566         }
00567 
00568       /* If sizeof a block < SCORE_REGSIZE, then Score GCC will chose
00569          the default "downward"/"upward" method:
00570 
00571          Example:
00572 
00573          struct struc
00574          {
00575            char a; char b; char c;
00576          } s = {'a', 'b', 'c'};
00577 
00578          Big endian:    s = {X, 'a', 'b', 'c'}
00579          Little endian: s = {'a', 'b', 'c', X}
00580 
00581          Where X is a hole.  */
00582 
00583       if (gdbarch_byte_order(gdbarch) == BFD_ENDIAN_BIG
00584           && (typecode == TYPE_CODE_STRUCT
00585               || typecode == TYPE_CODE_UNION)
00586           && argreg > SCORE_LAST_ARG_REGNUM
00587           && arglen < SCORE_REGSIZE)
00588         downward_offset += (SCORE_REGSIZE - arglen);
00589 
00590       while (arglen > 0)
00591         {
00592           int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE;
00593           ULONGEST regval = extract_unsigned_integer (val, partial_len,
00594                                                       byte_order);
00595 
00596           /* The last part of a arg should shift left when
00597              gdbarch_byte_order is BFD_ENDIAN_BIG.  */
00598           if (byte_order == BFD_ENDIAN_BIG
00599               && arg_last_part_p == 1
00600               && (typecode == TYPE_CODE_STRUCT
00601                   || typecode == TYPE_CODE_UNION))
00602             regval <<= ((SCORE_REGSIZE - partial_len) * TARGET_CHAR_BIT);
00603 
00604           /* Always increase the stack_offset and save args to stack.  */
00605           addr = sp + stack_offset + downward_offset;
00606           write_memory (addr, val, partial_len);
00607 
00608           if (argreg <= SCORE_LAST_ARG_REGNUM)
00609             {
00610               regcache_cooked_write_unsigned (regcache, argreg++, regval);
00611               if (arglen > SCORE_REGSIZE && arglen < SCORE_REGSIZE * 2)
00612                 arg_last_part_p = 1;
00613             }
00614 
00615           val += partial_len;
00616           arglen -= partial_len;
00617           stack_offset += align_up (partial_len, SCORE_REGSIZE);
00618         }
00619     }
00620 
00621   /* Step 5, Save SP.  */
00622   regcache_cooked_write_unsigned (regcache, SCORE_SP_REGNUM, sp);
00623 
00624   return sp;
00625 }
00626 
00627 static CORE_ADDR
00628 score7_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
00629 {
00630   CORE_ADDR cpc = pc;
00631   int iscan = 32, stack_sub = 0;
00632   while (iscan-- > 0)
00633     {
00634       inst_t *inst = score7_fetch_inst (gdbarch, cpc, NULL);
00635       if (!inst)
00636         break;
00637       if ((inst->len == 4) && !stack_sub
00638           && (G_FLD (inst->v, 29, 25) == 0x1
00639               && G_FLD (inst->v, 24, 20) == 0x0))
00640         {
00641           /* addi r0, offset */
00642           stack_sub = cpc + SCORE_INSTLEN;
00643           pc = cpc + SCORE_INSTLEN;
00644         }
00645       else if ((inst->len == 4)
00646                && (G_FLD (inst->v, 29, 25) == 0x0)
00647                && (G_FLD (inst->v, 24, 20) == 0x2)
00648                && (G_FLD (inst->v, 19, 15) == 0x0)
00649                && (G_FLD (inst->v, 14, 10) == 0xF)
00650                && (G_FLD (inst->v, 9, 0) == 0x56))
00651         {
00652           /* mv r2, r0  */
00653           pc = cpc + SCORE_INSTLEN;
00654           break;
00655         }
00656       else if ((inst->len == 2)
00657                && (G_FLD (inst->v, 14, 12) == 0x0)
00658                && (G_FLD (inst->v, 11, 8) == 0x2)
00659                && (G_FLD (inst->v, 7, 4) == 0x0)
00660                && (G_FLD (inst->v, 3, 0) == 0x3))
00661         {
00662           /* mv! r2, r0 */
00663           pc = cpc + SCORE16_INSTLEN;
00664           break;
00665         }
00666       else if ((inst->len == 2)
00667                && ((G_FLD (inst->v, 14, 12) == 3)    /* j15 form */
00668                    || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */
00669                    || (G_FLD (inst->v, 14, 12) == 0x0
00670                        && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */
00671         break;
00672       else if ((inst->len == 4)
00673                && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
00674                    || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */
00675                    || (G_FLD (inst->v, 29, 25) == 0x0
00676                        && G_FLD (inst->v, 6, 1) == 0x4)))  /* br */
00677         break;
00678 
00679       cpc += (inst->len == 2) ? SCORE16_INSTLEN : SCORE_INSTLEN;
00680     }
00681   return pc;
00682 }
00683 
00684 static CORE_ADDR
00685 score3_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
00686 {
00687   CORE_ADDR cpc = pc;
00688   int iscan = 32, stack_sub = 0;
00689   while (iscan-- > 0)
00690     {
00691       inst_t *inst
00692         = score3_adjust_pc_and_fetch_inst (&cpc, NULL,
00693                                            gdbarch_byte_order (gdbarch));
00694 
00695       if (!inst)
00696         break;
00697       if (inst->len == 4 && !stack_sub
00698           && (G_FLD (inst->v, 29, 25) == 0x1)
00699           && (G_FLD (inst->v, 19, 17) == 0x0)
00700           && (G_FLD (inst->v, 24, 20) == 0x0))
00701         {
00702           /* addi r0, offset */
00703           stack_sub = cpc + inst->len;
00704           pc = cpc + inst->len;
00705         }
00706       else if (inst->len == 4
00707                && (G_FLD (inst->v, 29, 25) == 0x0)
00708                && (G_FLD (inst->v, 24, 20) == 0x2)
00709                && (G_FLD (inst->v, 19, 15) == 0x0)
00710                && (G_FLD (inst->v, 14, 10) == 0xF)
00711                && (G_FLD (inst->v, 9, 0) == 0x56))
00712         {
00713           /* mv r2, r0  */
00714           pc = cpc + inst->len;
00715           break;
00716         }
00717       else if ((inst->len == 2)
00718                && (G_FLD (inst->v, 14, 10) == 0x10)
00719                && (G_FLD (inst->v, 9, 5) == 0x2)
00720                && (G_FLD (inst->v, 4, 0) == 0x0))
00721         {
00722           /* mv! r2, r0 */
00723           pc = cpc + inst->len;
00724           break;
00725         }
00726       else if (inst->len == 2
00727                && ((G_FLD (inst->v, 14, 12) == 3) /* b15 form */
00728                    || (G_FLD (inst->v, 14, 12) == 0x0
00729                        && G_FLD (inst->v, 11, 5) == 0x4))) /* br! */
00730         break;
00731       else if (inst->len == 4
00732                && ((G_FLD (inst->v, 29, 25) == 2)    /* j32 form */
00733                    || (G_FLD (inst->v, 29, 25) == 4))) /* b32 form */
00734         break;
00735 
00736       cpc += inst->len;
00737     }
00738   return pc;
00739 }
00740 
00741 static int
00742 score7_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
00743 {
00744   inst_t *inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
00745 
00746   if (inst->v == 0x23)
00747     return 1;   /* mv! r0, r2 */
00748   else if (G_FLD (inst->v, 14, 12) == 0x2
00749            && G_FLD (inst->v, 3, 0) == 0xa)
00750     return 1;   /* pop! */
00751   else if (G_FLD (inst->v, 14, 12) == 0x0
00752            && G_FLD (inst->v, 7, 0) == 0x34)
00753     return 1;   /* br! r3 */
00754   else if (G_FLD (inst->v, 29, 15) == 0x2
00755            && G_FLD (inst->v, 6, 1) == 0x2b)
00756     return 1;   /* mv r0, r2 */
00757   else if (G_FLD (inst->v, 29, 25) == 0x0
00758            && G_FLD (inst->v, 6, 1) == 0x4
00759            && G_FLD (inst->v, 19, 15) == 0x3)
00760     return 1;   /* br r3 */
00761   else
00762     return 0;
00763 }
00764 
00765 static int
00766 score3_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc)
00767 {
00768   CORE_ADDR pc = cur_pc;
00769   inst_t *inst
00770     = score3_adjust_pc_and_fetch_inst (&pc, NULL,
00771                                        gdbarch_byte_order (gdbarch));
00772 
00773   if (inst->len == 2
00774       && (G_FLD (inst->v, 14, 10) == 0x10)
00775       && (G_FLD (inst->v, 9, 5) == 0x0)
00776       && (G_FLD (inst->v, 4, 0) == 0x2))
00777     return 1;   /* mv! r0, r2 */
00778   else if (inst->len == 4
00779            && (G_FLD (inst->v, 29, 25) == 0x0)
00780            && (G_FLD (inst->v, 24, 20) == 0x2)
00781            && (G_FLD (inst->v, 19, 15) == 0x0)
00782            && (G_FLD (inst->v, 14, 10) == 0xF)
00783            && (G_FLD (inst->v, 9, 0) == 0x56))
00784     return 1;   /* mv r0, r2 */
00785   else if (inst->len == 2
00786            && (G_FLD (inst->v, 14, 12) == 0x0)
00787            && (G_FLD (inst->v, 11, 5) == 0x2))
00788     return 1;   /* pop! */
00789   else if (inst->len == 2
00790            && (G_FLD (inst->v, 14, 12) == 0x0)
00791            && (G_FLD (inst->v, 11, 7) == 0x0)
00792            && (G_FLD (inst->v, 6, 5) == 0x2))
00793     return 1;   /* rpop! */
00794   else if (inst->len == 2
00795            && (G_FLD (inst->v, 14, 12) == 0x0)
00796            && (G_FLD (inst->v, 11, 5) == 0x4)
00797            && (G_FLD (inst->v, 4, 0) == 0x3))
00798     return 1;   /* br! r3 */
00799   else if (inst->len == 4
00800            && (G_FLD (inst->v, 29, 25) == 0x0)
00801            && (G_FLD (inst->v, 24, 20) == 0x0)
00802            && (G_FLD (inst->v, 19, 15) == 0x3)
00803            && (G_FLD (inst->v, 14, 10) == 0xF)
00804            && (G_FLD (inst->v, 9, 0) == 0x8))
00805     return 1;   /* br r3 */
00806   else
00807     return 0;
00808 }
00809 
00810 static gdb_byte *
00811 score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size)
00812 {
00813   int ret;
00814   gdb_byte *memblock = NULL;
00815 
00816   if (size < 0)
00817     {
00818       error (_("Error: malloc size < 0 in file:%s, line:%d!"),
00819              __FILE__, __LINE__);
00820       return NULL;
00821     }
00822   else if (size == 0)
00823     return NULL;
00824 
00825   memblock = xmalloc (size);
00826   memset (memblock, 0, size);
00827   ret = target_read_memory (addr & ~0x3, memblock, size);
00828   if (ret)
00829     {
00830       error (_("Error: target_read_memory in file:%s, line:%d!"),
00831              __FILE__, __LINE__);
00832       return NULL;
00833     }
00834   return memblock;
00835 }
00836 
00837 static void
00838 score7_free_memblock (gdb_byte *memblock)
00839 {
00840   xfree (memblock);
00841 }
00842 
00843 static void
00844 score7_adjust_memblock_ptr (gdb_byte **memblock, CORE_ADDR prev_pc,
00845                            CORE_ADDR cur_pc)
00846 {
00847   if (prev_pc == -1)
00848     {
00849       /* First time call this function, do nothing.  */
00850     }
00851   else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0)
00852     {
00853       /* First 16-bit instruction, then 32-bit instruction.  */
00854       *memblock += SCORE_INSTLEN;
00855     }
00856   else if (cur_pc - prev_pc == 4)
00857     {
00858       /* Is 32-bit instruction, increase MEMBLOCK by 4.  */
00859       *memblock += SCORE_INSTLEN;
00860     }
00861 }
00862 
00863 static void
00864 score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
00865                         struct frame_info *this_frame,
00866                         struct score_frame_cache *this_cache)
00867 {
00868   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00869   CORE_ADDR sp;
00870   CORE_ADDR fp;
00871   CORE_ADDR cur_pc = startaddr;
00872 
00873   int sp_offset = 0;
00874   int ra_offset = 0;
00875   int fp_offset = 0;
00876   int ra_offset_p = 0;
00877   int fp_offset_p = 0;
00878   int inst_len = 0;
00879 
00880   gdb_byte *memblock = NULL;
00881   gdb_byte *memblock_ptr = NULL;
00882   CORE_ADDR prev_pc = -1;
00883 
00884   /* Allocate MEMBLOCK if PC - STARTADDR > 0.  */
00885   memblock_ptr = memblock =
00886     score7_malloc_and_get_memblock (startaddr, pc - startaddr);
00887 
00888   sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
00889   fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
00890 
00891   for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
00892     {
00893       inst_t *inst = NULL;
00894       if (memblock != NULL)
00895         {
00896           /* Reading memory block from target succefully and got all
00897              the instructions(from STARTADDR to PC) needed.  */
00898           score7_adjust_memblock_ptr (&memblock, prev_pc, cur_pc);
00899           inst = score7_fetch_inst (gdbarch, cur_pc, memblock);
00900         }
00901       else
00902         {
00903           /* Otherwise, we fetch 4 bytes from target, and GDB also
00904              work correctly.  */
00905           inst = score7_fetch_inst (gdbarch, cur_pc, NULL);
00906         }
00907 
00908       /* FIXME: make a full-power prologue analyzer.  */
00909       if (inst->len == 2)
00910         {
00911           inst_len = SCORE16_INSTLEN;
00912 
00913           if (G_FLD (inst->v, 14, 12) == 0x2
00914               && G_FLD (inst->v, 3, 0) == 0xe)
00915             {
00916               /* push! */
00917               sp_offset += 4;
00918 
00919               if (G_FLD (inst->v, 11, 7) == 0x6
00920                   && ra_offset_p == 0)
00921                 {
00922                   /* push! r3, [r0] */
00923                   ra_offset = sp_offset;
00924                   ra_offset_p = 1;
00925                 }
00926               else if (G_FLD (inst->v, 11, 7) == 0x4
00927                        && fp_offset_p == 0)
00928                 {
00929                   /* push! r2, [r0] */
00930                   fp_offset = sp_offset;
00931                   fp_offset_p = 1;
00932                 }
00933             }
00934           else if (G_FLD (inst->v, 14, 12) == 0x2
00935                    && G_FLD (inst->v, 3, 0) == 0xa)
00936             {
00937               /* pop! */
00938               sp_offset -= 4;
00939             }
00940           else if (G_FLD (inst->v, 14, 7) == 0xc1
00941                    && G_FLD (inst->v, 2, 0) == 0x0)
00942             {
00943               /* subei! r0, n */
00944               sp_offset += (int) pow (2, G_FLD (inst->v, 6, 3));
00945             }
00946           else if (G_FLD (inst->v, 14, 7) == 0xc0
00947                    && G_FLD (inst->v, 2, 0) == 0x0)
00948             {
00949               /* addei! r0, n */
00950               sp_offset -= (int) pow (2, G_FLD (inst->v, 6, 3));
00951             }
00952         }
00953       else
00954         {
00955           inst_len = SCORE_INSTLEN;
00956 
00957           if (G_FLD(inst->v, 29, 25) == 0x3
00958               && G_FLD(inst->v, 2, 0) == 0x4
00959               && G_FLD(inst->v, 19, 15) == 0)
00960             {
00961                 /* sw rD, [r0, offset]+ */
00962                 sp_offset += SCORE_INSTLEN;
00963 
00964                 if (G_FLD(inst->v, 24, 20) == 0x3)
00965                   {
00966                       /* rD = r3 */
00967                       if (ra_offset_p == 0)
00968                         {
00969                             ra_offset = sp_offset;
00970                             ra_offset_p = 1;
00971                         }
00972                   }
00973                 else if (G_FLD(inst->v, 24, 20) == 0x2)
00974                   {
00975                       /* rD = r2 */
00976                       if (fp_offset_p == 0)
00977                         {
00978                             fp_offset = sp_offset;
00979                             fp_offset_p = 1;
00980                         }
00981                   }
00982             }
00983           else if (G_FLD(inst->v, 29, 25) == 0x14
00984                    && G_FLD(inst->v, 19,15) == 0)
00985             {
00986                 /* sw rD, [r0, offset] */
00987                 if (G_FLD(inst->v, 24, 20) == 0x3)
00988                   {
00989                       /* rD = r3 */
00990                       ra_offset = sp_offset - G_FLD(inst->v, 14, 0);
00991                       ra_offset_p = 1;
00992                   }
00993                 else if (G_FLD(inst->v, 24, 20) == 0x2)
00994                   {
00995                       /* rD = r2 */
00996                       fp_offset = sp_offset - G_FLD(inst->v, 14, 0);
00997                       fp_offset_p = 1;
00998                   }
00999             }
01000           else if (G_FLD (inst->v, 29, 15) == 0x1c60
01001                    && G_FLD (inst->v, 2, 0) == 0x0)
01002             {
01003               /* lw r3, [r0]+, 4 */
01004               sp_offset -= SCORE_INSTLEN;
01005               ra_offset_p = 1;
01006             }
01007           else if (G_FLD (inst->v, 29, 15) == 0x1c40
01008                    && G_FLD (inst->v, 2, 0) == 0x0)
01009             {
01010               /* lw r2, [r0]+, 4 */
01011               sp_offset -= SCORE_INSTLEN;
01012               fp_offset_p = 1;
01013             }
01014 
01015           else if (G_FLD (inst->v, 29, 17) == 0x100
01016                    && G_FLD (inst->v, 0, 0) == 0x0)
01017             {
01018               /* addi r0, -offset */
01019               sp_offset += 65536 - G_FLD (inst->v, 16, 1);
01020             }
01021           else if (G_FLD (inst->v, 29, 17) == 0x110
01022                    && G_FLD (inst->v, 0, 0) == 0x0)
01023             {
01024               /* addi r2, offset */
01025               if (pc - cur_pc > 4)
01026                 {
01027                   unsigned int save_v = inst->v;
01028                   inst_t *inst2 =
01029                     score7_fetch_inst (gdbarch, cur_pc + SCORE_INSTLEN, NULL);
01030                   if (inst2->v == 0x23)
01031                     {
01032                       /* mv! r0, r2 */
01033                       sp_offset -= G_FLD (save_v, 16, 1);
01034                     }
01035                 }
01036             }
01037         }
01038     }
01039 
01040   /* Save RA.  */
01041   if (ra_offset_p == 1)
01042     {
01043       if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
01044         this_cache->saved_regs[SCORE_PC_REGNUM].addr =
01045           sp + sp_offset - ra_offset;
01046     }
01047   else
01048     {
01049       this_cache->saved_regs[SCORE_PC_REGNUM] =
01050         this_cache->saved_regs[SCORE_RA_REGNUM];
01051     }
01052 
01053   /* Save FP.  */
01054   if (fp_offset_p == 1)
01055     {
01056       if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
01057         this_cache->saved_regs[SCORE_FP_REGNUM].addr =
01058           sp + sp_offset - fp_offset;
01059     }
01060 
01061   /* Save SP and FP.  */
01062   this_cache->base = sp + sp_offset;
01063   this_cache->fp = fp;
01064 
01065   /* Don't forget to free MEMBLOCK if we allocated it.  */
01066   if (memblock_ptr != NULL)
01067     score7_free_memblock (memblock_ptr);
01068 }
01069 
01070 static void
01071 score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc,
01072                         struct frame_info *this_frame,
01073                         struct score_frame_cache *this_cache)
01074 {
01075   CORE_ADDR sp;
01076   CORE_ADDR fp;
01077   CORE_ADDR cur_pc = startaddr;
01078   enum bfd_endian byte_order
01079     = gdbarch_byte_order (get_frame_arch (this_frame));
01080 
01081   int sp_offset = 0;
01082   int ra_offset = 0;
01083   int fp_offset = 0;
01084   int ra_offset_p = 0;
01085   int fp_offset_p = 0;
01086   int inst_len = 0;
01087 
01088   CORE_ADDR prev_pc = -1;
01089 
01090   sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM);
01091   fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM);
01092 
01093   for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len)
01094     {
01095       inst_t *inst = NULL;
01096 
01097       inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order);
01098 
01099       /* FIXME: make a full-power prologue analyzer.  */
01100       if (inst->len == 2)
01101         {
01102           if (G_FLD (inst->v, 14, 12) == 0x0
01103               && G_FLD (inst->v, 11, 7) == 0x0
01104               && G_FLD (inst->v, 6, 5) == 0x3)
01105             {
01106               /* push! */
01107               sp_offset += 4;
01108 
01109               if (G_FLD (inst->v, 4, 0) == 0x3
01110                   && ra_offset_p == 0)
01111                 {
01112                   /* push! r3, [r0] */
01113                   ra_offset = sp_offset;
01114                   ra_offset_p = 1;
01115                 }
01116               else if (G_FLD (inst->v, 4, 0) == 0x2
01117                        && fp_offset_p == 0)
01118                 {
01119                   /* push! r2, [r0] */
01120                   fp_offset = sp_offset;
01121                   fp_offset_p = 1;
01122                 }
01123             }
01124           else if (G_FLD (inst->v, 14, 12) == 0x6
01125                    && G_FLD (inst->v, 11, 10) == 0x3)
01126             {
01127               /* rpush! */
01128               int start_r = G_FLD (inst->v, 9, 5);
01129               int cnt = G_FLD (inst->v, 4, 0);
01130      
01131               if ((ra_offset_p == 0)
01132                   && (start_r <= SCORE_RA_REGNUM)
01133                   && (SCORE_RA_REGNUM < start_r + cnt))
01134                 {
01135                   /* rpush! contains r3 */
01136                   ra_offset_p = 1;
01137                   ra_offset = sp_offset + 4 * (SCORE_RA_REGNUM - start_r) + 4;
01138                 }
01139 
01140               if ((fp_offset_p == 0)
01141                   && (start_r <= SCORE_FP_REGNUM)
01142                   && (SCORE_FP_REGNUM < start_r + cnt))
01143                 {
01144                   /* rpush! contains r2 */
01145                   fp_offset_p = 1;
01146                   fp_offset = sp_offset + 4 * (SCORE_FP_REGNUM - start_r) + 4;
01147                 }
01148 
01149               sp_offset += 4 * cnt;
01150             }
01151           else if (G_FLD (inst->v, 14, 12) == 0x0
01152                    && G_FLD (inst->v, 11, 7) == 0x0
01153                    && G_FLD (inst->v, 6, 5) == 0x2)
01154             {
01155               /* pop! */
01156               sp_offset -= 4;
01157             }
01158           else if (G_FLD (inst->v, 14, 12) == 0x6
01159                    && G_FLD (inst->v, 11, 10) == 0x2)
01160             {
01161               /* rpop! */
01162               sp_offset -= 4 * G_FLD (inst->v, 4, 0);
01163             }
01164           else if (G_FLD (inst->v, 14, 12) == 0x5
01165                    && G_FLD (inst->v, 11, 10) == 0x3
01166                    && G_FLD (inst->v, 9, 6) == 0x0)
01167             {
01168               /* addi! r0, -offset */
01169               int imm = G_FLD (inst->v, 5, 0);
01170               if (imm >> 5)
01171                 imm = -(0x3F - imm + 1);
01172               sp_offset -= imm;
01173             }
01174           else if (G_FLD (inst->v, 14, 12) == 0x5
01175                    && G_FLD (inst->v, 11, 10) == 0x3
01176                    && G_FLD (inst->v, 9, 6) == 0x2)
01177             {
01178               /* addi! r2, offset */
01179               if (pc - cur_pc >= 2)
01180                 {
01181                   unsigned int save_v = inst->v;
01182                   inst_t *inst2;
01183                   
01184                   cur_pc += inst->len;
01185                   inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL,
01186                                                            byte_order);
01187 
01188                   if (inst2->len == 2
01189                       && G_FLD (inst2->v, 14, 10) == 0x10
01190                       && G_FLD (inst2->v, 9, 5) == 0x0
01191                       && G_FLD (inst2->v, 4, 0) == 0x2)
01192                     {
01193                       /* mv! r0, r2 */
01194                       int imm = G_FLD (inst->v, 5, 0);
01195                       if (imm >> 5)
01196                         imm = -(0x3F - imm + 1);
01197                       sp_offset -= imm;
01198                     }
01199                 }
01200             }
01201         }
01202       else if (inst->len == 4)
01203         {
01204           if (G_FLD (inst->v, 29, 25) == 0x3
01205               && G_FLD (inst->v, 2, 0) == 0x4
01206               && G_FLD (inst->v, 24, 20) == 0x3
01207               && G_FLD (inst->v, 19, 15) == 0x0)
01208             {
01209               /* sw r3, [r0, offset]+ */
01210               sp_offset += inst->len;
01211               if (ra_offset_p == 0)
01212                 {
01213                   ra_offset = sp_offset;
01214                   ra_offset_p = 1;
01215                 }
01216             }
01217           else if (G_FLD (inst->v, 29, 25) == 0x3
01218                    && G_FLD (inst->v, 2, 0) == 0x4
01219                    && G_FLD (inst->v, 24, 20) == 0x2
01220                    && G_FLD (inst->v, 19, 15) == 0x0)
01221             {
01222               /* sw r2, [r0, offset]+ */
01223               sp_offset += inst->len;
01224               if (fp_offset_p == 0)
01225                 {
01226                   fp_offset = sp_offset;
01227                   fp_offset_p = 1;
01228                 }
01229             }
01230           else if (G_FLD (inst->v, 29, 25) == 0x7
01231                    && G_FLD (inst->v, 2, 0) == 0x0
01232                    && G_FLD (inst->v, 24, 20) == 0x3
01233                    && G_FLD (inst->v, 19, 15) == 0x0)
01234             {
01235               /* lw r3, [r0]+, 4 */
01236               sp_offset -= inst->len;
01237               ra_offset_p = 1;
01238             }
01239           else if (G_FLD (inst->v, 29, 25) == 0x7
01240                    && G_FLD (inst->v, 2, 0) == 0x0
01241                    && G_FLD (inst->v, 24, 20) == 0x2
01242                    && G_FLD (inst->v, 19, 15) == 0x0)
01243             {
01244               /* lw r2, [r0]+, 4 */
01245               sp_offset -= inst->len;
01246               fp_offset_p = 1;
01247             }
01248           else if (G_FLD (inst->v, 29, 25) == 0x1
01249                    && G_FLD (inst->v, 19, 17) == 0x0
01250                    && G_FLD (inst->v, 24, 20) == 0x0
01251                    && G_FLD (inst->v, 0, 0) == 0x0)
01252             {
01253               /* addi r0, -offset */
01254               int imm = G_FLD (inst->v, 16, 1);
01255               if (imm >> 15)
01256                 imm = -(0xFFFF - imm + 1);
01257               sp_offset -= imm;
01258             }
01259           else if (G_FLD (inst->v, 29, 25) == 0x1
01260                    && G_FLD (inst->v, 19, 17) == 0x0
01261                    && G_FLD (inst->v, 24, 20) == 0x2
01262                    && G_FLD (inst->v, 0, 0) == 0x0)
01263             {
01264               /* addi r2, offset */
01265               if (pc - cur_pc >= 2)
01266                 {
01267                   unsigned int save_v = inst->v;
01268                   inst_t *inst2;
01269                   
01270                   cur_pc += inst->len;
01271                   inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL,
01272                                                            byte_order);
01273 
01274                   if (inst2->len == 2
01275                       && G_FLD (inst2->v, 14, 10) == 0x10
01276                       && G_FLD (inst2->v, 9, 5) == 0x0
01277                       && G_FLD (inst2->v, 4, 0) == 0x2)
01278                     {
01279                       /* mv! r0, r2 */
01280                       int imm = G_FLD (inst->v, 16, 1);
01281                       if (imm >> 15)
01282                         imm = -(0xFFFF - imm + 1);
01283                       sp_offset -= imm;
01284                     }
01285                 }
01286             }
01287         }
01288     }
01289 
01290   /* Save RA.  */
01291   if (ra_offset_p == 1)
01292     {
01293       if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1)
01294         this_cache->saved_regs[SCORE_PC_REGNUM].addr =
01295           sp + sp_offset - ra_offset;
01296     }
01297   else
01298     {
01299       this_cache->saved_regs[SCORE_PC_REGNUM] =
01300         this_cache->saved_regs[SCORE_RA_REGNUM];
01301     }
01302 
01303   /* Save FP.  */
01304   if (fp_offset_p == 1)
01305     {
01306       if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1)
01307         this_cache->saved_regs[SCORE_FP_REGNUM].addr =
01308           sp + sp_offset - fp_offset;
01309     }
01310 
01311   /* Save SP and FP.  */
01312   this_cache->base = sp + sp_offset;
01313   this_cache->fp = fp;
01314 }
01315 
01316 static struct score_frame_cache *
01317 score_make_prologue_cache (struct frame_info *this_frame, void **this_cache)
01318 {
01319   struct score_frame_cache *cache;
01320 
01321   if ((*this_cache) != NULL)
01322     return (*this_cache);
01323 
01324   cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache);
01325   (*this_cache) = cache;
01326   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
01327 
01328   /* Analyze the prologue.  */
01329   {
01330     const CORE_ADDR pc = get_frame_pc (this_frame);
01331     CORE_ADDR start_addr;
01332 
01333     find_pc_partial_function (pc, NULL, &start_addr, NULL);
01334     if (start_addr == 0)
01335       return cache;
01336 
01337     if (target_mach == bfd_mach_score3)
01338       score3_analyze_prologue (start_addr, pc, this_frame, *this_cache);
01339     else
01340       score7_analyze_prologue (start_addr, pc, this_frame, *this_cache);
01341   }
01342 
01343   /* Save SP.  */
01344   trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base);
01345 
01346   return (*this_cache);
01347 }
01348 
01349 static void
01350 score_prologue_this_id (struct frame_info *this_frame, void **this_cache,
01351                         struct frame_id *this_id)
01352 {
01353   struct score_frame_cache *info = score_make_prologue_cache (this_frame,
01354                                                               this_cache);
01355   (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
01356 }
01357 
01358 static struct value *
01359 score_prologue_prev_register (struct frame_info *this_frame,
01360                               void **this_cache, int regnum)
01361 {
01362   struct score_frame_cache *info = score_make_prologue_cache (this_frame,
01363                                                               this_cache);
01364   return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
01365 }
01366 
01367 static const struct frame_unwind score_prologue_unwind =
01368 {
01369   NORMAL_FRAME,
01370   default_frame_unwind_stop_reason,
01371   score_prologue_this_id,
01372   score_prologue_prev_register,
01373   NULL,
01374   default_frame_sniffer,
01375   NULL
01376 };
01377 
01378 static CORE_ADDR
01379 score_prologue_frame_base_address (struct frame_info *this_frame,
01380                                    void **this_cache)
01381 {
01382   struct score_frame_cache *info =
01383     score_make_prologue_cache (this_frame, this_cache);
01384   return info->fp;
01385 }
01386 
01387 static const struct frame_base score_prologue_frame_base =
01388 {
01389   &score_prologue_unwind,
01390   score_prologue_frame_base_address,
01391   score_prologue_frame_base_address,
01392   score_prologue_frame_base_address,
01393 };
01394 
01395 static const struct frame_base *
01396 score_prologue_frame_base_sniffer (struct frame_info *this_frame)
01397 {
01398   return &score_prologue_frame_base;
01399 }
01400 
01401 /* Core file support (dirty hack)
01402   
01403    The core file MUST be generated by GNU/Linux on S+core.  */
01404 
01405 static void
01406 score7_linux_supply_gregset(const struct regset *regset,
01407                 struct regcache *regcache,
01408                 int regnum, const void *gregs_buf, size_t len)
01409 {
01410   int regno;
01411   elf_gregset_t *gregs;
01412 
01413   gdb_assert (regset != NULL);
01414   gdb_assert ((regcache != NULL) && (gregs_buf != NULL));
01415 
01416   gregs = (elf_gregset_t *) gregs_buf;
01417 
01418   for (regno = 0; regno < 32; regno++)
01419     if (regnum == -1 || regnum == regno)
01420       regcache_raw_supply (regcache, regno, gregs->regs + regno);
01421 
01422   {
01423     struct sreg {
01424       int regnum;
01425       void *buf;
01426     } sregs [] = {
01427       { 55, &(gregs->cel) },  /* CEL */
01428       { 54, &(gregs->ceh) },  /* CEH */
01429       { 53, &(gregs->sr0) },  /* sr0, i.e. cnt or COUNTER */
01430       { 52, &(gregs->sr1) },  /* sr1, i.e. lcr or LDCR */
01431       { 51, &(gregs->sr1) },  /* sr2, i.e. scr or STCR */
01432 
01433       /* Exception occured at this address, exactly the PC we want */
01434       { 49, &(gregs->cp0_epc) }, /* PC */
01435 
01436       { 38, &(gregs->cp0_ema) }, /* EMA */
01437       { 37, &(gregs->cp0_epc) }, /* EPC */
01438       { 34, &(gregs->cp0_ecr) }, /* ECR */
01439       { 33, &(gregs->cp0_condition) }, /* COND */
01440       { 32, &(gregs->cp0_psr) }, /* PSR */
01441     };
01442 
01443     for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++)
01444       if (regnum == -1 || regnum == sregs[regno].regnum)
01445         regcache_raw_supply (regcache,
01446                              sregs[regno].regnum, sregs[regno].buf);
01447   }
01448 }
01449 
01450 /* Return the appropriate register set from the core section identified
01451    by SECT_NAME and SECT_SIZE.  */
01452 
01453 static const struct regset *
01454 score7_linux_regset_from_core_section(struct gdbarch *gdbarch,
01455                     const char *sect_name, size_t sect_size)
01456 {
01457   struct gdbarch_tdep *tdep;
01458 
01459   gdb_assert (gdbarch != NULL);
01460   gdb_assert (sect_name != NULL);
01461 
01462   tdep = gdbarch_tdep (gdbarch);
01463 
01464   if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t))
01465     {
01466       if (tdep->gregset == NULL)
01467         tdep->gregset = regset_alloc (gdbarch,
01468                                       score7_linux_supply_gregset, NULL);
01469       return tdep->gregset;
01470     }
01471 
01472   return NULL;
01473 }
01474 
01475 static struct gdbarch *
01476 score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
01477 {
01478   struct gdbarch *gdbarch;
01479   struct gdbarch_tdep *tdep;
01480   target_mach = info.bfd_arch_info->mach;
01481 
01482   arches = gdbarch_list_lookup_by_info (arches, &info);
01483   if (arches != NULL)
01484     {
01485       return (arches->gdbarch);
01486     }
01487   tdep = xcalloc(1, sizeof(struct gdbarch_tdep));
01488   gdbarch = gdbarch_alloc (&info, tdep);
01489 
01490   set_gdbarch_short_bit (gdbarch, 16);
01491   set_gdbarch_int_bit (gdbarch, 32);
01492   set_gdbarch_float_bit (gdbarch, 32);
01493   set_gdbarch_double_bit (gdbarch, 64);
01494   set_gdbarch_long_double_bit (gdbarch, 64);
01495 #if WITH_SIM
01496   set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno);
01497 #endif
01498   set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM);
01499   set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM);
01500   set_gdbarch_adjust_breakpoint_address (gdbarch,
01501                                          score_adjust_breakpoint_address);
01502   set_gdbarch_register_type (gdbarch, score_register_type);
01503   set_gdbarch_frame_align (gdbarch, score_frame_align);
01504   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
01505   set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
01506   set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
01507   set_gdbarch_print_insn (gdbarch, score_print_insn);
01508 
01509   switch (target_mach)
01510     {
01511     case bfd_mach_score7:
01512       set_gdbarch_breakpoint_from_pc (gdbarch, score7_breakpoint_from_pc);
01513       set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue);
01514       set_gdbarch_in_function_epilogue_p (gdbarch,
01515                                           score7_in_function_epilogue_p);
01516       set_gdbarch_register_name (gdbarch, score7_register_name);
01517       set_gdbarch_num_regs (gdbarch, SCORE7_NUM_REGS);
01518       /* Core file support.  */
01519       set_gdbarch_regset_from_core_section (gdbarch,
01520                                             score7_linux_regset_from_core_section);
01521       break;
01522 
01523     case bfd_mach_score3:
01524       set_gdbarch_breakpoint_from_pc (gdbarch, score3_breakpoint_from_pc);
01525       set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue);
01526       set_gdbarch_in_function_epilogue_p (gdbarch,
01527                                           score3_in_function_epilogue_p);
01528       set_gdbarch_register_name (gdbarch, score3_register_name);
01529       set_gdbarch_num_regs (gdbarch, SCORE3_NUM_REGS);
01530       break;
01531     }
01532 
01533   /* Watchpoint hooks.  */
01534   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
01535 
01536   /* Dummy frame hooks.  */
01537   set_gdbarch_return_value (gdbarch, score_return_value);
01538   set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
01539   set_gdbarch_dummy_id (gdbarch, score_dummy_id);
01540   set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call);
01541 
01542   /* Normal frame hooks.  */
01543   dwarf2_append_unwinders (gdbarch);
01544   frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
01545   frame_unwind_append_unwinder (gdbarch, &score_prologue_unwind);
01546   frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer);
01547 
01548   return gdbarch;
01549 }
01550 
01551 extern initialize_file_ftype _initialize_score_tdep;
01552 
01553 void
01554 _initialize_score_tdep (void)
01555 {
01556   gdbarch_register (bfd_arch_score, score_gdbarch_init, NULL);
01557 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines